]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
do a better job of purifying xlats
authorAlan T. DeKok <aland@freeradius.org>
Wed, 19 Feb 2025 19:09:23 +0000 (14:09 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 19 Feb 2025 19:09:23 +0000 (14:09 -0500)
set the can_purify flag in more places, add tests, and do
associated cleanups

src/lib/unlang/xlat_alloc.c
src/lib/unlang/xlat_expr.c
src/lib/unlang/xlat_priv.h
src/lib/unlang/xlat_purify.c
src/tests/unit/xlat/purify.txt

index d2c9ccc7454fb1d258a48ddcf10d82e26a433328..a9fdb3b77655cb142ee7efe0aec5e83ae3346db9 100644 (file)
@@ -39,7 +39,7 @@ xlat_exp_head_t *_xlat_exp_head_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx)
        MEM(head = talloc_zero(ctx, xlat_exp_head_t));
 
        fr_dlist_init(&head->dlist, xlat_exp_t, entry);
-       head->flags.pure = true;
+       head->flags.pure = head->flags.can_purify = true;
 #ifndef NDEBUG
        head->file = file;
        head->line = line;
@@ -107,7 +107,7 @@ static xlat_exp_t *xlat_exp_alloc_pool(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, uns
        xlat_exp_t *node;
 
        MEM(node = talloc_zero_pooled_object(ctx, xlat_exp_t, extra_hdrs, extra));
-       node->flags.pure = true;        /* everything starts pure */
+       node->flags.pure = node->flags.can_purify = true;       /* everything starts pure */
        node->quote = T_BARE_WORD;
 #ifndef NDEBUG
        node->file = file;
index 236fe9d4a12a5d6097e5ea35c977c18009553c1e..f57979e2ebb3c089bed437e9599b1d5b706d8d67 100644 (file)
@@ -2764,13 +2764,13 @@ static fr_slen_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf
                }
 
                node->flags.constant = true;
-               node->flags.pure = true;
+               node->flags.pure = node->flags.can_purify = true;
 
        } else if (tmpl_contains_xlat(node->vpt)) {
                node->flags = tmpl_xlat(vpt)->flags;
 
        } else if (tmpl_is_attr(node->vpt)) {
-               node->flags.pure = false;
+               node->flags.pure = node->flags.can_purify = false;
 
 #ifndef NDEBUG
                if (vpt->name[0] == '%') {
index 08132bb64125bcc47c92ba02a93388f4b996c69d..f5bb04e308c887726ff5fcbc1ecb4c0d472fc1a9 100644 (file)
@@ -228,7 +228,7 @@ static inline CC_HINT(nonnull) void xlat_flags_merge(xlat_flags_t *parent, xlat_
 {
        parent->needs_resolving |= child->needs_resolving;
        parent->pure &= child->pure; /* purity can only be removed, never added */
-       parent->can_purify |= child->can_purify;
+       parent->can_purify |= child->can_purify; /* there is SOME node under us which can be purified */
        parent->constant &= child->constant;
        parent->impure_func |= child->impure_func;
 }
index 486f2eb58a0ccd2e53ed6f2b3520dd2e82fc841a..7c8381e6c771244faf0d4897da54fa936cf6249c 100644 (file)
@@ -88,10 +88,18 @@ int xlat_purify_list(xlat_exp_head_t *head, request_t *request)
                                node->flags = child->flags;
                                break;
                        }
-                       FALL_THROUGH;
+                       break;
+
+               case XLAT_BOX:
+               case XLAT_ONE_LETTER:
+               case XLAT_REGEX:
+                       break;
 
-               default:
-                       fr_strerror_printf("Internal error - cannot purify xlat");
+               case XLAT_INVALID:
+               case XLAT_FUNC_UNRESOLVED:
+               case XLAT_VIRTUAL:
+               case XLAT_VIRTUAL_UNRESOLVED:
+                       fr_assert(0);
                        return -1;
 
                case XLAT_GROUP:
@@ -205,8 +213,11 @@ int xlat_purify(xlat_exp_head_t *head, unlang_interpret_t *intp)
 
        rcode = xlat_purify_list(head, request);
        talloc_free(request);
+       if (rcode < 0) return rcode;
 
-       return rcode;
+       fr_assert(!head->flags.can_purify);
+
+       return 0;
 }
 
 static fr_value_box_t *xlat_value_box(xlat_exp_t *node)
index 263c601f4f5524b1668e498698169336277e1d60..9f773514d9c85b0f5be2a0e52ed26aff4633737c 100644 (file)
@@ -44,6 +44,15 @@ match 45
 xlat_purify (2 + 3) * 4 + 5
 match 25
 
+#
+#  Not the same as a regex %{3}, but we can't tell the difference here.
+#
+xlat_purify %{1 + 2}
+match %{3}
+
+xlat_purify %{'a' + 'b'}
+match %{"ab"}
+
 xlat_purify NAS-Port + 5
 match (NAS-Port + 5)
 
@@ -198,13 +207,13 @@ match !%expr.rcode('fail')
 #  @todo - xlat_tokenize() does not call purify
 #
 xlat_purify (string)(%{1 + 2})
-match %cast(string, %{(1 + 2)})
+match "3"
 
 #
 #  This is a different code path than the above.
 #
 xlat_purify (string)%{1 + 2}
-match (string)%{(1 + 2)}
+match (string)%{3}
 
 xlat_purify "hello"
 match "hello"
@@ -218,12 +227,8 @@ match "hello 3"
 xlat_purify "hello " + (string)%{1 + 2} + " bob"
 match "hello 3 bob"
 
-#
-#  @todo - this seems wrong, but likely a bug in unit_test_attribute.c
-#  The real run-time tests work
-#
 xlat_purify "hello %{1 + 2} bob"
-match "hello %{(1 + 2)} bob"
+match "hello %{3} bob"
 
 #
 #  New syntax!
@@ -262,4 +267,4 @@ xlat_purify %md5("foo")
 match 0xacbd18db4cc2f85cedef654fccc4a4d8
 
 count
-match 116
+match 120