mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 07:37:02 +02:00
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')",
This commit is contained in:
parent
7abc9224a6
commit
5313570605
@ -345,7 +345,7 @@ void http_free_redirect_rule(struct redirect_rule *rdr)
|
|||||||
struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, struct proxy *curproxy,
|
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)
|
const char **args, char **errmsg, int use_fmt, int dir)
|
||||||
{
|
{
|
||||||
struct redirect_rule *rule;
|
struct redirect_rule *rule = NULL;
|
||||||
int cur_arg;
|
int cur_arg;
|
||||||
int type = REDIRECT_TYPE_NONE;
|
int type = REDIRECT_TYPE_NONE;
|
||||||
int code = 302;
|
int code = 302;
|
||||||
@ -406,7 +406,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
memprintf(errmsg,
|
memprintf(errmsg,
|
||||||
"'%s': unsupported HTTP code '%s' (must be one of 301, 302, 303, 307 or 308)",
|
"'%s': unsupported HTTP code '%s' (must be one of 301, 302, 303, 307 or 308)",
|
||||||
args[cur_arg - 1], args[cur_arg]);
|
args[cur_arg - 1], args[cur_arg]);
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(args[cur_arg], "drop-query") == 0) {
|
else if (strcmp(args[cur_arg], "drop-query") == 0) {
|
||||||
@ -423,7 +423,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + cur_arg, errmsg);
|
cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + cur_arg, errmsg);
|
||||||
if (!cond) {
|
if (!cond) {
|
||||||
memprintf(errmsg, "error in condition: %s", *errmsg);
|
memprintf(errmsg, "error in condition: %s", *errmsg);
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -431,32 +431,32 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
memprintf(errmsg,
|
memprintf(errmsg,
|
||||||
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query', 'ignore-empty' or 'append-slash' (was '%s')",
|
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query', 'ignore-empty' or 'append-slash' (was '%s')",
|
||||||
args[cur_arg]);
|
args[cur_arg]);
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
cur_arg++;
|
cur_arg++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == REDIRECT_TYPE_NONE) {
|
if (type == REDIRECT_TYPE_NONE) {
|
||||||
memprintf(errmsg, "redirection type expected ('prefix', 'location', or 'scheme')");
|
memprintf(errmsg, "redirection type expected ('prefix', 'location', or 'scheme')");
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir && type != REDIRECT_TYPE_LOCATION) {
|
if (dir && type != REDIRECT_TYPE_LOCATION) {
|
||||||
memprintf(errmsg, "response only supports redirect type 'location'");
|
memprintf(errmsg, "response only supports redirect type 'location'");
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rule = calloc(1, sizeof(*rule));
|
rule = calloc(1, sizeof(*rule));
|
||||||
if (!rule) {
|
if (!rule)
|
||||||
memprintf(errmsg, "parsing [%s:%d]: out of memory.", file, linenum);
|
goto out_of_memory;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
rule->cond = cond;
|
rule->cond = cond;
|
||||||
LIST_INIT(&rule->rdr_fmt);
|
LIST_INIT(&rule->rdr_fmt);
|
||||||
|
|
||||||
if (!use_fmt) {
|
if (!use_fmt) {
|
||||||
/* old-style static redirect rule */
|
/* old-style static redirect rule */
|
||||||
rule->rdr_str = strdup(destination);
|
rule->rdr_str = strdup(destination);
|
||||||
|
if (!rule->rdr_str)
|
||||||
|
goto out_of_memory;
|
||||||
rule->rdr_len = strlen(destination);
|
rule->rdr_len = strlen(destination);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -474,7 +474,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
cap |= (dir ? SMP_VAL_BE_HRS_HDR : SMP_VAL_BE_HRQ_HDR);
|
cap |= (dir ? SMP_VAL_BE_HRS_HDR : SMP_VAL_BE_HRQ_HDR);
|
||||||
if (!(type == REDIRECT_TYPE_PREFIX && destination[0] == '/' && destination[1] == '\0')) {
|
if (!(type == REDIRECT_TYPE_PREFIX && destination[0] == '/' && destination[1] == '\0')) {
|
||||||
if (!parse_logformat_string(destination, curproxy, &rule->rdr_fmt, LOG_OPT_HTTP, cap, errmsg)) {
|
if (!parse_logformat_string(destination, curproxy, &rule->rdr_fmt, LOG_OPT_HTTP, cap, errmsg)) {
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
free(curproxy->conf.lfs_file);
|
free(curproxy->conf.lfs_file);
|
||||||
curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
|
curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
|
||||||
@ -489,11 +489,15 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
rule->cookie_len = strlen(cookie);
|
rule->cookie_len = strlen(cookie);
|
||||||
if (cookie_set) {
|
if (cookie_set) {
|
||||||
rule->cookie_str = malloc(rule->cookie_len + 10);
|
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, cookie, rule->cookie_len);
|
||||||
memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
|
memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
|
||||||
rule->cookie_len += 9;
|
rule->cookie_len += 9;
|
||||||
} else {
|
} else {
|
||||||
rule->cookie_str = malloc(rule->cookie_len + 21);
|
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, cookie, rule->cookie_len);
|
||||||
memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
|
memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
|
||||||
rule->cookie_len += 20;
|
rule->cookie_len += 20;
|
||||||
@ -507,6 +511,18 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
|
|
||||||
missing_arg:
|
missing_arg:
|
||||||
memprintf(errmsg, "missing argument for '%s'", args[cur_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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user