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.
This commit is contained in:
Ray Chason
2022-11-23 12:05:04 -08:00
committed by PatR
parent 5181c287d3
commit 913a7dc0e0
+45 -12
View File
@@ -7,6 +7,7 @@
static void savedsym_add(const char *, const char *, int); static void savedsym_add(const char *, const char *, int);
static struct _savedsym *savedsym_find(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 */ 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); enum graphics_sets which_set);
struct customization_detail *find_display_urep_customization( struct customization_detail *find_display_urep_customization(
const char *customization_name, int glyphidx, enum graphics_sets which_set); 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]; extern glyph_map glyphmap[MAX_GLYPH];
static void shuffle_customizations(void); static void shuffle_customizations(void);
@@ -1090,18 +1090,51 @@ apply_customizations_to_symset(enum graphics_sets which_set)
static void static void
shuffle_customizations(void) shuffle_customizations(void)
{ {
int i; static const int offsets[2] = { GLYPH_OBJ_OFF, GLYPH_OBJ_PILETOP_OFF };
struct unicode_representation *tmp_u[2][NUM_OBJECTS]; int j;
for (i = 0; i < NUM_OBJECTS; i++) { for (j = 0; j < SIZE(offsets); j++) {
tmp_u[0][i] = glyph_map *obj_glyphs = glyphmap + offsets[j];
glyphmap[objects[i].oc_descr_idx + GLYPH_OBJ_OFF].u; int i;
tmp_u[1][i] = struct unicode_representation *tmp_u[NUM_OBJECTS];
glyphmap[objects[i].oc_descr_idx + GLYPH_OBJ_PILETOP_OFF].u; int duplicate[NUM_OBJECTS];
}
for (i = 0; i < NUM_OBJECTS; i++) { for (i = 0; i < NUM_OBJECTS; i++) {
glyphmap[i + GLYPH_OBJ_OFF].u = tmp_u[0][i]; duplicate[i] = -1;
glyphmap[i + GLYPH_OBJ_PILETOP_OFF].u = tmp_u[1][i]; }
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];
}
} }
} }