From: Alan T. DeKok Date: Sun, 1 Sep 2024 13:38:35 +0000 (-0400) Subject: track impure functions separately from pure xlats X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=53a2a1547ac4f854958a96309a8525519ea73539;p=thirdparty%2Ffreeradius-server.git track impure functions separately from pure xlats 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 --- diff --git a/src/lib/unlang/xlat.h b/src/lib/unlang/xlat.h index 797c44634f..48fc8a45a4 100644 --- a/src/lib/unlang/xlat.h +++ b/src/lib/unlang/xlat.h @@ -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 */ diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index 8fa41a0503..26cb49fb02 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -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); diff --git a/src/lib/unlang/xlat_func.c b/src/lib/unlang/xlat_func.c index 995ad57848..4ce620fd72 100644 --- a/src/lib/unlang/xlat_func.c +++ b/src/lib/unlang/xlat_func.c @@ -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. diff --git a/src/lib/unlang/xlat_priv.h b/src/lib/unlang/xlat_priv.h index 806163ed2b..08132bb641 100644 --- a/src/lib/unlang/xlat_priv.h +++ b/src/lib/unlang/xlat_priv.h @@ -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) diff --git a/src/lib/unlang/xlat_redundant.c b/src/lib/unlang/xlat_redundant.c index 1393c0fe21..54326a31bb 100644 --- a/src/lib/unlang/xlat_redundant.c +++ b/src/lib/unlang/xlat_redundant.c @@ -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); /* diff --git a/src/lib/unlang/xlat_tokenize.c b/src/lib/unlang/xlat_tokenize.c index 0013583dfc..fb658ea5b4 100644 --- a/src/lib/unlang/xlat_tokenize.c +++ b/src/lib/unlang/xlat_tokenize.c @@ -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; +}