From 26c701f802051559d6388dc7ecdeaf08d48adfab Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 17 Oct 2025 11:21:50 -0600 Subject: [PATCH] Two bug fixes in mdict_free A heap-allocated multidictionary should be freed by calling mdict_free. However, while this function does free the contents of the dictionary, it neglects to free the dictionary itself. There's also a second bug, which is that if a multidictionary is created with no dictionaries, gdb will crash on the first line of mdict_free: enum dict_type type = mdict->dictionaries[0]->vector->type; So, this patch also adds the type to struct multidictionary, avoiding this problem. Note that this does not increase the structure size on x86-64, because the new member fits into the padding. Approved-By: Simon Marchi --- gdb/dictionary.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/gdb/dictionary.c b/gdb/dictionary.c index f435ad5a47e..ca0d4b5298a 100644 --- a/gdb/dictionary.c +++ b/gdb/dictionary.c @@ -911,6 +911,9 @@ struct multidictionary /* The number of language dictionaries currently allocated. Only used for expandable dictionaries. */ unsigned short n_allocated_dictionaries; + + /* The type of dictionary. */ + enum dict_type type; }; /* A helper function to collate symbols on the pending list by language. */ @@ -948,6 +951,7 @@ mdict_create_hashed (struct obstack *obstack, retval->dictionaries = XOBNEWVEC (obstack, struct dictionary *, nsyms.size ()); retval->n_allocated_dictionaries = nsyms.size (); + retval->type = DICT_HASHED; int idx = 0; for (const auto &[language, symlist] : nsyms) @@ -969,6 +973,7 @@ mdict_create_hashed_expandable (enum language language) retval->n_allocated_dictionaries = 1; retval->dictionaries = XNEW (struct dictionary *); retval->dictionaries[0] = dict_create_hashed_expandable (language); + retval->type = DICT_HASHED_EXPANDABLE; return retval; } @@ -988,6 +993,7 @@ mdict_create_linear (struct obstack *obstack, retval->dictionaries = XOBNEWVEC (obstack, struct dictionary *, nsyms.size ()); retval->n_allocated_dictionaries = nsyms.size (); + retval->type = DICT_LINEAR; int idx = 0; for (const auto &[language, symlist] : nsyms) @@ -1009,6 +1015,7 @@ mdict_create_linear_expandable (enum language language) retval->n_allocated_dictionaries = 1; retval->dictionaries = XNEW (struct dictionary *); retval->dictionaries[0] = dict_create_linear_expandable (language); + retval->type = DICT_LINEAR_EXPANDABLE; return retval; } @@ -1018,15 +1025,12 @@ mdict_create_linear_expandable (enum language language) void mdict_free (struct multidictionary *mdict) { - /* Grab the type of dictionary being used. */ - enum dict_type type = mdict->dictionaries[0]->vector->type; - /* Loop over all dictionaries and free them. */ for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx) dict_free (mdict->dictionaries[idx]); /* Free the dictionary list, if needed. */ - switch (type) + switch (mdict->type) { case DICT_HASHED: case DICT_LINEAR: @@ -1036,6 +1040,7 @@ mdict_free (struct multidictionary *mdict) case DICT_HASHED_EXPANDABLE: case DICT_LINEAR_EXPANDABLE: xfree (mdict->dictionaries); + xfree (mdict); break; } } @@ -1067,10 +1072,7 @@ create_new_language_dictionary (struct multidictionary *mdict, { struct dictionary *retval = nullptr; - /* We use the first dictionary entry to decide what create function - to call. Not optimal but sufficient. */ - gdb_assert (mdict->dictionaries[0] != nullptr); - switch (mdict->dictionaries[0]->vector->type) + switch (mdict->type) { case DICT_HASHED: case DICT_LINEAR: