]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
brute-force delete local variables when leaving scope
authorAlan T. DeKok <aland@freeradius.org>
Thu, 21 Sep 2023 21:51:00 +0000 (17:51 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 23 Sep 2023 11:57:16 +0000 (07:57 -0400)
we will later move them to their own list, which will help a lot.

src/lib/unlang/interpret.c
src/tests/keywords/local-variable

index d6b791b3ac18aba2c163da71cb96fdbf179c580b..3caf49ba04f936f23e0c89eec8238fa1971c8c27 100644 (file)
@@ -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;
 }
 
index d231e87e53d43b378d2d8d50a737ed02791ec3bc..c92c1f6f80a2ef120355c0ae7dc9bf1726e91209 100644 (file)
@@ -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") {