]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
track impure functions separately from pure xlats
authorAlan T. DeKok <aland@freeradius.org>
Sun, 1 Sep 2024 13:38:35 +0000 (09:38 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 1 Sep 2024 13:38:35 +0000 (09:38 -0400)
which means that

&foo - 1

isn't pure, because it depends on "foo".  But it's also not an
impure function, which means it can be calculated without the
interpreter yielding

src/lib/unlang/xlat.h
src/lib/unlang/xlat_expr.c
src/lib/unlang/xlat_func.c
src/lib/unlang/xlat_priv.h
src/lib/unlang/xlat_redundant.c
src/lib/unlang/xlat_tokenize.c

index 797c44634fa5ce86fe7e7e7d678d4528cccf203f..48fc8a45a414da0f3197dfadf24d2bee9b9e27a7 100644 (file)
@@ -110,6 +110,7 @@ typedef struct xlat_s xlat_t;
 typedef struct {
        bool                    needs_resolving;//!< Needs pass2 resolution.
        bool                    pure;           //!< has no external side effects, true for BOX, LITERAL, and some functions
+       bool                    impure_func;    //!< xlat contains an impure function
        bool                    can_purify;     //!< if the xlat has a pure function with pure arguments.
 
        bool                    constant;       //!< xlat is just tmpl_attr_tail_data, or XLAT_BOX
@@ -435,6 +436,8 @@ tmpl_t              *xlat_to_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t *xlat);
 
 int            xlat_from_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t **head, tmpl_t **vpt_p);
 
+bool           xlat_impure_func(xlat_exp_head_t const *head) CC_HINT(nonnull);
+
 /*
  *     xlat_alloc.c
  */
index 8fa41a05032357d13b42b25b0a26ede40ee9bd0d..26cb49fb02325db7ee705b013c5b05a1b1e0132d 100644 (file)
@@ -2153,6 +2153,7 @@ static fr_slen_t tokenize_unary(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf
        unary->call.func = func;
        unary->call.dict = t_rules->attr.dict_def;
        unary->flags = func->flags;
+       unary->flags.impure_func = !func->flags.pure;
 
        if (tokenize_field(unary->call.args, &node, &our_in, p_rules, t_rules, bracket_rules, out_c, (c == '!')) < 0) {
                talloc_free(unary);
@@ -2374,7 +2375,7 @@ static fr_slen_t tokenize_rcode(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf
        MEM(node = xlat_exp_alloc(head, XLAT_FUNC, fr_sbuff_start(&our_in), slen));
        node->call.func = func;
        // no need to set dict here
-       node->flags = func->flags;
+       node->flags = func->flags; /* rcode is impure, but can be calculated statically */
 
        MEM(arg = xlat_exp_alloc(node, XLAT_BOX, fr_sbuff_start(&our_in), slen));
 
@@ -2982,6 +2983,7 @@ redo:
        node->call.func = func;
        node->call.dict = t_rules->attr.dict_def;
        node->flags = func->flags;
+       node->flags.impure_func = !func->flags.pure;
 
        xlat_func_append_arg(node, lhs, logical_ops[op] && cond);
        xlat_func_append_arg(node, rhs, logical_ops[op] && cond);
index 995ad57848e30d8069340ecb63cd741f32d17046..4ce620fd72d54fafe0e94993d07a86eb0e9683ab 100644 (file)
@@ -403,6 +403,7 @@ void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
 {
        x->flags.pure = flags & XLAT_FUNC_FLAG_PURE;
        x->internal = flags & XLAT_FUNC_FLAG_INTERNAL;
+       x->flags.impure_func = !x->flags.pure;
 }
 
 /** Set a print routine for an xlat function.
index 806163ed2b9a4974f4d8712890637b142585a5c7..08132bb64125bcc47c92ba02a93388f4b996c69d 100644 (file)
@@ -230,6 +230,7 @@ static inline CC_HINT(nonnull) void xlat_flags_merge(xlat_flags_t *parent, xlat_
        parent->pure &= child->pure; /* purity can only be removed, never added */
        parent->can_purify |= child->can_purify;
        parent->constant &= child->constant;
+       parent->impure_func |= child->impure_func;
 }
 
 static inline CC_HINT(nonnull) int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
index 1393c0fe21051faba7403a025215eb65e4aca7a7..54326a31bb73cef6d4053d0ced53866fc564123b 100644 (file)
@@ -215,6 +215,7 @@ static xlat_exp_t *xlat_exp_func_alloc(TALLOC_CTX *ctx, xlat_t const *func, xlat
                return NULL;
        }
        node->flags = func->flags;
+       node->flags.impure_func = !func->flags.pure;
        xlat_flags_merge(&node->flags, &args->flags);
 
        /*
index 0013583dfcaae696820f5084d73fc281f38c55e9..fb658ea5b41f2b9207fae1583dc46a345316e4b7 100644 (file)
@@ -378,6 +378,7 @@ static int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in, tm
                node->call.func = func;
                if (t_rules) node->call.dict = t_rules->attr.dict_def;
                node->flags = func->flags;
+               node->flags.impure_func = !func->flags.pure;
                node->call.input_type = func->input_type;
        }
 
@@ -1688,6 +1689,7 @@ int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
 
                        xlat_flags_merge(&node->flags, &node->call.args->flags);
                        node->flags.can_purify = (node->call.func->flags.pure && node->call.args->flags.pure) | node->call.args->flags.can_purify;
+                       node->flags.impure_func = !node->call.func->flags.pure;
                        break;
 
                /*
@@ -1851,3 +1853,8 @@ done:
 
        return 0;
 }
+
+bool xlat_impure_func(xlat_exp_head_t const *head)
+{
+       return head->flags.impure_func;
+}