]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
fix final issues
authorAlan T. DeKok <aland@freeradius.org>
Wed, 25 May 2022 20:45:54 +0000 (16:45 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 26 May 2022 11:20:13 +0000 (07:20 -0400)
src/lib/unlang/xlat_expr.c
src/tests/unit/xlat/purify.txt

index 588957079f88c118a1fb3073edacf0c107248ab4..1820099fc1faad578de030883ebbd7e5b349833c 100644 (file)
@@ -572,6 +572,51 @@ static xlat_action_t xlat_func_unary_minus(TALLOC_CTX *ctx, fr_dcursor_t *out,
        return XLAT_ACTION_DONE;
 }
 
+/** Convert XLAT_BOX arguments to XLAT_TMPL
+ *
+ *  xlat_tokenize() just makes all unknown arguments into XLAT_BOX, of data type FR_TYPE_STRING.  Whereas
+ *  xlat_tokenize_expr() calls tmpl_afrom_substr(), which tries hard to create a particular data type.
+ *
+ *  This function fixes up calls of the form %(op_add: 3 4), which normally passes 2 arguments of "3" and "4",
+ *  so that the arguments are instead passed as integers 3 and 4.
+ *
+ *  This fixup isn't *strictly* necessary, but it's good to have no surprises in the code, if the user creates
+ *  an expression manually.
+ */
+static int xlat_function_args_to_tmpl(xlat_inst_ctx_t const *xctx)
+{
+       xlat_exp_foreach(xctx->ex->call.args, arg) {
+               ssize_t slen;
+               xlat_exp_t *node;
+               tmpl_t *vpt;
+
+               fr_assert(arg->type == XLAT_GROUP);
+
+               node = xlat_exp_head(arg->group);
+               if (!node) continue;
+               if (node->type != XLAT_BOX) continue;
+               if (node->data.type != FR_TYPE_STRING) continue;
+
+               /*
+                *      Try to parse it.  If we can't, leave it for a run-time error.
+                */
+               slen = tmpl_afrom_substr(node, &vpt, &FR_SBUFF_IN(node->data.vb_strvalue, node->data.vb_length),
+                                        node->quote, NULL, NULL);
+               if (slen <= 0) continue;
+               if ((size_t) slen < node->data.vb_length) continue;
+
+               /*
+                *      Leave it as XLAT_BOX, but with the (guessed) new data type.
+                */
+               fr_value_box_clear(&node->data);
+               fr_value_box_copy(node, &node->data, tmpl_value(vpt));
+               talloc_free(vpt);
+       }
+
+       return 0;
+}
+
+
 #undef XLAT_REGISTER_BINARY_OP
 #define XLAT_REGISTER_BINARY_OP(_op, _name) \
 do { \
@@ -579,6 +624,7 @@ do { \
        xlat_func_args(xlat, binary_op_xlat_args); \
        xlat_internal(xlat); \
        xlat_print_set(xlat, xlat_expr_print_binary); \
+       xlat_async_instantiate_set(xlat, xlat_function_args_to_tmpl, NULL, NULL, NULL); \
        xlat->token = _op; \
 } while (0)
 
index 05f9713f0057585af20bd08341400bd25d3c77ae..ff3216646090afb99d8aec28261c948ac7bd605e 100644 (file)
@@ -106,25 +106,12 @@ xlat_purify (4 + 3) + 6
 match 13
 
 #
-#  @todo - this gets parsed as "4" + "3", because the parsing of
-#  XLAT_BOX in xlat_tokenize_string() just makes everything into
-#  FR_TYPE_STRING.  The parsing in tmpl_tokenize() is different,
-#  as it tries to figure out what data type things are.
-#
-#  The solution is likely to have the expression code double-check
-#  it's arguments on instantiate, and if they are FR_TYPE_STRING with
-#  quote T_BARE_WORD, then go re-evaluate them.  Tho that seems
-#  terrible, TBH.  A cleaner way would be to add a parse flag which tells
-#  the xlat tokenizer "please try to figure out WTF this value is".
-#
-#  which then gets "43", and then "43" to int, and 43+6 -> 49
-#
-#  The rules for parsing tmpls at run-time are apparently different
-#  than parsing them at compile time?
+#  xlat_tokenize() parses it's arguments as XLAT_BOX,
+#  of FR_TYPE_STRING.  The binary op instantiation function
+#  fixes those up via tmpl_afrom_substr().
 #
 xlat_purify %(op_add:4 3) + 6
-match 49
-#match ((4 + 3) + 6)
+match 13
 
 #
 #  useless casts are omitted.
@@ -160,10 +147,7 @@ match (%{Service-Type} == 3)
 #match ERROR offset 1: Failed resolving attribute in expansion: Message
 
 #
-#  @todo - find some way quote the RHS?  Maybe just make it
-#  T_SINGLE_QUOTED_STRING for "string" types, and leave it T_BARE_WORD
-#  for everything else.  But this presumes that the RHS is always only
-#  one value-box, and perhaps it isn't?
+#  Strings are single quoted
 #
 xlat_purify &Filter-Id == ("foo" + "bar")
 match (%{Filter-Id} == 'foobar')