From: Alan T. DeKok Date: Thu, 21 Sep 2023 21:51:00 +0000 (-0400) Subject: brute-force delete local variables when leaving scope X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=099ec83df3a0a5063d4cf8fdf5efa7ec85b9fe65;p=thirdparty%2Ffreeradius-server.git brute-force delete local variables when leaving scope we will later move them to their own list, which will help a lot. --- diff --git a/src/lib/unlang/interpret.c b/src/lib/unlang/interpret.c index d6b791b3ac1..3caf49ba04f 100644 --- a/src/lib/unlang/interpret.c +++ b/src/lib/unlang/interpret.c @@ -210,6 +210,22 @@ int unlang_interpret_push(request_t *request, unlang_t const *instruction, return 0; } +typedef struct { + fr_dict_t const *dict; + request_t *request; +} unlang_variable_ref_t; + +static int _local_variables_free(unlang_variable_ref_t *ref) +{ + fr_pair_list_foreach(&ref->request->request_pairs, vp) { + if (vp->da->dict == ref->dict) { + (void) fr_pair_delete(&ref->request->request_pairs, vp); + } + } + + return 0; +} + /** Push the children of the current frame onto a new frame onto the stack * * @param[in] request to push the frame onto. @@ -227,6 +243,7 @@ unlang_action_t unlang_interpret_push_children(rlm_rcode_t *p_result, request_t unlang_stack_t *stack = request->stack; unlang_stack_frame_t *frame = &stack->frame[stack->depth]; /* Quiet static analysis */ unlang_group_t *g; + unlang_variable_ref_t *ref; fr_assert(unlang_ops[frame->instruction->type].debug_braces); @@ -247,6 +264,22 @@ unlang_action_t unlang_interpret_push_children(rlm_rcode_t *p_result, request_t return UNLANG_ACTION_STOP_PROCESSING; } + if (!g->variables) return UNLANG_ACTION_PUSHED_CHILD; + + if (!frame->state) { + MEM(ref = talloc(stack, unlang_variable_ref_t)); + frame->state = ref; + } else { + MEM(ref = talloc(frame->state, unlang_variable_ref_t)); + } + + /* + * Set the destructor to clean up local variables. + */ + ref->dict = g->variables->dict; + ref->request = request; + talloc_set_destructor(ref, _local_variables_free); + return UNLANG_ACTION_PUSHED_CHILD; } diff --git a/src/tests/keywords/local-variable b/src/tests/keywords/local-variable index d231e87e53d..c92c1f6f80a 100644 --- a/src/tests/keywords/local-variable +++ b/src/tests/keywords/local-variable @@ -1,11 +1,26 @@ &Filter-Id := 2 +if !(&request.[#] == 4) { + test_fail +} + group { uint32 foo &foo := 1 &Filter-Id := &foo + + # + # For now, local variables are in the request. + # + if !(&request.[#] == 6) { + test_fail + } +} # leaving this scope automatically deletes &foo + +if !(&request.[#] == 5) { + test_fail } if !(&Filter-Id == "1") {