From: Alan T. DeKok Date: Tue, 30 Jan 2024 14:47:53 +0000 (-0500) Subject: Call dict->proto->free() if we called dict->proto->init() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1bd7fc5b736b7b778732c792aeb88d855a11156a;p=thirdparty%2Ffreeradius-server.git Call dict->proto->free() if we called dict->proto->init() With some complete magic --- diff --git a/src/lib/util/dict_fixup.c b/src/lib/util/dict_fixup.c index 6242106d26c..4338379333d 100644 --- a/src/lib/util/dict_fixup.c +++ b/src/lib/util/dict_fixup.c @@ -281,7 +281,19 @@ static fr_dict_attr_t const *dict_find_or_load_reference(fr_dict_t **dict_def, c return NULL; } - if (dict->proto && dict->proto->init && (dict->proto->init() < 0)) return NULL; + /* + * If we call init(), make sure that we call free(); + */ + if (dict->proto && dict->proto->init) { + if (dict->proto->init() < 0) return NULL; + + /* + * Mark the *referencing* dictionary as autofree. + * + * Changing this to dict->autofree=true will break things. :( + */ + (*dict_def)->autofree = true; + } /* * The reference is to the root of the foreign protocol, we're done. diff --git a/src/lib/util/dict_priv.h b/src/lib/util/dict_priv.h index 6a8801c9a75..d204f0a2fcc 100644 --- a/src/lib/util/dict_priv.h +++ b/src/lib/util/dict_priv.h @@ -84,6 +84,8 @@ struct fr_dict { bool string_based; //!< TACACS, etc. + bool autofree; //!< from dict_fixup. + fr_hash_table_t *vendors_by_name; //!< Lookup vendor by name. fr_hash_table_t *vendors_by_num; //!< Lookup vendor by PEN. diff --git a/src/lib/util/dict_util.c b/src/lib/util/dict_util.c index 39273439178..e6c861a4a83 100644 --- a/src/lib/util/dict_util.c +++ b/src/lib/util/dict_util.c @@ -3344,6 +3344,15 @@ static int _dict_free(fr_dict_t *dict) } #endif + /* + * If we called init(), then call free() + */ + if (dict->autofree) { + fr_assert(dict->proto); + fr_assert(dict->proto->free); + dict->proto->free(); + } + if (!fr_cond_assert(!dict->in_protocol_by_name || fr_hash_table_delete(dict->gctx->protocol_by_name, dict))) { fr_strerror_printf("Failed removing dictionary from protocol hash \"%s\"", dict->root->name); return -1;