From: Alan T. DeKok Date: Wed, 20 Sep 2023 20:51:14 +0000 (-0400) Subject: add and use unlang_interpret_push_children() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0192b02c74832a1c4d03b3dbd79d55b6ec2b6537;p=thirdparty%2Ffreeradius-server.git add and use unlang_interpret_push_children() which pushes the children of the current frame. This wrapper function simplifies a bunch of keyword code. subrequest does not use this, as it pushes another frame before pushing the children. Perhaps that should instead be a resume function? --- diff --git a/src/lib/unlang/call.c b/src/lib/unlang/call.c index 36ef94a064e..83074ae6c80 100644 --- a/src/lib/unlang/call.c +++ b/src/lib/unlang/call.c @@ -52,22 +52,13 @@ static unlang_action_t unlang_call_finalize(UNUSED rlm_rcode_t *p_result, reques static unlang_action_t unlang_call_children(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame) { - unlang_group_t *g = unlang_generic_to_group(frame->instruction); - - fr_assert(g->children); + frame_repeat(frame, unlang_call_finalize); /* * Push the contents of the call { } section onto the stack. * This gets executed after the server returns. */ - if (unlang_interpret_push(request, g->children, frame->result, - UNLANG_NEXT_SIBLING, UNLANG_SUB_FRAME) < 0) { - *p_result = RLM_MODULE_FAIL; - return UNLANG_ACTION_STOP_PROCESSING; - } - - frame_repeat(frame, unlang_call_finalize); - return UNLANG_ACTION_PUSHED_CHILD; + return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING); } diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index 078360595be..1d92c9049d1 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -1719,6 +1719,8 @@ static unlang_t *compile_variable(unlang_t *parent, unlang_compile_t *unlang_ctx .local = true, }; + fr_assert(unlang_ops[parent->type].debug_braces); + /* * The variables exist in the parent block. */ diff --git a/src/lib/unlang/foreach.c b/src/lib/unlang/foreach.c index 68938e1d12b..59ae416e8a3 100644 --- a/src/lib/unlang/foreach.c +++ b/src/lib/unlang/foreach.c @@ -78,7 +78,6 @@ static int _free_unlang_frame_state_foreach(unlang_frame_state_foreach_t *state) static unlang_action_t unlang_foreach_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); - unlang_group_t *g = unlang_generic_to_group(frame->instruction); fr_pair_t *vp; if (is_stack_unwinding_to_break(request->stack)) return UNLANG_ACTION_CALCULATE_RESULT; @@ -111,17 +110,12 @@ static unlang_action_t unlang_foreach_next(rlm_rcode_t *p_result, request_t *req RDEBUG2("# looping with: Foreach-Variable-%d = %pV", state->depth, &vp->data); #endif + repeatable_set(frame); + /* * Push the child, and yield for a later return. */ - if (unlang_interpret_push(request, g->children, frame->result, UNLANG_NEXT_SIBLING, UNLANG_SUB_FRAME) < 0) { - *p_result = RLM_MODULE_FAIL; - return UNLANG_ACTION_STOP_PROCESSING; - } - - repeatable_set(frame); - - return UNLANG_ACTION_PUSHED_CHILD; + return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING); } @@ -217,17 +211,12 @@ static unlang_action_t unlang_foreach(rlm_rcode_t *p_result, request_t *request, frame->process = unlang_foreach_next; + repeatable_set(frame); + /* * Push the child, and go process it. */ - if (unlang_interpret_push(request, g->children, frame->result, UNLANG_NEXT_SIBLING, UNLANG_SUB_FRAME) < 0) { - *p_result = RLM_MODULE_FAIL; - return UNLANG_ACTION_STOP_PROCESSING; - } - - repeatable_set(frame); - - return UNLANG_ACTION_PUSHED_CHILD; + return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING); } static unlang_action_t unlang_break(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame) diff --git a/src/lib/unlang/group.c b/src/lib/unlang/group.c index 7f4e4a4484b..d94120dd86f 100644 --- a/src/lib/unlang/group.c +++ b/src/lib/unlang/group.c @@ -29,24 +29,7 @@ RCSID("$Id$") unlang_action_t unlang_group(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame) { - unlang_group_t *g = unlang_generic_to_group(frame->instruction); - - /* - * The compiler catches most of these, EXCEPT for the - * top-level 'recv Access-Request' etc. Which can exist, - * and can be empty. - */ - if (!g->children) { - RDEBUG2(""); - return UNLANG_ACTION_EXECUTE_NEXT; - } - - if (unlang_interpret_push(request, g->children, frame->result, UNLANG_NEXT_SIBLING, UNLANG_SUB_FRAME) < 0) { - *p_result = RLM_MODULE_FAIL; - return UNLANG_ACTION_STOP_PROCESSING; - } - - return UNLANG_ACTION_PUSHED_CHILD; + return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING); } static unlang_action_t unlang_policy(rlm_rcode_t *result, request_t *request, unlang_stack_frame_t *frame) diff --git a/src/lib/unlang/interpret.c b/src/lib/unlang/interpret.c index da7ce7d316d..d6b791b3ac1 100644 --- a/src/lib/unlang/interpret.c +++ b/src/lib/unlang/interpret.c @@ -210,6 +210,46 @@ int unlang_interpret_push(request_t *request, unlang_t const *instruction, return 0; } +/** Push the children of the current frame onto a new frame onto the stack + * + * @param[in] request to push the frame onto. + * @param[in] default_rcode The default result. + * @param[in] do_next_sibling Whether to only execute the first node in the #unlang_t program + * or to execute subsequent nodes. + * @return + * - UNLANG_ACTION_PUSHED_CHILD on success. + * - UNLANG_ACTION_EXECUTE_NEXT do nothing, but just go to the next sibling instruction + * - UNLANG_ACTION_STOP_PROCESSING, fatal error, usually stack overflow. + */ +unlang_action_t unlang_interpret_push_children(rlm_rcode_t *p_result, request_t *request, + rlm_rcode_t default_rcode, bool do_next_sibling) +{ + unlang_stack_t *stack = request->stack; + unlang_stack_frame_t *frame = &stack->frame[stack->depth]; /* Quiet static analysis */ + unlang_group_t *g; + + fr_assert(unlang_ops[frame->instruction->type].debug_braces); + + g = unlang_generic_to_group(frame->instruction); + + /* + * The compiler catches most of these, EXCEPT for the + * top-level 'recv Access-Request' etc. Which can exist, + * and can be empty. + */ + if (!g->children) { + RDEBUG2(""); + return UNLANG_ACTION_EXECUTE_NEXT; + } + + if (unlang_interpret_push(request, g->children, default_rcode, do_next_sibling, UNLANG_SUB_FRAME) < 0) { + *p_result = RLM_MODULE_FAIL; + return UNLANG_ACTION_STOP_PROCESSING; + } + + return UNLANG_ACTION_PUSHED_CHILD; +} + static void instruction_timeout_handler(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *ctx); /** Update the current result after each instruction, and after popping each stack frame diff --git a/src/lib/unlang/limit.c b/src/lib/unlang/limit.c index aececa084d9..670851dd2fd 100644 --- a/src/lib/unlang/limit.c +++ b/src/lib/unlang/limit.c @@ -66,25 +66,20 @@ static unlang_action_t unlang_limit_resume_done(UNUSED rlm_rcode_t *p_result, UN static unlang_action_t unlang_limit_enforce(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame) { unlang_frame_state_limit_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_limit_t); - unlang_group_t *g; + unlang_action_t action; state->thread = unlang_thread_instance(frame->instruction); fr_assert(state->thread != NULL); if (state->thread->active_callers >= state->limit) return UNLANG_ACTION_FAIL; - g = unlang_generic_to_group(frame->instruction); - - if (unlang_interpret_push(request, g->children, frame->result, UNLANG_NEXT_STOP, UNLANG_SUB_FRAME) < 0) { - *p_result = RLM_MODULE_FAIL; - return UNLANG_ACTION_STOP_PROCESSING; - } + frame_repeat(frame, unlang_limit_resume_done); - state->thread->active_callers++; + action = unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_STOP); - frame_repeat(frame, unlang_limit_resume_done); + state->thread->active_callers += (action == UNLANG_ACTION_PUSHED_CHILD); - return UNLANG_ACTION_PUSHED_CHILD; + return action; } static unlang_action_t unlang_limit_xlat_done(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame) diff --git a/src/lib/unlang/timeout.c b/src/lib/unlang/timeout.c index c5b565dd87e..c5bd1325eeb 100644 --- a/src/lib/unlang/timeout.c +++ b/src/lib/unlang/timeout.c @@ -74,7 +74,6 @@ static unlang_action_t unlang_timeout_resume_done(UNUSED rlm_rcode_t *p_result, static unlang_action_t unlang_timeout_set(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame) { unlang_frame_state_timeout_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_timeout_t); - unlang_group_t *g; fr_time_t timeout; /* @@ -87,13 +86,6 @@ static unlang_action_t unlang_timeout_set(rlm_rcode_t *p_result, request_t *requ if (fr_event_timer_at(state, unlang_interpret_event_list(request), &state->ev, timeout, unlang_timeout_handler, state) < 0) { RPEDEBUG("Failed inserting event"); - goto fail; - } - - g = unlang_generic_to_group(frame->instruction); - - if (unlang_interpret_push(request, g->children, frame->result, UNLANG_NEXT_STOP, UNLANG_SUB_FRAME) < 0) { - fail: *p_result = RLM_MODULE_FAIL; return UNLANG_ACTION_STOP_PROCESSING; } @@ -101,7 +93,7 @@ static unlang_action_t unlang_timeout_set(rlm_rcode_t *p_result, request_t *requ frame_repeat(frame, unlang_timeout_resume_done); state->success = true; - return UNLANG_ACTION_PUSHED_CHILD; + return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_STOP); } static unlang_action_t unlang_timeout_xlat_done(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame) diff --git a/src/lib/unlang/unlang_priv.h b/src/lib/unlang/unlang_priv.h index dfb1ab1f8dd..e01d6f02b87 100644 --- a/src/lib/unlang/unlang_priv.h +++ b/src/lib/unlang/unlang_priv.h @@ -565,6 +565,10 @@ int unlang_interpret_push(request_t *request, unlang_t const *instruction, rlm_rcode_t default_rcode, bool do_next_sibling, bool top_frame) CC_HINT(warn_unused_result); +int unlang_interpret_push_children(rlm_rcode_t *p_result, request_t *request, + rlm_rcode_t default_rcode, bool do_next_sibling) + CC_HINT(warn_unused_result); + int unlang_op_init(void); void unlang_op_free(void);