@@ -29,41 +29,64 @@ typedef struct {
2929 char * data ;
3030 size_t len ;
3131 size_t cap ;
32+ bool oom ;
3233} strbuf_t ;
3334
3435static void strbuf_init (strbuf_t * buf ) {
3536 buf -> data = malloc (256 );
3637 buf -> len = 0 ;
3738 buf -> cap = 256 ;
38- if (buf -> data ) buf -> data [0 ] = '\0' ;
39+ buf -> oom = (buf -> data == NULL );
40+ if (buf -> data ) {
41+ buf -> data [0 ] = '\0' ;
42+ } else {
43+ buf -> cap = 0 ;
44+ }
3945}
4046
41- static void strbuf_grow (strbuf_t * buf , size_t need ) {
42- if (buf -> len + need >= buf -> cap ) {
43- size_t new_cap = buf -> cap * 2 ;
44- while (buf -> len + need >= new_cap ) new_cap *= 2 ;
45- char * new_data = realloc (buf -> data , new_cap );
46- if (new_data ) {
47- buf -> data = new_data ;
48- buf -> cap = new_cap ;
47+ static bool strbuf_grow (strbuf_t * buf , size_t need ) {
48+ if (buf -> oom ) return false;
49+ if (buf -> len + need < buf -> cap ) return true;
50+
51+ size_t new_cap = buf -> cap ? buf -> cap : 1 ;
52+ while (buf -> len + need >= new_cap ) {
53+ if (new_cap > SIZE_MAX / 2 ) {
54+ buf -> oom = true;
55+ return false;
4956 }
57+ new_cap *= 2 ;
5058 }
59+
60+ char * new_data = realloc (buf -> data , new_cap );
61+ if (!new_data ) {
62+ buf -> oom = true;
63+ return false;
64+ }
65+ buf -> data = new_data ;
66+ buf -> cap = new_cap ;
67+ return true;
5168}
5269
5370static void strbuf_append (strbuf_t * buf , const char * s ) {
71+ if (!s ) return ;
5472 size_t len = strlen (s );
55- strbuf_grow (buf , len + 1 );
73+ if (! strbuf_grow (buf , len + 1 )) return ;
5674 memcpy (buf -> data + buf -> len , s , len + 1 );
5775 buf -> len += len ;
5876}
5977
6078static void strbuf_append_char (strbuf_t * buf , char c ) {
61- strbuf_grow (buf , 2 );
79+ if (! strbuf_grow (buf , 2 )) return ;
6280 buf -> data [buf -> len ++ ] = c ;
6381 buf -> data [buf -> len ] = '\0' ;
6482}
6583
6684static char * strbuf_finish (strbuf_t * buf ) {
85+ if (buf -> oom ) {
86+ free (buf -> data );
87+ buf -> data = NULL ;
88+ return NULL ;
89+ }
6790 return buf -> data ;
6891}
6992
@@ -109,16 +132,29 @@ glyph_value_t *glyph_str(const char *val) {
109132 if (v ) {
110133 v -> type = GLYPH_STR ;
111134 v -> str_val = strdup_safe (val );
135+ if (val && !v -> str_val ) {
136+ free (v );
137+ return NULL ;
138+ }
112139 }
113140 return v ;
114141}
115142
116143glyph_value_t * glyph_bytes (const uint8_t * data , size_t len ) {
144+ if (len > 0 && !data ) return NULL ;
145+
117146 glyph_value_t * v = calloc (1 , sizeof (glyph_value_t ));
118147 if (v ) {
119148 v -> type = GLYPH_BYTES ;
120- v -> bytes_val .data = malloc (len );
121- if (v -> bytes_val .data ) {
149+ if (len == 0 ) {
150+ v -> bytes_val .data = NULL ;
151+ v -> bytes_val .len = 0 ;
152+ } else {
153+ v -> bytes_val .data = malloc (len );
154+ if (!v -> bytes_val .data ) {
155+ free (v );
156+ return NULL ;
157+ }
122158 memcpy (v -> bytes_val .data , data , len );
123159 v -> bytes_val .len = len ;
124160 }
@@ -132,6 +168,12 @@ glyph_value_t *glyph_id(const char *prefix, const char *value) {
132168 v -> type = GLYPH_ID ;
133169 v -> id_val .prefix = strdup_safe (prefix ? prefix : "" );
134170 v -> id_val .value = strdup_safe (value );
171+ if (!v -> id_val .prefix || (value && !v -> id_val .value )) {
172+ free (v -> id_val .prefix );
173+ free (v -> id_val .value );
174+ free (v );
175+ return NULL ;
176+ }
135177 }
136178 return v ;
137179}
@@ -152,11 +194,13 @@ void glyph_list_append(glyph_value_t *list, glyph_value_t *item) {
152194 size_t new_count = list -> list_val .count + 1 ;
153195 glyph_value_t * * new_items = realloc (list -> list_val .items ,
154196 new_count * sizeof (glyph_value_t * ));
155- if (new_items ) {
156- new_items [list -> list_val .count ] = item ;
157- list -> list_val .items = new_items ;
158- list -> list_val .count = new_count ;
197+ if (!new_items ) {
198+ glyph_value_free (item );
199+ return ;
159200 }
201+ new_items [list -> list_val .count ] = item ;
202+ list -> list_val .items = new_items ;
203+ list -> list_val .count = new_count ;
160204}
161205
162206glyph_value_t * glyph_map_new (void ) {
@@ -172,22 +216,35 @@ glyph_value_t *glyph_map_new(void) {
172216void glyph_map_set (glyph_value_t * map , const char * key , glyph_value_t * value ) {
173217 if (!map || map -> type != GLYPH_MAP || !key || !value ) return ;
174218
219+ char * key_copy = strdup_safe (key );
220+ if (!key_copy ) {
221+ glyph_value_free (value );
222+ return ;
223+ }
224+
175225 size_t new_count = map -> map_val .count + 1 ;
176226 glyph_map_entry_t * new_entries = realloc (map -> map_val .entries ,
177227 new_count * sizeof (glyph_map_entry_t ));
178- if (new_entries ) {
179- new_entries [map -> map_val .count ].key = strdup_safe (key );
180- new_entries [map -> map_val .count ].value = value ;
181- map -> map_val .entries = new_entries ;
182- map -> map_val .count = new_count ;
228+ if (!new_entries ) {
229+ free (key_copy );
230+ glyph_value_free (value );
231+ return ;
183232 }
233+ new_entries [map -> map_val .count ].key = key_copy ;
234+ new_entries [map -> map_val .count ].value = value ;
235+ map -> map_val .entries = new_entries ;
236+ map -> map_val .count = new_count ;
184237}
185238
186239glyph_value_t * glyph_struct_new (const char * type_name ) {
187240 glyph_value_t * v = calloc (1 , sizeof (glyph_value_t ));
188241 if (v ) {
189242 v -> type = GLYPH_STRUCT ;
190243 v -> struct_val .type_name = strdup_safe (type_name );
244+ if (type_name && !v -> struct_val .type_name ) {
245+ free (v );
246+ return NULL ;
247+ }
191248 v -> struct_val .fields = NULL ;
192249 v -> struct_val .fields_count = 0 ;
193250 }
@@ -197,15 +254,24 @@ glyph_value_t *glyph_struct_new(const char *type_name) {
197254void glyph_struct_set (glyph_value_t * s , const char * key , glyph_value_t * value ) {
198255 if (!s || s -> type != GLYPH_STRUCT || !key || !value ) return ;
199256
257+ char * key_copy = strdup_safe (key );
258+ if (!key_copy ) {
259+ glyph_value_free (value );
260+ return ;
261+ }
262+
200263 size_t new_count = s -> struct_val .fields_count + 1 ;
201264 glyph_map_entry_t * new_fields = realloc (s -> struct_val .fields ,
202265 new_count * sizeof (glyph_map_entry_t ));
203- if (new_fields ) {
204- new_fields [s -> struct_val .fields_count ].key = strdup_safe (key );
205- new_fields [s -> struct_val .fields_count ].value = value ;
206- s -> struct_val .fields = new_fields ;
207- s -> struct_val .fields_count = new_count ;
266+ if (!new_fields ) {
267+ free (key_copy );
268+ glyph_value_free (value );
269+ return ;
208270 }
271+ new_fields [s -> struct_val .fields_count ].key = key_copy ;
272+ new_fields [s -> struct_val .fields_count ].value = value ;
273+ s -> struct_val .fields = new_fields ;
274+ s -> struct_val .fields_count = new_count ;
209275}
210276
211277glyph_value_t * glyph_sum (const char * tag , glyph_value_t * value ) {
@@ -214,6 +280,11 @@ glyph_value_t *glyph_sum(const char *tag, glyph_value_t *value) {
214280 v -> type = GLYPH_SUM ;
215281 v -> sum_val .tag = strdup_safe (tag );
216282 v -> sum_val .value = value ;
283+ if (tag && !v -> sum_val .tag ) {
284+ glyph_value_free (value );
285+ free (v );
286+ return NULL ;
287+ }
217288 }
218289 return v ;
219290}
@@ -382,11 +453,17 @@ static void write_canon_value(strbuf_t *buf, const glyph_value_t *v,
382453
383454/* Compare entries by canonical key for sorting */
384455static int compare_entries (const void * a , const void * b ) {
385- const glyph_map_entry_t * ea = a ;
386- const glyph_map_entry_t * eb = b ;
456+ const glyph_map_entry_t * ea = ( const glyph_map_entry_t * ) a ;
457+ const glyph_map_entry_t * eb = ( const glyph_map_entry_t * ) b ;
387458 return strcmp (ea -> key , eb -> key );
388459}
389460
461+ static int compare_key_strings (const void * a , const void * b ) {
462+ const char * const * ka = (const char * const * )a ;
463+ const char * const * kb = (const char * const * )b ;
464+ return strcmp (* ka , * kb );
465+ }
466+
390467static void write_canon_map (strbuf_t * buf , const glyph_map_entry_t * entries ,
391468 size_t count , const glyph_canon_opts_t * opts ) {
392469 strbuf_append_char (buf , '{' );
@@ -422,6 +499,7 @@ static bool check_homogeneous(glyph_value_t **items, size_t count,
422499 /* Collect all keys */
423500 size_t all_keys_cap = 64 ;
424501 char * * all_keys = malloc (all_keys_cap * sizeof (char * ));
502+ if (!all_keys ) return false;
425503 size_t all_keys_count = 0 ;
426504
427505 for (size_t i = 0 ; i < count ; i ++ ) {
@@ -452,9 +530,21 @@ static bool check_homogeneous(glyph_value_t **items, size_t count,
452530 if (!found ) {
453531 if (all_keys_count >= all_keys_cap ) {
454532 all_keys_cap *= 2 ;
455- all_keys = realloc (all_keys , all_keys_cap * sizeof (char * ));
533+ char * * new_all_keys = realloc (all_keys , all_keys_cap * sizeof (char * ));
534+ if (!new_all_keys ) {
535+ for (size_t m = 0 ; m < all_keys_count ; m ++ ) free (all_keys [m ]);
536+ free (all_keys );
537+ return false;
538+ }
539+ all_keys = new_all_keys ;
540+ }
541+ all_keys [all_keys_count ] = strdup_safe (key );
542+ if (!all_keys [all_keys_count ]) {
543+ for (size_t m = 0 ; m < all_keys_count ; m ++ ) free (all_keys [m ]);
544+ free (all_keys );
545+ return false;
456546 }
457- all_keys [ all_keys_count ++ ] = strdup_safe ( key ) ;
547+ all_keys_count ++ ;
458548 }
459549 }
460550 }
@@ -503,8 +593,7 @@ static bool check_homogeneous(glyph_value_t **items, size_t count,
503593 }
504594
505595 /* Sort columns */
506- qsort (all_keys , all_keys_count , sizeof (char * ),
507- (int (* )(const void * , const void * ))strcmp );
596+ qsort (all_keys , all_keys_count , sizeof (char * ), compare_key_strings );
508597
509598 * out_cols = all_keys ;
510599 * out_col_count = all_keys_count ;
@@ -717,7 +806,12 @@ char *glyph_canonicalize_loose_no_tabular(const glyph_value_t *v) {
717806char * glyph_canonicalize_loose_with_opts (const glyph_value_t * v ,
718807 const glyph_canon_opts_t * opts ) {
719808 strbuf_t buf ;
809+ glyph_canon_opts_t default_opts ;
720810 strbuf_init (& buf );
811+ if (!opts ) {
812+ default_opts = glyph_canon_opts_default ();
813+ opts = & default_opts ;
814+ }
721815 write_canon_value (& buf , v , opts );
722816 return strbuf_finish (& buf );
723817}
0 commit comments