]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
better checks for parent / child lengths
authorAlan T. DeKok <aland@freeradius.org>
Sat, 23 Aug 2025 15:41:24 +0000 (11:41 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 23 Aug 2025 18:24:44 +0000 (14:24 -0400)
src/lib/util/dict_tokenize.c
src/lib/util/dict_validate.c

index 16395e43150760658a3a5905b272363e3b0306ca..d4674ebb988b0f893445d5c54f8190492a37a5c8 100644 (file)
@@ -2289,9 +2289,11 @@ static int dict_read_process_member(dict_tokenize_ctx_t *dctx, char **argv, int
 #endif
 
        /*
-        *      If our parent is a fixed-size struct, then we have to be fixed-size, too.
+        *      If our parent is a known width struct, then we're
+        *      allowed to be variable width.  The parent might just
+        *      have a "length=16" prefix, which lets its children be
+        *      variable sized.
         */
-       da->flags.is_known_width |= CURRENT_FRAME(dctx)->da->flags.is_known_width;
 
        /*
         *      Double check any bit field magic
@@ -2456,9 +2458,8 @@ static int dict_read_process_member(dict_tokenize_ctx_t *dctx, char **argv, int
                 *      to them.
                 */
                if (da->type == FR_TYPE_TLV) {
-                       dctx->relative_attr = dict_attr_child_by_num(CURRENT_FRAME(dctx)->da,
-                                                                    CURRENT_FRAME(dctx)->member_num);
-                       if (dctx->relative_attr && (dict_dctx_push(dctx, dctx->relative_attr, NEST_NONE) < 0)) return -1;
+                       dctx->relative_attr = da;
+                       if (dict_dctx_push(dctx, dctx->relative_attr, NEST_NONE) < 0) return -1;
                }
 
        } else if (CURRENT_FRAME(dctx)->da->flags.length) {
index f2094195f6817ebe984e8b956046d636544f2e64..6d12d1cec5118ad32d3c265b1f5b080d5fc73e43 100644 (file)
@@ -506,7 +506,12 @@ bool dict_attr_flags_valid(fr_dict_attr_t *da)
                ALLOW_FLAG(extra);
                ALLOW_FLAG(subtype);
 
-               if (parent->flags.is_known_width && !flags->is_known_width && !flags->length) {
+               /*
+                *      If our parent is known width, then the children have to be known width, UNLESS
+                *      either this child or its parent has a "length" prefix.
+                */
+               if (parent->flags.is_known_width && !flags->is_known_width && !flags->length &&
+                   !da_is_length_field(da) && !da_is_length_field(parent)) {
                        fr_strerror_const("Variable-sized fields cannot be used within a 'struct' which is 'array'");
                        return false;
                }