MEDIUM: tools: improve time format error detection

As reported in GH issue #109 and in discourse issue
https://discourse.haproxy.org/t/haproxy-returns-408-or-504-error-when-timeout-client-value-is-every-25d
the time parser doesn't error on overflows nor underflows. This is a
recurring problem which additionally has the bad taste of taking a long
time before hitting the user.

This patch makes parse_time_err() return special error codes for overflows
and underflows, and adds the control in the call places to report suitable
errors depending on the requested unit. In practice, underflows are almost
never returned as the parsing function takes care of rounding values up,
so this might possibly happen on 64-bit overflows returning exactly zero
after rounding though. It is not really possible to cut the patch into
pieces as it changes the function's API, hence all callers.

Tests were run on about every relevant part (cookie maxlife/maxidle,
server inter, stats timeout, timeout*, cli's set timeout command,
tcp-request/response inspect-delay).
This commit is contained in:
Willy Tarreau 2019-06-07 19:00:37 +02:00
parent b65717fa55
commit 9faebe34cd
15 changed files with 332 additions and 47 deletions

View File

@ -737,6 +737,10 @@ extern time_t my_timegm(const struct tm *tm);
extern const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags);
extern const char *parse_size_err(const char *text, unsigned *ret);
/* special return values for the time parser */
#define PARSE_TIME_UNDER ((char *)1)
#define PARSE_TIME_OVER ((char *)2)
/* unit flags to pass to parse_time_err */
#define TIME_UNIT_US 0x0000
#define TIME_UNIT_MS 0x0001

View File

@ -222,8 +222,11 @@ int make_arg_list(const char *in, int len, uint64_t mask, struct arg **argp,
goto empty_err;
ptr_err = parse_time_err(word, &uint, TIME_UNIT_MS);
if (ptr_err)
if (ptr_err) {
if (ptr_err == PARSE_TIME_OVER || ptr_err == PARSE_TIME_UNDER)
ptr_err = word;
goto parse_err;
}
arg->data.sint = uint;
arg->type = ARGT_SINT;
break;

View File

@ -263,9 +263,21 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
}
res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
if (res) {
if (res == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 65535 ms.\n",
file, linenum, args[1], args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
file, linenum, args[1], args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
file, linenum, *res, args[0]);
file, linenum, *res, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
@ -942,15 +954,21 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
}
err = parse_time_err(args[1], &val, TIME_UNIT_MS);
if (err) {
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[1], args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
}
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
file, linenum, args[1], args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
}
else if (err) {
ha_alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
}
global.max_spread_checks = val;
if (global.max_spread_checks < 0) {
ha_alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
}
}
else if (strcmp(args[0], "cpu-map") == 0) {
/* map a process list to a CPU set */

View File

@ -1067,7 +1067,19 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
}
res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
if (res) {
if (res == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
file, linenum, args[cur_arg+1], args[cur_arg]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
file, linenum, args[cur_arg+1], args[cur_arg]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
file, linenum, *res, args[cur_arg]);
err_code |= ERR_ALERT | ERR_FATAL;
@ -1087,8 +1099,21 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
goto out;
}
res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
if (res) {
if (res == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
file, linenum, args[cur_arg+1], args[cur_arg]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
file, linenum, args[cur_arg+1], args[cur_arg]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
file, linenum, *res, args[cur_arg]);
err_code |= ERR_ALERT | ERR_FATAL;
@ -1932,8 +1957,20 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
unsigned interval;
err = parse_time_err(args[2], &interval, TIME_UNIT_S);
if (err) {
ha_alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to stats refresh interval, maximum value is 2147483647 s (~68 years).\n",
file, linenum, args[2]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to stats refresh interval, minimum non-null value is 1 s.\n",
file, linenum, args[2]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to stats refresh interval.\n",
file, linenum, *err);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
@ -3374,7 +3411,19 @@ stats_error_parsing:
goto out;
}
err = parse_time_err(args[1], &val, TIME_UNIT_MS);
if (err) {
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to grace time, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to grace time, minimum non-null value is 1 ms.\n",
file, linenum, args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err) {
ha_alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
file, linenum, *err);
err_code |= ERR_ALERT | ERR_FATAL;

View File

