From: Alan T. DeKok Date: Fri, 18 Apr 2025 12:40:11 +0000 (-0400) Subject: hoist tmpls X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b4ad384e8ba029845d36ad16e7ed4a6eb669cad4;p=thirdparty%2Ffreeradius-server.git hoist tmpls if a tmpl is asked to parse %{...}. then the result is TMPL_TYPE_XLAT. However, if the contents of that xlat are identically a tmpl, e.g. User-Name, then there is no reason to keep the xlat. Instead, we hoist the tmpl we really want, and discard the intermediate xlat this simplifies the internal data structures, and allows for additional optimizations. It also means that we do less work at run-time in order to expand the tmpl. --- diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index 7f4b38d6438..00d58aff514 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -3207,10 +3207,34 @@ fr_slen_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, slen = xlat_tokenize(vpt, &head, &our_in, p_rules, t_rules); if (slen <= 0) FR_SBUFF_ERROR_RETURN(&our_in); - if (xlat_needs_resolving(head)) UNRESOLVED_SET(&type); + if (xlat_needs_resolving(head)) { + UNRESOLVED_SET(&type); + goto set_tmpl; - tmpl_init(vpt, type, quote, fr_sbuff_start(&our_in), slen, t_rules); - vpt->data.xlat.ex = head; + } else if (fr_dlist_num_elements(&head->dlist) == 1) { + xlat_exp_t *node = xlat_exp_head(head); + tmpl_t *hoisted; + + if (node->type != XLAT_TMPL) goto set_tmpl; + + /* + * We were asked to parse a tmpl. But it turned out to be an xlat %{...} + * + * If that xlat is identically a tmpl such as %{User-Name}, then we just + * hoist the tmpl to this node. Otherwise at run time, we will have an + * extra bounce through the xlat code, for no real reason. + */ + hoisted = node->vpt; + + (void) talloc_steal(ctx, hoisted); + talloc_free(vpt); + vpt = hoisted; + + } else { + set_tmpl: + tmpl_init(vpt, type, quote, fr_sbuff_start(&our_in), slen, t_rules); + vpt->data.xlat.ex = head; + } *out = vpt; diff --git a/src/tests/unit/xlat/base.txt b/src/tests/unit/xlat/base.txt index 746395a3744..42647512071 100644 --- a/src/tests/unit/xlat/base.txt +++ b/src/tests/unit/xlat/base.txt @@ -73,6 +73,13 @@ match ERROR offset 14: Too many arguments, expected 0, got 1 xlat %test('bar') match %test('bar') +# +# @todo - we now hoist the tmpl -> xlat -> tmpl to just a tmpl. But +# we don't change the name of the parent group. We may want to do that. +# +xlat %test(%{User-Name}) +match %test(%{User-Name}) + xlat %test() match ERROR offset 6: Missing required arg 1 @@ -297,4 +304,4 @@ xlat %md5('arg"') match %md5(0x61726722) count -match 159 +match 161