]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Cast nothing to string/octets yields empty string/octets
authorAlan T. DeKok <aland@freeradius.org>
Thu, 6 Jul 2023 13:01:50 +0000 (09:01 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 6 Jul 2023 13:44:58 +0000 (09:44 -0400)
Because we want the following condition to work, when there is
only one of attribute Tmp-Integer-0:

if ("%{Tmp-String-0[2]}" == '') {
// always runs!
}

i.e. expanding in a string context, a reference to an attribute
which doesn't exist should result in an empty string, and not a
condition failure of "can't create LHS of condition"

src/lib/unlang/xlat_builtin.c
src/tests/keywords/xlat-cond-missing [new file with mode: 0644]

index 9b54e7f0a995221c4d5d4ae5a288ed6d14e42bd0..0e972cda769371d09ac0d90a249ba69b26878314 100644 (file)
@@ -1374,7 +1374,7 @@ finish:
 
 static xlat_arg_parser_t const xlat_func_cast_args[] = {
        { .required = true, .single = true, .type = FR_TYPE_VOID },
-       { .required = true, .type = FR_TYPE_VOID },
+       { .type = FR_TYPE_VOID },
        { .variadic = XLAT_ARG_VARIADIC_EMPTY_KEEP, .type = FR_TYPE_VOID },
        XLAT_ARG_PARSER_TERMINATOR
 };
@@ -1425,6 +1425,25 @@ static xlat_action_t xlat_func_cast(TALLOC_CTX *ctx, fr_dcursor_t *out,
                }
        }
 
+       (void) fr_value_box_list_pop_head(args);
+
+       /*
+        *      When we cast nothing to a string / octets, the result is an empty string/octets.
+        */
+       if (unlikely(!fr_value_box_list_head(args))) {
+               if ((type == FR_TYPE_STRING) || (type == FR_TYPE_OCTETS)) {
+                       fr_value_box_t *dst;
+
+                       MEM(dst = fr_value_box_alloc(ctx, type, NULL, false));
+                       fr_dcursor_append(out, dst);
+
+                       return XLAT_ACTION_DONE;
+               }
+
+               RDEBUG("No data for cast to '%s'", fr_type_to_str(type));
+               return XLAT_ACTION_FAIL;
+       }
+
        /*
         *      Cast to string means *print* to string.
         */
@@ -1432,7 +1451,6 @@ static xlat_action_t xlat_func_cast(TALLOC_CTX *ctx, fr_dcursor_t *out,
                fr_sbuff_t *agg;
                fr_value_box_t *dst;
 
-               (void) fr_value_box_list_pop_head(args);
                talloc_free(name);
 
                FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 256, SIZE_MAX);
@@ -1453,7 +1471,7 @@ static xlat_action_t xlat_func_cast(TALLOC_CTX *ctx, fr_dcursor_t *out,
        /*
         *      Copy inputs to outputs, casting them along the way.
         */
-       arg = name;
+       arg = NULL;
        while ((arg = fr_value_box_list_next(args, arg)) != NULL) {
                fr_value_box_t  *vb, *p;
 
diff --git a/src/tests/keywords/xlat-cond-missing b/src/tests/keywords/xlat-cond-missing
new file mode 100644 (file)
index 0000000..93ebc00
--- /dev/null
@@ -0,0 +1,23 @@
+&request += {
+       &Tmp-IP-Address-0 = 192.0.2.1
+       &Tmp-IP-Address-0 = 192.0.2.2
+       &Tmp-IP-Address-0 = 192.0.2.3
+       &Tmp-IP-Address-0 = 192.0.2.4
+}
+
+if (%{Tmp-IP-Address-0[#]} != 4) {
+       test_fail
+}
+
+#
+#  This expansion should succeed, and should result in an empty string.
+#
+#  It's stupid to do this expansion.  The admin should instead just check
+#  for the existence of the attribute.  But... the syntax allows it, so
+#  it should work.
+#
+if !("%{Tmp-IP-Address-0[4]}" == '') {
+       test_fail
+}
+
+success