@ -1203,7 +1203,19 @@ resolv_out:
goto out;
}
res = parse_time_err(args[2], &time, TIME_UNIT_MS);
if (res) {
if (res == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[1], args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
file, linenum, args[1], args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
file, linenum, *res, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
@ -1283,7 +1295,19 @@ resolv_out:
goto out;
}
res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
if (res) {
if (res == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s %s>, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[2], args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s %s>, minimum non-null value is 1 ms.\n",
file, linenum, args[2], args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
file, linenum, *res, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
@ -1459,14 +1483,21 @@ int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
goto out;
}
res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
if (res) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
file, linenum, *res, args[0]);
if (res == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s %s>, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[2], args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (timeout_mail <= 0) {
ha_alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
else if (res == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s %s>, minimum non-null value is 1 ms.\n",
file, linenum, args[2], args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
file, linenum, *res, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}

View File

@ -309,7 +309,17 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
unsigned timeout;
const char *res = parse_time_err(args[2], &timeout, TIME_UNIT_MS);
if (res) {
if (res == PARSE_TIME_OVER) {
memprintf(err, "timer overflow in argument '%s' to '%s %s' (maximum value is 2147483647 ms or ~24.8 days)",
args[2], args[0], args[1]);
return -1;
}
else if (res == PARSE_TIME_UNDER) {
memprintf(err, "timer underflow in argument '%s' to '%s %s' (minimum non-null value is 1 ms)",
args[2], args[0], args[1]);
return -1;
}
else if (res) {
memprintf(err, "'%s %s' : unexpected character '%c'", args[0], args[1], *res);
return -1;
}

View File

@ -3482,7 +3482,19 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
goto out;
}
res = parse_time_err(args[2], &timeout, TIME_UNIT_MS);
if (res) {
if (res == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s %s>, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[2], args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s %s>, minimum non-null value is 1 ms.\n",
file, linenum, args[2], args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (res) {
ha_alert("parsing [%s:%d] : unexpected character '%c' in 'timeout %s'.\n",
file, linenum, *res, args[1]);
err_code |= ERR_ALERT | ERR_FATAL;

View File

@ -8073,7 +8073,17 @@ static int hlua_read_timeout(char **args, int section_type, struct proxy *curpx,
const char *error;
error = parse_time_err(args[1], timeout, TIME_UNIT_MS);
if (error && *error != '\0') {
if (error == PARSE_TIME_OVER) {
memprintf(err, "timer overflow in argument <%s> to <%s> (maximum value is 2147483647 ms or ~24.8 days)",
args[1], args[0]);
return -1;
}
else if (error == PARSE_TIME_UNDER) {
memprintf(err, "timer underflow in argument <%s> to <%s> (minimum non-null value is 1 ms)",
args[1], args[0]);
return -1;
}
else if (error) {
memprintf(err, "%s: invalid timeout", args[0]);
return -1;
}

View File

@ -1816,7 +1816,17 @@ static int bind_parse_tcp_ut(char **args, int cur_arg, struct proxy *px, struct
}
ptr = parse_time_err(args[cur_arg + 1], &timeout, TIME_UNIT_MS);
if (ptr) {
if (ptr == PARSE_TIME_OVER) {
memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)",
args[cur_arg+1], args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
else if (ptr == PARSE_TIME_UNDER) {
memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)",
args[cur_arg+1], args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
else if (ptr) {
memprintf(err, "'%s' : expects a positive delay in milliseconds", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
@ -1891,7 +1901,17 @@ static int srv_parse_tcp_ut(char **args, int *cur_arg, struct proxy *px, struct
}
ptr = parse_time_err(args[*cur_arg + 1], &timeout, TIME_UNIT_MS);
if (ptr) {
if (ptr == PARSE_TIME_OVER) {
memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)",
args[*cur_arg+1], args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
else if (ptr == PARSE_TIME_UNDER) {
memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)",
args[*cur_arg+1], args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
else if (ptr) {
memprintf(err, "'%s' : expects a positive delay in milliseconds", args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
}

View File

@ -275,7 +275,17 @@ static int proxy_parse_timeout(char **args, int section, struct proxy *proxy,
}
res = parse_time_err(args[1], &timeout, TIME_UNIT_MS);
if (res) {
if (res == PARSE_TIME_OVER) {
memprintf(err, "timer overflow in argument '%s' to 'timeout %s' (maximum value is 2147483647 ms or ~24.8 days)",
args[1], name);
return -1;
}
else if (res == PARSE_TIME_UNDER) {
memprintf(err, "timer underflow in argument '%s' to 'timeout %s' (minimum non-null value is 1 ms)",
args[1], name);
return -1;
}
else if (res) {
memprintf(err, "unexpected character '%c' in 'timeout %s'", *res, name);
return -1;
}
@ -1056,7 +1066,17 @@ static int proxy_parse_hard_stop_after(char **args, int section_type, struct pro
return -1;
}
res = parse_time_err(args[1], &global.hard_stop_after, TIME_UNIT_MS);
if (res) {
if (res == PARSE_TIME_OVER) {
memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)",
args[1], args[0]);
return -1;
}
else if (res == PARSE_TIME_UNDER) {
memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)",
args[1], args[0]);
return -1;
}
else if (res) {
memprintf(err, "unexpected character '%c' in argument to <%s>.\n", *res, args[0]);
return -1;
}

View File

@ -404,7 +404,17 @@ static int srv_parse_pool_purge_delay(char **args, int *cur_arg, struct proxy *c
return ERR_ALERT | ERR_FATAL;
}
res = parse_time_err(arg, &time, TIME_UNIT_MS);
if (res) {
if (res == PARSE_TIME_OVER) {
memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)",
args[*cur_arg+1], args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
else if (res == PARSE_TIME_UNDER) {
memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)",
args[*cur_arg+1], args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
else if (res) {
memprintf(err, "unexpected character '%c' in argument to <%s>.\n",
*res, args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
@ -2305,7 +2315,20 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
while (*args[cur_arg]) {
if (!strcmp(args[cur_arg], "agent-inter")) {
const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
if (err) {
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err) {
ha_alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
file, linenum, *err, newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
@ -2530,7 +2553,20 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
}
else if (!strcmp(args[cur_arg], "inter")) {
const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
if (err) {
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err) {
ha_alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
file, linenum, *err, newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
@ -2547,7 +2583,20 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
}
else if (!strcmp(args[cur_arg], "fastinter")) {
const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
if (err) {
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
file, linenum, *err, newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
@ -2564,7 +2613,20 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
}
else if (!strcmp(args[cur_arg], "downinter")) {
const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
if (err) {
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err) {
ha_alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
file, linenum, *err, newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
@ -2611,7 +2673,20 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
else if (!strcmp(args[cur_arg], "slowstart")) {
/* slowstart is stored in seconds */
const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
if (err) {
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.\n",
file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err) {
ha_alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
file, linenum, *err, newsrv->id);
err_code |= ERR_ALERT | ERR_FATAL;

View File

@ -9065,7 +9065,17 @@ static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy
}
res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
if (res) {
if (res == PARSE_TIME_OVER) {
memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
args[1], args[0]);
return -1;
}
else if (res == PARSE_TIME_UNDER) {
memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
args[1], args[0]);
return -1;
}
else if (res) {
memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
return -1;
}

View File

@ -2032,12 +2032,15 @@ int strl2llrc_dotted(const char *text, int len, long long *ret)
* The value is returned in <ret> if everything is fine, and a NULL is returned
* by the function. In case of error, a pointer to the error is returned and
* <ret> is left untouched. Values are automatically rounded up when needed.
* Values resulting in values larger than or equal to 2^31 after conversion are
* reported as an overflow as value PARSE_TIME_OVER. Non-null values resulting
* in an underflow are reported as an underflow as value PARSE_TIME_UNDER.
*/
const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags)
{
unsigned imult, idiv;
unsigned omult, odiv;
unsigned value;
unsigned long long imult, idiv;
unsigned long long omult, odiv;
unsigned long long value, result;
omult = odiv = 1;
@ -2100,8 +2103,12 @@ const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags)
if (imult % odiv == 0) { imult /= odiv; odiv = 1; }
if (odiv % imult == 0) { odiv /= imult; imult = 1; }
value = (value * (imult * omult) + (idiv * odiv - 1)) / (idiv * odiv);
*ret = value;
result = (value * (imult * omult) + (idiv * odiv - 1)) / (idiv * odiv);
if (result >= 0x80000000)
return PARSE_TIME_OVER;
if (!result && value)
return PARSE_TIME_UNDER;
*ret = result;
return NULL;
}

View File

@ -769,15 +769,21 @@ int parse_stick_table(const char *file, int linenum, char **args,
goto out;
}
err = parse_time_err(args[idx], &val, TIME_UNIT_MS);
if (err) {
ha_alert("parsing [%s:%d] : %s: unexpected character '%c' in argument of '%s'.\n",
file, linenum, args[0], *err, args[idx-1]);
if (err == PARSE_TIME_OVER) {
ha_alert("parsing [%s:%d]: %s: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 ms (~24.8 days).\n",
file, linenum, args[0], args[idx], args[idx-1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (val > INT_MAX) {
ha_alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
file, linenum, val);
else if (err == PARSE_TIME_UNDER) {
ha_alert("parsing [%s:%d]: %s: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
file, linenum, args[0], args[idx], args[idx-1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (err) {
ha_alert("parsing [%s:%d] : %s: unexpected character '%c' in argument of '%s'.\n",
file, linenum, args[0], *err, args[idx-1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}

View File

@ -922,7 +922,12 @@ static int tcp_parse_tcp_rep(char **args, int section_type, struct proxy *curpx,
memprintf(err,
"'%s %s' expects a positive delay in milliseconds, in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
if (ptr)
if (ptr == PARSE_TIME_OVER)
memprintf(err, "%s (timer overflow in '%s', maximum value is 2147483647 ms or ~24.8 days)", *err, args[2]);
else if (ptr == PARSE_TIME_UNDER)
memprintf(err, "%s (timer underflow in '%s', minimum non-null value is 1 ms)", *err, args[2]);
else if (ptr)
memprintf(err, "%s (unexpected character '%c')", *err, *ptr);
return -1;
}
@ -1031,7 +1036,12 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
memprintf(err,
"'%s %s' expects a positive delay in milliseconds, in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
if (ptr)
if (ptr == PARSE_TIME_OVER)
memprintf(err, "%s (timer overflow in '%s', maximum value is 2147483647 ms or ~24.8 days)", *err, args[2]);
else if (ptr == PARSE_TIME_UNDER)
memprintf(err, "%s (timer underflow in '%s', minimum non-null value is 1 ms)", *err, args[2]);
else if (ptr)
memprintf(err, "%s (unexpected character '%c')", *err, *ptr);
return -1;
}