]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Call dict->proto->free() if we called dict->proto->init()
authorAlan T. DeKok <aland@freeradius.org>
Tue, 30 Jan 2024 14:47:53 +0000 (09:47 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 30 Jan 2024 14:47:53 +0000 (09:47 -0500)
With some complete magic

src/lib/util/dict_fixup.c
src/lib/util/dict_priv.h
src/lib/util/dict_util.c

index 6242106d26ca67b11a5ecc3039c726bfaf1d4fe6..4338379333d8221fa7b476a14b987aa5c463fccd 100644 (file)
@@ -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.
index 6a8801c9a75a77ad3e88b4caa99acba030a061b0..d204f0a2fccc3c6c2486fea3cb3c9065752c66ed 100644 (file)
@@ -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.
 
index 3927343917891c68973805321f33a52ae89f4b3c..e6c861a4a836baa07a8a9ede2f281c0118dac113 100644 (file)
@@ -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;