BUG/MINOR: http_rules: fix errors paths in http_parse_redirect_rule()
http_parse_redirect_rule() doesn't perform enough checks around NULL
returning allocating functions.
Moreover, existing error paths don't perform cleanups. This could lead to
memory leaks.
Adding a few checks and a cleanup path to ensure memory errors are
properly handled and that no memory leaks occurs within the function
(already allocated structures are freed on error path).
It should partially fix GH #2130.
This patch depends on ("MINOR: proxy: add http_free_redirect_rule() function")
This could be backported up to 2.4. The patch is also relevant for
2.2 but "MINOR: proxy: add http_free_redirect_rule() function" would
need to be adapted first.
==
Backport notes:
-> For 2.2 only:
Replace:
(strcmp(args[cur_arg], "drop-query") == 0)
with:
(!strcmp(args[cur_arg],"drop-query"))
-> For 2.2 and 2.4:
Replace:
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query', 'ignore-empty' or 'append-slash' (was '%s')",
with:
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s')",
(cherry picked from commit 5313570605fdcf471e7286a68432830a2a1ca72f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 35b2d25318c735b61872a9652d7f2f3fba0ca4d3)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 443763835aa7bc2fe7783c925e4ea6550d30f6fc)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/http_rules.c b/src/http_rules.c
index 9de91a2..52b77c6 100644
--- a/src/http_rules.c
+++ b/src/http_rules.c
@@ -329,7 +329,7 @@
struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, struct proxy *curproxy,
const char **args, char **errmsg, int use_fmt, int dir)
{
- struct redirect_rule *rule;
+ struct redirect_rule *rule = NULL;
int cur_arg;
int type = REDIRECT_TYPE_NONE;
int code = 302;
@@ -390,7 +390,7 @@
memprintf(errmsg,
"'%s': unsupported HTTP code '%s' (must be one of 301, 302, 303, 307 or 308)",
args[cur_arg - 1], args[cur_arg]);
- return NULL;
+ goto err;
}
}
else if (strcmp(args[cur_arg], "drop-query") == 0) {
@@ -404,7 +404,7 @@
cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + cur_arg, errmsg);
if (!cond) {
memprintf(errmsg, "error in condition: %s", *errmsg);
- return NULL;
+ goto err;
}
break;
}
@@ -412,32 +412,32 @@
memprintf(errmsg,
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s')",
args[cur_arg]);
- return NULL;
+ goto err;
}
cur_arg++;
}
if (type == REDIRECT_TYPE_NONE) {
memprintf(errmsg, "redirection type expected ('prefix', 'location', or 'scheme')");
- return NULL;
+ goto err;
}
if (dir && type != REDIRECT_TYPE_LOCATION) {
memprintf(errmsg, "response only supports redirect type 'location'");
- return NULL;
+ goto err;
}
rule = calloc(1, sizeof(*rule));
- if (!rule) {
- memprintf(errmsg, "parsing [%s:%d]: out of memory.", file, linenum);
- return NULL;
- }
+ if (!rule)
+ goto out_of_memory;
rule->cond = cond;
LIST_INIT(&rule->rdr_fmt);
if (!use_fmt) {
/* old-style static redirect rule */
rule->rdr_str = strdup(destination);
+ if (!rule->rdr_str)
+ goto out_of_memory;
rule->rdr_len = strlen(destination);
}
else {
@@ -455,7 +455,7 @@
cap |= (dir ? SMP_VAL_BE_HRS_HDR : SMP_VAL_BE_HRQ_HDR);
if (!(type == REDIRECT_TYPE_PREFIX && destination[0] == '/' && destination[1] == '\0')) {
if (!parse_logformat_string(destination, curproxy, &rule->rdr_fmt, LOG_OPT_HTTP, cap, errmsg)) {
- return NULL;
+ goto err;
}
free(curproxy->conf.lfs_file);
curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
@@ -470,11 +470,15 @@
rule->cookie_len = strlen(cookie);
if (cookie_set) {
rule->cookie_str = malloc(rule->cookie_len + 10);
+ if (!rule->cookie_str)
+ goto out_of_memory;
memcpy(rule->cookie_str, cookie, rule->cookie_len);
memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
rule->cookie_len += 9;
} else {
rule->cookie_str = malloc(rule->cookie_len + 21);
+ if (!rule->cookie_str)
+ goto out_of_memory;
memcpy(rule->cookie_str, cookie, rule->cookie_len);
memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
rule->cookie_len += 20;
@@ -488,6 +492,18 @@
missing_arg:
memprintf(errmsg, "missing argument for '%s'", args[cur_arg]);
+ goto err;
+ out_of_memory:
+ memprintf(errmsg, "parsing [%s:%d]: out of memory.", file, linenum);
+ err:
+ if (rule)
+ http_free_redirect_rule(rule);
+ else if (cond) {
+ /* rule not yet allocated, but cond already is */
+ prune_acl_cond(cond);
+ free(cond);
+ }
+
return NULL;
}