]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
free conditions and children of "if" sections which were skipped
authorAlan T. DeKok <aland@freeradius.org>
Tue, 12 Jul 2022 21:03:38 +0000 (17:03 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 14 Jul 2022 14:04:02 +0000 (10:04 -0400)
and ensure that cf_section_free_children() doesn't free CONF_DATA,
as that's still needed.

src/lib/server/cf_file.c
src/lib/server/cf_util.c
src/lib/unlang/compile.c
src/lib/unlang/condition.c

index 8cb745e61c5e328a3e80f4a32cfe7eda4468557b..138242771df731b8a0f26e026471b641c3b3e11a 100644 (file)
@@ -1520,9 +1520,9 @@ static CONF_ITEM *process_if(cf_stack_t *stack)
         *      Now that the CONF_SECTION and condition are OK, add
         *      the condition to the CONF_SECTION.
         */
-       cf_data_add(cs, cond, NULL, false);
+       cf_data_add(cs, cond, NULL, true);
 #ifdef WITH_XLAT_COND
-       cf_data_add(cs, head, NULL, false);
+       cf_data_add(cs, head, NULL, true);
 #endif
        stack->ptr = ptr;
 
index 3cad91c80b7acdc6c0ec0e2c0c3350ba3189611b..1409a3b76e5530a3ace64b3ad8860b111944ae80 100644 (file)
@@ -2204,7 +2204,13 @@ void _cf_debug(CONF_ITEM const *ci)
  */
 void cf_item_free_children(CONF_ITEM *ci)
 {
-       fr_dlist_talloc_free(&ci->children);
-       TALLOC_FREE(ci->ident1);
-       TALLOC_FREE(ci->ident2);
+       CONF_ITEM *child = NULL;
+
+       while ((child = fr_dlist_next(&ci->children, child)) != NULL) {
+               if (child->type == CONF_ITEM_DATA) {
+                       continue;
+               }
+
+               child = fr_dlist_talloc_free_item(&ci->children, child);
+       }
 }
index a61dc7fadf0833b91bffd3fdccca803fe6f52cd3..38c6c4ac09e22ef0d5ac5559ce18710241adee46 100644 (file)
@@ -2220,6 +2220,18 @@ static unlang_t *compile_children(unlang_group_t *g, unlang_compile_t *unlang_ct
                                 *      So we skip this "elsif" or "else".
                                 */
                                if (skip_else) {
+                                       void *ptr;
+
+                                       /*
+                                        *      And manually free this.
+                                        */
+                                       ptr = cf_data_remove(subcs, fr_cond_t, NULL);
+                                       talloc_free(ptr);
+                                       ptr = cf_data_remove(subcs, xlat_exp_head_t, NULL);
+                                       talloc_free(ptr);
+
+                                       cf_section_free_children(subcs);
+
                                        cf_log_debug_prefix(ci, "Skipping contents of '%s' due to previous "
                                                            "'%s' being always being taken.",
                                                            name, skip_else);
@@ -3079,9 +3091,11 @@ static unlang_t *compile_if_subsection(unlang_t *parent, unlang_compile_t *unlan
                 *      Free the children, which frees any xlats,
                 *      conditions, etc. which were defined, but are
                 *      now entirely unused.
+                *
+                *      However, we still need to cache the conditions, as they will be accessed at run-time.
                 */
-               cf_section_free_children(cs);
                c = compile_empty(parent, unlang_ctx, cs, ext);
+               cf_section_free_children(cs);
 
        } else {
                fr_cond_iter_t  iter;
index e977c82360d5bc6fc88e7fc6378cb4dc806f42ff..da5ee314084770c0cf525298105288ae80ecc823 100644 (file)
@@ -107,10 +107,12 @@ static unlang_action_t unlang_if(rlm_rcode_t *p_result, request_t *request, unla
 
        /*
         *      If we always run this condition, then don't bother pushing anything onto the stack.
+        *
+        *      We still run this condition, even for "false" values, due to things like
+        *
+        *              if (0) { ... } elsif ....
         */
        if (gext->is_truthy) {
-               fr_assert(gext->value); /* otherwise it would have been omitted from the unlang tree */
-
                return unlang_group(p_result, request, frame);
        }