]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
fixes for numerical key in xlats
authorAlan T. DeKok <aland@freeradius.org>
Fri, 13 Sep 2024 23:04:32 +0000 (19:04 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 13 Sep 2024 23:04:32 +0000 (19:04 -0400)
src/lib/unlang/foreach.c
src/tests/keywords/foreach-explode-key [new file with mode: 0644]

index 8783c5fc6e03e67afafb0ff1bfe5126b2fb10a39..85b7bb1a65e7a218bfcc9eb02c5319635e18f6d1 100644 (file)
@@ -221,17 +221,42 @@ static unlang_action_t unlang_foreach_next_old(rlm_rcode_t *p_result, request_t
        return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING);
 }
 
+static int unlang_foreach_xlat_key_update(request_t *request, unlang_frame_state_foreach_t *state)
+{
+       fr_value_box_t box;
+
+       RDEBUG("UPDATE");
+
+       fr_value_box_clear_value(&state->key->data);
+
+       fr_value_box(&box, state->index, false);
+
+       if (fr_value_box_cast(state->key, &state->key->data, state->key->vp_type, state->key->da, &box) < 0) {
+               RDEBUG("Failed casting 'foreach' key variable '%s' from %u", state->key->da->name, state->index);
+               return -1;
+       }
+
+       RDEBUG("KEY %pP", state->key);
+
+       return 0;
+}
+
+
 static unlang_action_t unlang_foreach_xlat_next(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
        unlang_frame_state_foreach_t    *state = talloc_get_type_abort(frame->state, unlang_frame_state_foreach_t);
        fr_value_box_t *box;
 
 next:
+       state->index++;
+
        box = fr_dcursor_next(&state->cursor);
        if (!box) {
                *p_result = frame->result;
                return UNLANG_ACTION_CALCULATE_RESULT;
        }
+       
+       if (unlang_foreach_xlat_key_update(request, state) < 0) goto next;
 
        fr_value_box_clear_value(&state->value->data);
        if (fr_value_box_cast(state->value, &state->value->data, state->value->vp_type, state->value->da, box) < 0) {
@@ -301,32 +326,23 @@ static unlang_action_t unlang_foreach_xlat_init(rlm_rcode_t *p_result, request_t
                return UNLANG_ACTION_CALCULATE_RESULT;
        }
 
+       if (unlang_foreach_xlat_key_update(request, state) < 0) {
+               *p_result = RLM_MODULE_FAIL;
+               return UNLANG_ACTION_CALCULATE_RESULT;
+       }
+
        frame->process = unlang_foreach_xlat_expanded;
        repeatable_set(frame);
 
        return UNLANG_ACTION_PUSHED_CHILD;
 }
 
-static int unlang_foreach_key_update(request_t *request, unlang_frame_state_foreach_t *state)
+static void unlang_foreach_attr_key_update(UNUSED request_t *request, unlang_frame_state_foreach_t *state)
 {
        fr_value_box_clear_value(&state->key->data);
-
-       if (tmpl_is_attr(state->vpt)) {
-               if (tmpl_dcursor_print(&FR_SBUFF_IN(state->buffer, BUFFER_SIZE), &state->cc) > 0) {
-                       fr_value_box_strdup(state->key, &state->key->data, NULL, state->buffer, false);
-               }
-       } else {
-               fr_value_box_t box;
-
-               fr_value_box(&box, state->index, false);
-
-               if (fr_value_box_cast(state->key, &state->key->data, state->key->vp_type, state->key->da, &box) < 0) {
-                       RDEBUG("Failed casting 'foreach' key variable '%s' from %u", state->key->da->name, state->index);
-                       return -1;
-               }
+       if (tmpl_dcursor_print(&FR_SBUFF_IN(state->buffer, BUFFER_SIZE), &state->cc) > 0) {
+               fr_value_box_strdup(state->key, &state->key->data, NULL, state->buffer, false);
        }
-
-       return 0;
 }
 
 static unlang_action_t unlang_foreach_attr_next(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
@@ -366,9 +382,7 @@ next:
        }
 
        if (state->key) {
-               state->index++;
-
-               if (unlang_foreach_key_update(request, state) < 0) goto next;
+               unlang_foreach_attr_key_update(request, state);
        }
 
        /*
@@ -450,10 +464,7 @@ static unlang_action_t unlang_foreach_attr_init(rlm_rcode_t *p_result, request_t
         *      Update the key with the current path or index.
         */
        if (state->key) {
-               if (unlang_foreach_key_update(request, state) < 0) {
-                       *p_result = RLM_MODULE_FAIL;
-                       return UNLANG_ACTION_CALCULATE_RESULT;                  
-               }
+               unlang_foreach_attr_key_update(request, state);
        }
 
        if (vp->vp_type == FR_TYPE_GROUP) {
@@ -547,18 +558,17 @@ static unlang_action_t unlang_foreach(rlm_rcode_t *p_result, request_t *request,
                }
                fr_assert(state->value != NULL);
 
-               if (tmpl_is_attr(gext->vpt)) {
-                       if (gext->key) {
-                               if (fr_pair_append_by_da(request->local_ctx, &state->key, &request->local_pairs, gext->key) < 0) {
-                                       REDEBUG("Failed creating %s", gext->key->name);
-                                       *p_result = RLM_MODULE_FAIL;
-                                       return UNLANG_ACTION_CALCULATE_RESULT;
-                               }
-                               fr_assert(state->key != NULL);
-
-                               MEM(state->buffer = talloc_array(state, char, BUFFER_SIZE));
+               if (gext->key) {
+                       if (fr_pair_append_by_da(request->local_ctx, &state->key, &request->local_pairs, gext->key) < 0) {
+                               REDEBUG("Failed creating %s", gext->key->name);
+                               *p_result = RLM_MODULE_FAIL;
+                               return UNLANG_ACTION_CALCULATE_RESULT;
                        }
-
+                       fr_assert(state->key != NULL);
+               }
+                       
+               if (tmpl_is_attr(gext->vpt)) {
+                       MEM(state->buffer = talloc_array(state, char, BUFFER_SIZE));
                        return unlang_foreach_attr_init(p_result, request, frame, state);
                }
 
diff --git a/src/tests/keywords/foreach-explode-key b/src/tests/keywords/foreach-explode-key
new file mode 100644 (file)
index 0000000..f48b7ca
--- /dev/null
@@ -0,0 +1,23 @@
+#
+#  PRE: foreach-explode
+#
+string input
+string result
+
+input = "a b c d e f"
+result = ""
+
+foreach uint32 key,string thing (%explode(%{input}, ' ')) {
+       result += thing
+       result += ':'
+       result += (string) key
+       result += ','
+}
+
+result -= ','
+
+if (result != "a:0,b:1,c:2,d:3,e:4,f:5") {
+       test_fail
+}
+
+success