]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add finalisation safety checks
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 11 Nov 2024 23:17:33 +0000 (17:17 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 11 Nov 2024 23:17:33 +0000 (17:17 -0600)
src/lib/util/dict.h
src/lib/util/dict_util.c

index c6e9e2ab6a1ee8437a5b95b5b029df6d3a084466..4a6c6989443e9b12c2ff42c9c0a9c1bbf3dd6b38 100644 (file)
@@ -191,11 +191,17 @@ struct dict_attr_s {
 
        fr_dict_attr_flags_t    flags;                          //!< Flags.
 
-       bool                    attr_set:1;                     //!< Attribute number has been set.
+       struct {
+               bool                    attr_set : 1;           //!< Attribute number has been set.
                                                                //!< We need the full range of values 0-UINT32_MAX
                                                                ///< so we can't use any attr values to indicate
                                                                ///< "unsetness".
 
+               bool                    finalised : 1;          //!< Attribute definition is complete and modifications
+                                                               ///< that would change the address of the memory chunk
+                                                               ///< of the attribute are no longer permitted.
+       } state;
+
        char const              *filename;                      //!< Where the attribute was defined.
                                                                ///< this buffer's lifetime is bound to the
                                                                ///< fr_dict_t.
index cc3551b2c3d5c4ce3bb7273845f82fae72955bfd..00af217a452f856a673154a00a3f2ec71817e471 100644 (file)
@@ -523,6 +523,11 @@ int dict_attr_type_init(fr_dict_attr_t **da_p, fr_type_t type)
                return -1;
        }
 
+       if (unlikely((*da_p)->state.finalised == true)) {
+               fr_strerror_const("Can't perform type initialisation on finalised attribute");
+               return -1;
+       }
+
        /*
         *      Structural types can have children
         *      so add the extension for them.
@@ -601,6 +606,7 @@ int dict_attr_parent_init(fr_dict_attr_t **da_p, fr_dict_attr_t const *parent)
 {
        fr_dict_attr_t *da = *da_p;
 
+
        if (unlikely((*da_p)->type == FR_TYPE_NULL)) {
                fr_strerror_const("Attribute type must be set before initialising parent.  Use dict_attr_type_init() first");
                return -1;
@@ -611,6 +617,13 @@ int dict_attr_parent_init(fr_dict_attr_t **da_p, fr_dict_attr_t const *parent)
                                   da->name, parent->name, da->parent->name);
                return -1;
        }
+
+       if (unlikely((*da_p)->state.finalised == true)) {
+               fr_strerror_printf("Attempting to set parent for '%s' to '%s', but attribute already finalised",
+                                  da->name, parent->name);
+               return -1;
+       }
+
        da->parent = parent;
        da->dict = parent->dict;
        da->depth = parent->depth + 1;
@@ -643,12 +656,12 @@ int dict_attr_parent_init(fr_dict_attr_t **da_p, fr_dict_attr_t const *parent)
  */
 int dict_attr_num_init(fr_dict_attr_t *da, unsigned int num)
 {
-       if (da->attr_set) {
+       if (da->state.attr_set) {
                fr_strerror_const("Attribute number already set");
                return -1;
        }
        da->attr = num;
-       da->attr_set = true;
+       da->state.attr_set = true;
 
        return 0;
 }
@@ -750,6 +763,8 @@ int dict_attr_finalise(fr_dict_attr_t **da_p, char const *name)
 
        DA_VERIFY(*da_p);
 
+       (*da_p)->state.finalised = true;
+
        return 0;
 }
 
@@ -1573,6 +1588,11 @@ int fr_dict_attr_add_initialised(fr_dict_attr_t *da)
                return -1;
        }
 
+       if (unlikely(da->state.finalised == false)) {
+               fr_strerror_const("Attribute has not been finalised");
+               return -1;
+       }
+
        /*
         *      Check that the definition is valid.
         */
@@ -1602,7 +1622,7 @@ int fr_dict_attr_add_initialised(fr_dict_attr_t *da)
         *      between auto-assigned and explkicitly assigned.
         */
        if (da->flags.name_only) {
-               if (da->attr_set) {
+               if (da->state.attr_set) {
                        fr_dict_attr_t *parent = fr_dict_attr_unconst(da->parent);
 
                        if (da->attr > da->parent->last_child_attr) {