]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow arrays of known-width structs
authorAlan T. DeKok <aland@freeradius.org>
Thu, 17 Mar 2022 22:54:25 +0000 (18:54 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 18 Mar 2022 13:16:27 +0000 (09:16 -0400)
and do more checks on known widths

src/lib/util/dict_tokenize.c
src/lib/util/dict_validate.c

index 27c1ddd525eeae7d8cb52a9489d656a06635950f..3deec8e6586ed4a6a76e342d1a198a3818bdf64c 100644 (file)
@@ -1106,6 +1106,11 @@ static int dict_read_process_member(dict_tokenize_ctx_t *ctx, char **argv, int a
 
        memcpy(&flags, base_flags, sizeof(flags));
 
+       /*
+        *      If our parent is a fixed-size struct, then we have to be fixed-size, too.
+        */
+       flags.is_known_width |= ctx->stack[ctx->stack_depth].da->flags.is_known_width;
+
        if (dict_process_type_field(ctx, argv[1], &type, &flags) < 0) return -1;
 
        /*
index 2eff2c87a523804bbe7d56490cef89556affeaa7..b23c1de66cf2e73b7bb29dfb887d3acb0f5bc4ba 100644 (file)
@@ -117,6 +117,7 @@ bool dict_attr_flags_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
                case FR_TYPE_TIME_DELTA:
                case FR_TYPE_STRING:
                case FR_TYPE_OCTETS:
+               case FR_TYPE_STRUCT:
                        break;
                }
 
@@ -228,9 +229,14 @@ bool dict_attr_flags_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
                                return false;
                        }
 
+                       /*
+                        *      If we have arrays of structs, then the structure MUST be known width.
+                        */
+                       flags->is_known_width |= flags->array;
+
                        ALLOW_FLAG(extra);
-                       /* @todo - allow arrays of struct? */
                        ALLOW_FLAG(subtype);
+                       ALLOW_FLAG(array);
                        break;
 
                case FR_TYPE_TLV:
@@ -326,6 +332,7 @@ bool dict_attr_flags_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
 
        case FR_TYPE_STRUCT:
                ALLOW_FLAG(internal);
+               ALLOW_FLAG(array);
                if (all_flags) {
                        fr_strerror_const("Invalid flag for attribute of type 'struct'");
                        return false;
@@ -483,6 +490,11 @@ bool dict_attr_flags_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
                ALLOW_FLAG(extra);
                ALLOW_FLAG(subtype);
 
+               if (parent->flags.is_known_width && !flags->is_known_width && !flags->length) {
+                       fr_strerror_const("Variable-sized fields cannot be used within a 'struct' which is 'array'");
+                       return false;
+               }
+
                if (flags->array) {
                        switch (type) {
                        case FR_TYPE_FIXED_SIZE:
@@ -494,6 +506,7 @@ bool dict_attr_flags_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
                                break;
                        }
                }
+
                if (all_flags) {
                        fr_strerror_const("Invalid flag for attribute inside of a 'struct'");
                        return false;
@@ -662,31 +675,6 @@ bool dict_attr_fields_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
                return false;
        }
 
-#if 0
-       if (parent->type == FR_TYPE_STRUCT) {
-               /*
-                *      @todo - check PREVIOUS element.  if it's non-fixed size, then error out.
-                *      Move validation code from dict_read_process_member() to here
-                */
-               switch (type) {
-               case FR_TYPE_FIXED_SIZE:
-                       break;
-
-               case FR_TYPE_TLV:
-               case FR_TYPE_STRING:
-               case FR_TYPE_OCTETS:
-                       if (flags->length != 0) {
-                               fr_strerror_const("The 'octets' type MUST be fixed-width when used inside of a 'struct'");
-                               return false;
-                       }
-                       break;
-
-               default:
-                       break;
-               }
-       }
-#endif
-
        /*
         *      Initialize the length field, which is needed for the attr_valid() callback.
         */
@@ -697,6 +685,8 @@ bool dict_attr_fields_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
                flags->length = fr_value_box_network_length(&box);
        }
 
+       if (type == FR_TYPE_STRUCT) flags->is_known_width |= flags->array;
+
        /*
         *      Run protocol-specific validation functions, BEFORE we
         *      do the rest of the checks.