]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Rework xlat code to produce FR_TYPE_NULL boxes
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 4 Apr 2021 19:20:24 +0000 (20:20 +0100)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 4 Apr 2021 21:48:25 +0000 (22:48 +0100)
src/lib/unlang/xlat_builtin.c
src/lib/unlang/xlat_eval.c
src/lib/unlang/xlat_tokenize.c
src/lib/util/value.c
src/modules/rlm_client/rlm_client.c
src/tests/keywords/debug [new file with mode: 0644]

index de1f55d1e3aee07ddf28e1775f15f1a4df2d5c76..3e9a3f1a8a2de00610be826b41b7f798e33e1d25 100644 (file)
@@ -801,8 +801,7 @@ static xlat_action_t xlat_func_debug(TALLOC_CTX *ctx, fr_dcursor_t *out,
        /*
         *  Assume we just want to get the current value and NOT set it to 0
         */
-       if (!in_head)
-               goto done;
+       if (in_head->type == FR_TYPE_NULL) goto done;
 
        level = in_head->vb_int8;
        if (level == 0) {
@@ -1403,7 +1402,7 @@ static xlat_action_t xlat_func_lpad(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out,
        /*
         *      Fill is optional
         */
-       if (fill) {
+       if (fill->type != FR_TYPE_NULL) {
                fill_str = fill->vb_strvalue;
                fill_len = talloc_array_length(fill_str) - 1;
        }
@@ -1485,7 +1484,7 @@ static xlat_action_t xlat_func_rpad(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out,
        /*
         *      Fill is optional
         */
-       if (fill) {
+       if (fill->type != FR_TYPE_NULL) {
                fill_str = fill->vb_strvalue;
                fill_len = talloc_array_length(fill_str) - 1;
        }
index fd099ab7617592af685333e2dbbda1a86eb30e0e..7aa23cdc0d8bbc89b965458df13959c8f3ced841 100644 (file)
@@ -402,6 +402,12 @@ xlat_action_t xlat_process_args(TALLOC_CTX *ctx, fr_value_box_list_t *list, requ
                                        REDEBUG("Missing required argument %u", (unsigned int)((arg_p - args) + 1));
                                        return XLAT_ACTION_FAIL;
                                }
+
+                               /*
+                                *      Add a placeholder 'null' box
+                                */
+                               MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_NULL, NULL, false));
+                               fr_dlist_insert_tail(list, vb);
                                return XLAT_ACTION_DONE;
                        }
 
@@ -425,8 +431,20 @@ xlat_action_t xlat_process_args(TALLOC_CTX *ctx, fr_value_box_list_t *list, requ
                         *      argument with the head of the group.
                         */
                        if (arg_p->single || arg_p->concat) {
-                               fr_dlist_replace(list, vb, fr_dlist_pop_head(&vb->vb_group));
-                               talloc_free(vb);
+                               /*
+                                *      If the group is empty, convert
+                                *      it to a null box to maintain
+                                *      correct ordering in the argument
+                                *      list.
+                                */
+                               if (fr_dlist_empty(&vb->vb_group)) {
+                                       fr_value_box_t *prev = fr_dlist_remove(list, vb);
+                                       fr_value_box_init_null(vb);
+                                       fr_dlist_insert_after(list, prev, vb);
+                               } else {
+                                       fr_dlist_replace(list, vb, fr_dlist_pop_head(&vb->vb_group));
+                                       talloc_free(vb);
+                               }
                        }
 
                        if (arg_p->variadic) {
@@ -1366,6 +1384,7 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_t con
                case XLAT_GROUP:
                        XLAT_DEBUG("** [%i] %s(child) - %%{%s ...}", unlang_interpret_stack_depth(request), __FUNCTION__,
                                   node->fmt);
+                       if (!node->child) return XLAT_ACTION_DONE;
 
                        /*
                         *      Hand back the child node to the caller
index 923723816431275018e3b9d688b3db62b2f70ab5..ebc510c34ab9664da1f902ded41f9b7feb14767e 100644 (file)
@@ -1022,35 +1022,11 @@ static int xlat_tokenize_literal(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_
                                goto error;
                        }
                /*
-                *      We're parsing the string *containing* the xlat
-                *      expansions.
+                *      Empty input, emit no arguments
                 */
-               } else {
-                       /*      If we have an empty node, finish building it and
-                        *      emit it.
-                        *
-                        *      We're about to return, and it's a useful
-                        *      indication to the caller that this wasn't a parse
-                        *      error but just an empty string.
-                        */
-                       if (len == 0) {
-                               /*
-                                *      This isn't the only node in the sequence
-                                *      don't emit an empty trailing literal.
-                                */
-                               if (*head) {
-                                       talloc_free(node);
-                                       break;
-                               }
-
-                               xlat_exp_set_type(node, XLAT_LITERAL);
-                               xlat_exp_set_name_buffer_shallow(node, str);
-
-                               XLAT_DEBUG("LITERAL <-- (empty)");
-                               node->flags.needs_async = false; /* literals are always true */
-                               xlat_flags_merge(flags, &node->flags);
-                               fr_cursor_insert(&cursor, node);
-                       }
+               } else if (len == 0) {
+                       talloc_free(node);
+                       XLAT_DEBUG("LITERAL <-- (empty)");
                }
                break;
        }
@@ -1303,13 +1279,16 @@ ssize_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t
        *head = NULL;
 
        fr_strerror_clear();    /* Clear error buffer */
-       if (xlat_tokenize_literal(ctx, head, flags,
-                                 &our_in, false, p_rules, t_rules) < 0) return -fr_sbuff_used(&our_in);
+       if (xlat_tokenize_literal(ctx, head, flags, &our_in,
+                                 false, p_rules, t_rules) < 0) return -fr_sbuff_used(&our_in);
 
        /*
         *      Zero length expansion, return a zero length node.
         */
-       if (fr_sbuff_used(&our_in) == 0) *head = xlat_exp_alloc(ctx, XLAT_LITERAL, "", 0);
+       if (!*head) {
+               *head = xlat_exp_alloc(ctx, XLAT_LITERAL, "", 0);
+               return 0;
+       }
 
        /*
         *      Create ephemeral instance data for the xlat
@@ -1522,8 +1501,16 @@ ssize_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, f
 
        fr_strerror_clear();    /* Clear error buffer */
 
-       if (xlat_tokenize_literal(ctx, head, flags,
-                                 &our_in, false, p_rules, t_rules) < 0) return -fr_sbuff_used(&our_in);
+       if (xlat_tokenize_literal(ctx, head, flags, &our_in,
+                                 false, p_rules, t_rules) < 0) return -fr_sbuff_used(&our_in);
+
+       /*
+        *      Zero length expansion, return a zero length node.
+        */
+       if (!*head) {
+               *head = xlat_exp_alloc(ctx, XLAT_LITERAL, "", 0);
+               return fr_sbuff_set(in, &our_in);
+       }
 
        /*
         *      Add nodes that need to be bootstrapped to
index 9c2cb0828ed4bfd8350b688d93a69c4b21918ddf..303349ef11b02c4bc99ccd27d2ef1678e41034a7 100644 (file)
@@ -168,7 +168,7 @@ size_t fr_value_box_type_table_len = NUM_ELEMENTS(fr_value_box_type_table);
 #define network_min_size(_x) (fr_value_box_network_sizes[_x][0])
 #define network_max_size(_x) (fr_value_box_network_sizes[_x][1])
 static size_t const fr_value_box_network_sizes[FR_TYPE_MAX + 1][2] = {
-       [FR_TYPE_NULL]                  = {~0, 0},
+       [FR_TYPE_NULL]                          = {~0, 0},
 
        [FR_TYPE_STRING]                        = {0, ~0},
        [FR_TYPE_OCTETS]                        = {0, ~0},
index dd040b1c43538b32e162513a815bab562c84afa6..8649a069b3801ffe02a5790e7359489efa414f81 100644 (file)
@@ -234,7 +234,7 @@ static xlat_action_t xlat_client(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *
        fr_value_box_t  *client_ip = fr_dlist_next(in, field);
        fr_value_box_t  *vb;
 
-       if (client_ip) {
+       if (!fr_box_is_null(client_ip)) {
                if (fr_inet_pton(&ip, client_ip->vb_strvalue, -1, AF_UNSPEC, false, true) < 0) {
                        RDEBUG("Invalid client IP address \"%s\"", client_ip->vb_strvalue);
                        return XLAT_ACTION_FAIL;
diff --git a/src/tests/keywords/debug b/src/tests/keywords/debug
new file mode 100644 (file)
index 0000000..3d5c447
--- /dev/null
@@ -0,0 +1,34 @@
+#
+#  PRE: update if
+#
+
+update request {
+       &Tmp-Integer-0 := "%(debug:4)"
+}
+
+# Check debug level is now 4
+if ("%(debug:3)" != 4) {
+       test_fail
+}
+
+# Call with NULL arg, should report current level
+if ("%(debug:%{Tmp-String-8})" != 3) {
+       test_fail
+}
+
+# ...and again
+if ("%(debug:%{Tmp-String-8})" != 3) {
+       test_fail
+}
+
+# ...and again
+if ("%(debug:)" != 3) {
+       test_fail
+}
+
+# ...and again
+if ("%(debug:)" != 3) {
+       test_fail
+}
+
+success