]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
validate data type where possible.
authorAlan T. DeKok <aland@freeradius.org>
Wed, 25 May 2022 12:19:31 +0000 (08:19 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 25 May 2022 14:59:53 +0000 (10:59 -0400)
This doesn't catch all of the cases, but it catches enough to be
useful.

src/lib/unlang/xlat_tokenize.c
src/tests/unit/xlat/base.txt

index ea40a76324371bea07f34ace540a567ad78fabbc..3553aecd337f3b9c3a85b0e93f47bd370976e922 100644 (file)
@@ -391,14 +391,69 @@ static inline int xlat_tokenize_function_mono(xlat_exp_head_t *head,
        return 0;
 }
 
+static int xlat_validate_function_arg(xlat_arg_parser_t const *arg_p, xlat_exp_t *arg)
+{
+       ssize_t slen;
+       xlat_exp_t *node;
+       fr_value_box_t box;
+
+       /*
+        *      The caller doesn't care about the type, OR the type is string, which it already is.
+        */
+       if ((arg_p->type == FR_TYPE_VOID) || (arg_p->type == FR_TYPE_STRING)) {
+               return 0;
+       }
+
+       node = xlat_exp_head(arg->group);
+
+       /*
+        *      @todo - check arg_p->single, and complain.
+        */
+       if (xlat_exp_next(arg->group, node)) return 0;
+
+       /*
+        *      @todo - These checks are relatively basic.  We should do better checks, such as if the
+        *      expected type is not string/octets, and the passed arguments are multiple things, then
+        *      die?
+        *
+        *      And check also the 'concat' flag?
+        */
+       if (node->type != XLAT_BOX) return 0;
+
+       /*
+        *      Boxes are always strings, because of xlat_tokenize_string()
+        */
+       fr_assert(node->data.type == FR_TYPE_STRING);
+
+       fr_value_box_init_null(&box);
+
+       /*
+        *      The entire string must be parseable as the data type we expect.
+        */
+       slen = fr_value_box_from_str(node, &box, arg_p->type, NULL, /* no enum */
+                                    node->data.vb_strvalue, node->data.vb_length,
+                                    NULL, /* no parse rules */
+                                    node->data.tainted);
+       if (slen <= 0) return -1;
+
+       /*
+        *      Replace the string value with the parsed data type.
+        */
+       fr_value_box_clear(&node->data);
+       fr_value_box_copy(node, &node->data, &box);
+
+       return 0;
+}
+
 int xlat_validate_function_args(xlat_exp_t *node)
 {
        xlat_arg_parser_t const *arg_p;
        xlat_exp_t              *arg = xlat_exp_head(node->call.args);
+       int                     i = 0;
 
        fr_assert(node->type == XLAT_FUNC);
 
-       for (arg_p = node->call.func->args; arg_p->type != FR_TYPE_NULL; arg_p++) {
+       for (arg_p = node->call.func->args, i = 0; arg_p->type != FR_TYPE_NULL; arg_p++) {
                if (!arg_p->required) break;
 
                if (!arg) {
@@ -413,7 +468,13 @@ int xlat_validate_function_args(xlat_exp_t *node)
                 */
                fr_assert(arg->type == XLAT_GROUP);
 
+               if (xlat_validate_function_arg(arg_p, arg) < 0) {
+                       fr_strerror_printf("Failed parsing argument %d as type '%s'", i, fr_type_to_str(arg_p->type));
+                       return -1;
+               }
+
                arg = xlat_exp_next(node->call.args, arg);
+               i++;
        }
 
        return 0;
index bb2b790b78b8038a84688222604bbd548c183342..a8ae03326d21c233fdb6ae57f0d2e5e9bf2432fc 100644 (file)
@@ -300,5 +300,29 @@ match ERROR offset 44: Missing closing brace
 xlat_argv echo hello %{Tmp-String-0}:1234 world
 match [0]{ echo }, [1]{ hello }, [2]{ %{Tmp-String-0}:1234 }, [3]{ world }
 
+xlat %(debug: 5)
+match %(debug: 5)
+
+#
+#  @todo - debug takes an integer, and this is wrong.
+#
+xlat %(debug: "foo")
+match %(debug: "foo")
+
+#
+#  This is correct.
+#
+xlat %(rpad:&User-Name 5 x)
+match %(rpad:&User-Name 5 x)
+
+#
+#  The second argument should be an integer.
+#
+#  @todo - we don't currently track string offsets for intermediate nodes,
+#  so the "offset 23" is wrong.  It also doesn't say *which* string is wrong.  We'll fix that later.
+#
+xlat %(rpad:&User-Name foo x)
+match ERROR offset 23: Failed parsing argument 1 as type 'uint64'
+
 count
-match 179
+match 187