From 5181c287d3c419b553ca025199b36094131d91ca Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Sun, 6 Nov 2022 21:51:19 -0500 Subject: [PATCH 1/3] Parse only Unicode symbols in the current symset --- src/symbols.c | 20 +++++++++++++++----- src/utf8map.c | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/symbols.c b/src/symbols.c index 0b517addd..29ddf9f7c 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -332,6 +332,10 @@ clear_symsetentry(int which_set, boolean name_too) free((genericptr_t) g.symset[which_set].name); g.symset[which_set].name = (char *) 0; } +#ifdef ENHANCED_SYMBOLS + free_all_glyphmap_u(); + purge_custom_entries(which_set); +#endif } boolean symset_is_compatible(enum symset_handling_types handling, unsigned long wincap2) @@ -462,7 +466,11 @@ parse_sym_line(char *buf, int which_set) symp = match_sym(buf); if (!symp && buf[0] == 'G' && buf[1] == '_') { #ifdef ENHANCED_SYMBOLS - is_glyph = match_glyph(buf); + if (g.chosen_symset_start) { + is_glyph = match_glyph(buf); + } else { + is_glyph = TRUE; /* report error only once */ + } #else enhanced_unavailable = TRUE; #endif @@ -608,7 +616,9 @@ parse_sym_line(char *buf, int which_set) } #ifdef ENHANCED_SYMBOLS } else { - glyphrep_to_custom_map_entries(buf, &glyph); + if (g.chosen_symset_start) { + glyphrep_to_custom_map_entries(buf, &glyph); + } #endif } } @@ -1058,11 +1068,11 @@ apply_customizations_to_symset(enum graphics_sets which_set) struct customization_detail *details; if (g.symset[which_set].handling == H_UTF8 - && g.sym_customizations[UNICODESET].count - && g.sym_customizations[UNICODESET].details) { + && g.sym_customizations[which_set].count + && g.sym_customizations[which_set].details) { /* These UTF-8 customizations get applied to the glyphmap array, not to symset entries */ - details = g.sym_customizations[UNICODESET].details; + details = g.sym_customizations[which_set].details; while (details) { gm = &glyphmap[details->content.urep.glyphidx]; (void) set_map_u(gm, diff --git a/src/utf8map.c b/src/utf8map.c index fbffe18b7..35e390fbb 100644 --- a/src/utf8map.c +++ b/src/utf8map.c @@ -65,7 +65,7 @@ to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat) (findwhat->color != 0L) ? findwhat->color : 0L); #endif add_custom_urep_entry(known_handling[H_UTF8], glyph, - uval, utf8str, findwhat->color, UNICODESET); + uval, utf8str, findwhat->color, g.symset_which_set); } } From 913a7dc0e0583adcb1210ee76c1cdde0aac48fe2 Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Tue, 8 Nov 2022 23:41:40 -0500 Subject: [PATCH 2/3] Fix use after free in Unicode mappings Shuffling gem appearances can cause mappings from object to appearance that are not one-to-one. Copy any multiple mappings and free any mappings that are left unused. --- src/symbols.c | 57 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/src/symbols.c b/src/symbols.c index 29ddf9f7c..5117b4ac5 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -7,6 +7,7 @@ static void savedsym_add(const char *, const char *, int); static struct _savedsym *savedsym_find(const char *, int); +void purge_custom_entries(enum graphics_sets which_set); extern const uchar def_r_oc_syms[MAXOCLASSES]; /* drawing.c */ @@ -1057,7 +1058,6 @@ struct customization_detail *find_matching_symset_customization( enum graphics_sets which_set); struct customization_detail *find_display_urep_customization( const char *customization_name, int glyphidx, enum graphics_sets which_set); -void purge_custom_entries(enum graphics_sets which_set); extern glyph_map glyphmap[MAX_GLYPH]; static void shuffle_customizations(void); @@ -1090,18 +1090,51 @@ apply_customizations_to_symset(enum graphics_sets which_set) static void shuffle_customizations(void) { - int i; - struct unicode_representation *tmp_u[2][NUM_OBJECTS]; + static const int offsets[2] = { GLYPH_OBJ_OFF, GLYPH_OBJ_PILETOP_OFF }; + int j; - for (i = 0; i < NUM_OBJECTS; i++) { - tmp_u[0][i] = - glyphmap[objects[i].oc_descr_idx + GLYPH_OBJ_OFF].u; - tmp_u[1][i] = - glyphmap[objects[i].oc_descr_idx + GLYPH_OBJ_PILETOP_OFF].u; - } - for (i = 0; i < NUM_OBJECTS; i++) { - glyphmap[i + GLYPH_OBJ_OFF].u = tmp_u[0][i]; - glyphmap[i + GLYPH_OBJ_PILETOP_OFF].u = tmp_u[1][i]; + for (j = 0; j < SIZE(offsets); j++) { + glyph_map *obj_glyphs = glyphmap + offsets[j]; + int i; + struct unicode_representation *tmp_u[NUM_OBJECTS]; + int duplicate[NUM_OBJECTS]; + + for (i = 0; i < NUM_OBJECTS; i++) { + duplicate[i] = -1; + } + for (i = 0; i < NUM_OBJECTS; i++) { + int idx = objects[i].oc_descr_idx; + + /* + * Shuffling gem appearances can cause the same oc_descr_idx to + * appear more than once. Detect this condition and ensure that + * each pointer points to a unique allocation. + */ + if (duplicate[idx] >= 0) { + /* Current structure already appears in tmp_u */ + struct unicode_representation *other = tmp_u[duplicate[idx]]; + + tmp_u[i] = (struct unicode_representation *) alloc(sizeof *tmp_u[i]); + *tmp_u[i] = *other; + if (other->utf8str != NULL) { + tmp_u[i]->utf8str = (uint8 *) dupstr((const char *) other->utf8str); + } + } else { + tmp_u[i] = obj_glyphs[idx].u; + if (obj_glyphs[idx].u != NULL) { + duplicate[idx] = i; + obj_glyphs[idx].u = NULL; + } + } + } + for (i = 0; i < NUM_OBJECTS; i++) { + /* Some glyphmaps may not have been transferred */ + if (obj_glyphs[i].u != NULL) { + free(obj_glyphs[i].u->utf8str); + free(obj_glyphs[i].u); + } + obj_glyphs[i].u = tmp_u[i]; + } } } From 5a80a437a2c1b580137d9210179d85e6b47adbe6 Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Sat, 12 Nov 2022 08:04:52 -0500 Subject: [PATCH 3/3] Free the whole list when freeing --- src/symbols.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/symbols.c b/src/symbols.c index 5117b4ac5..6867bb425 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -1155,7 +1155,7 @@ purge_custom_entries(enum graphics_sets which_set) { struct symset_customization *gdc = &g.sym_customizations[which_set]; struct customization_detail *details = gdc->details, *next; - if (details) { + while (details) { next = details->next; if (gdc->custtype == custom_ureps) { if (details->content.urep.u.utf8str)