From: Alan T. DeKok Date: Tue, 13 May 2025 18:26:53 +0000 (-0400) Subject: allow attribute references as cursors for function arguments X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd0be1b2b6e65baa0dcbb480a470a749bcb796f8;p=thirdparty%2Ffreeradius-server.git allow attribute references as cursors for function arguments via the somewhat bad hack of adding a flag to xlat_exp_head_t, because it's too hard to pass in the xlat_arg_parser_t to the xlat evaluation function --- diff --git a/src/lib/unlang/xlat_eval.c b/src/lib/unlang/xlat_eval.c index 74b493a5be9..1d1f83d59db 100644 --- a/src/lib/unlang/xlat_eval.c +++ b/src/lib/unlang/xlat_eval.c @@ -489,9 +489,14 @@ check_non_leaf: if (arg->type == FR_TYPE_VOID) return XLAT_ACTION_DONE; /* - * We have a cursor. + * We already have a pair cursor, the argument was an attribute reference. */ - fr_assert(arg->type == FR_TYPE_PAIR_CURSOR); + if (vb->type == FR_TYPE_PAIR_CURSOR) return XLAT_ACTION_DONE; + + /* + * If the argument is a pair + */ + fr_assert(vb->type != FR_TYPE_PAIR_CURSOR); { int err; @@ -1306,6 +1311,25 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_head_ if (!*in) return XLAT_ACTION_DONE; + /* + * An attribute reference which is a cursor just gets a + * value-box of cursor returned. That is filled in + * later. + */ + if (unlikely(head && head->cursor)) { + int err; + + fr_assert((*in)->type == XLAT_TMPL); + + MEM(value = fr_value_box_alloc(ctx, FR_TYPE_PAIR_CURSOR, NULL)); + + (void) tmpl_dcursor_value_box_init(&err, value, request, (*in)->vpt); + if (err < -1) return XLAT_ACTION_FAIL; + + fr_dcursor_append(out, value); + goto finish; + } + XLAT_DEBUG("** [%i] %s >> entered", unlang_interpret_stack_depth(request), __FUNCTION__); for (node = *in; node; node = xlat_exp_next(head, node)) { diff --git a/src/lib/unlang/xlat_priv.h b/src/lib/unlang/xlat_priv.h index 982b93e73e5..ff1c3a1973b 100644 --- a/src/lib/unlang/xlat_priv.h +++ b/src/lib/unlang/xlat_priv.h @@ -190,6 +190,7 @@ struct xlat_exp_head_s { xlat_flags_t flags; //!< Flags that control resolution and evaluation. uint8_t instantiated : 1; //!< temporary flag until we fix more things uint8_t is_argv : 1; //!< this thing holds function arguments + uint8_t cursor : 1; //!< otherwise it's too hard to pass xlat_arg_parser_t to the evaluation function. #ifndef NDEBUG char const * _CONST file; //!< File where the xlat was allocated. diff --git a/src/lib/unlang/xlat_tokenize.c b/src/lib/unlang/xlat_tokenize.c index 2cdd2d9a47b..405c45ef1ab 100644 --- a/src/lib/unlang/xlat_tokenize.c +++ b/src/lib/unlang/xlat_tokenize.c @@ -285,15 +285,11 @@ static int xlat_validate_function_arg(xlat_arg_parser_t const *arg_p, xlat_exp_t } /* - * @todo - in xlat_frame_eval(), push the vpt pointer? We don't want the _values_ of the - * referenced attributes, we want a cursor which walks over the referenced attributes. - * - * Except that the xlat_frame_eval_repeat() doesn't have access to the arg list, so it - * can't check that we want a tmpl / cursor. Maybe hack that by restricting the cursor - * argument to the first one, or the first + variadic of the same type. + * Bare attribute references are allowed, but are marked up as "return a cursor to this + * thing, don't return a value". */ - fr_strerror_const("Please use strings for references - unquoted strings are not yet supported"); - return -1; + arg->group->cursor = true; + return 0; } /* diff --git a/src/tests/keywords/cbor b/src/tests/keywords/cbor index 9aa14c47bb3..2c7a6628424 100644 --- a/src/tests/keywords/cbor +++ b/src/tests/keywords/cbor @@ -34,4 +34,12 @@ if (User-Name != "bob") { test_fail } +# +# The cursor as an attribute reference, and not as a string. +# +cbor := %cbor.encode(User-Name) +if (cbor != 0x9fa10163626f62ff) { + test_fail +} + success