From 0e53d875c78550b91a645d40f28af978af864d69 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 27 Jul 2026 12:15:11 +0200 Subject: [PATCH] BUG/MINOR: http-rules: fix release of a failed "set-cookie-fmt" redirect rule is a union holding either an ist (set-cookie, clear-cookie) or a log-format expression (set-cookie-fmt), and http_free_redirect_rule() picks the member to release from the REDIRECT_FLAG_COOKIE_FMT flag: if ((rdr->flags & REDIRECT_FLAG_COOKIE_FMT)) lf_expr_deinit(&rdr->cookie.fmt); else istfree(&rdr->cookie.str); But http_parse_redirect_rule() accumulates the flags in a local variable and only assigns them with "rule->flags = flags" at the very end, once everything succeeded. So when the log-format string of a "set-cookie-fmt" fails to parse, the "goto err" runs http_free_redirect_rule() on a rule whose ->flags is still 0, and istfree() is called on the member while is the live one, leading the process to crash. Let's init the rule members (code, type and flags) as soon as possible, so after the rule allocation. And REDIRECT_FLAG_COOKIE_FMT flag is not set directly on the rule's flags, before the log-format string parsing. This only happens while parsing an invalid configuration, hence no security impact, but a configuration checker must report errors rather than abort. This should be backported to all versions having "set-cookie-fmt", so 2.9 and above. --- src/http_rules.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/http_rules.c b/src/http_rules.c index ee4543083..05801b1f3 100644 --- a/src/http_rules.c +++ b/src/http_rules.c @@ -456,6 +456,10 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st if (!rule) goto out_of_memory; rule->cond = cond; + rule->type = type; + rule->code = code; + rule->flags = flags; + LIST_INIT(&rule->list); lf_expr_init(&rule->rdr_fmt); if (!use_fmt) { @@ -478,7 +482,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st cap |= (dir ? SMP_VAL_FE_HRS_HDR : SMP_VAL_FE_HRQ_HDR); if (curproxy->cap & PR_CAP_BE) cap |= (dir ? SMP_VAL_BE_HRS_HDR : SMP_VAL_BE_HRQ_HDR); - if (!(type == REDIRECT_TYPE_PREFIX && destination[0] == '/' && destination[1] == '\0')) { + if (!(rule->type == REDIRECT_TYPE_PREFIX && destination[0] == '/' && destination[1] == '\0')) { if (!parse_logformat_string(destination, curproxy, &rule->rdr_fmt, LOG_OPT_HTTP, cap, errmsg)) { goto err; } @@ -500,6 +504,8 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st else if (cookie_set == 2) { // set-cookie-fmt int cap = 0; + rule->flags |= REDIRECT_FLAG_COOKIE_FMT; + lf_expr_init(&rule->cookie.fmt); curproxy->conf.args.ctx = ARGC_RDR; if (curproxy->cap & PR_CAP_FE) @@ -512,8 +518,6 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st if (!parse_logformat_string(trash.area, curproxy, &rule->cookie.fmt, LOG_OPT_HTTP, cap, errmsg)) { goto err; } - - flags |= REDIRECT_FLAG_COOKIE_FMT; } else { // clear-cookie rule->cookie.str = istalloc(cookie_len+20); @@ -523,10 +527,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st istcat(&rule->cookie.str, ist2("; path=/; Max-Age=0;", 20), cookie_len+21); } } - rule->type = type; - rule->code = code; - rule->flags = flags; - LIST_INIT(&rule->list); + return rule; missing_arg: -- 2.47.3