From: Alan T. DeKok Date: Tue, 12 Jul 2022 21:03:38 +0000 (-0400) Subject: free conditions and children of "if" sections which were skipped X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=089201c19dc6a6508391737056907b053c3ffa05;p=thirdparty%2Ffreeradius-server.git free conditions and children of "if" sections which were skipped and ensure that cf_section_free_children() doesn't free CONF_DATA, as that's still needed. --- diff --git a/src/lib/server/cf_file.c b/src/lib/server/cf_file.c index 8cb745e61c5..138242771df 100644 --- a/src/lib/server/cf_file.c +++ b/src/lib/server/cf_file.c @@ -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; diff --git a/src/lib/server/cf_util.c b/src/lib/server/cf_util.c index 3cad91c80b7..1409a3b76e5 100644 --- a/src/lib/server/cf_util.c +++ b/src/lib/server/cf_util.c @@ -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); + } } diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index a61dc7fadf0..38c6c4ac09e 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -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; diff --git a/src/lib/unlang/condition.c b/src/lib/unlang/condition.c index e977c82360d..da5ee314084 100644 --- a/src/lib/unlang/condition.c +++ b/src/lib/unlang/condition.c @@ -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); }