]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow attribute references as cursors for function arguments
authorAlan T. DeKok <aland@freeradius.org>
Tue, 13 May 2025 18:26:53 +0000 (14:26 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 13 May 2025 19:52:31 +0000 (15:52 -0400)
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

src/lib/unlang/xlat_eval.c
src/lib/unlang/xlat_priv.h
src/lib/unlang/xlat_tokenize.c
src/tests/keywords/cbor

index 74b493a5be9a21d85be4db94a2d632e94cd64b15..1d1f83d59db03dee2dbfc3bbd4d3e5c0e26d17ec 100644 (file)
@@ -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)) {
index 982b93e73e5559f2564a0f0d7c1d0b2227650f06..ff1c3a1973bf0956c00eaee46641c32f67d177fc 100644 (file)
@@ -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.
index 2cdd2d9a47bd4b91e9a144a526a22601a8ccca79..405c45ef1ab4506cf3663998e89626b3da5944bd 100644 (file)
@@ -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;
        }
 
        /*
index 9aa14c47bb3f06a1b9ccb0300ae3eb8d32fa98ea..2c7a6628424316b8a4c732908ab121eb83004e23 100644 (file)
@@ -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