]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tools: improve time format error detection
authorWilly Tarreau <w@1wt.eu>
Fri, 7 Jun 2019 17:00:37 +0000 (19:00 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 7 Jun 2019 17:32:02 +0000 (19:32 +0200)
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).

15 files changed:
include/common/standard.h
src/arg.c
src/cfgparse-global.c
src/cfgparse-listen.c
src/cfgparse.c
src/cli.c
src/flt_spoe.c
src/hlua.c
src/proto_tcp.c
src/proxy.c
src/server.c
src/ssl_sock.c
src/standard.c
src/stick_table.c
src/tcp_rules.c

index be85bb5e7af2085c31cd2b7167c12d84376b65ae..0f4b1870e4bc67b07a3f35de6ae1d4a8ca004a5b 100644 (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
index b0fe94544fbbff4410ea1019b1f20e0fe6763b67..2719b53953e04d8ead647e4741290359be67073a 100644 (file)
--- a/src/arg.c
+++ b/src/arg.c
@@ -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;
index 8355a8f1b2ea1431401160a626c1317b67ddf396..4ecaff1ae91419d28d433c39bf3f2a14e5698070 100644 (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) {
-                       ha_alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
+               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;
                }
-               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]);
+               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;
        }
        else if (strcmp(args[0], "cpu-map") == 0) {
                /* map a process list to a CPU set */
index 7ffc0e0947ed15d992833f9f97f1dba0d36ee5f6..d659779a842c5578d18784da0856030edeee5792 100644 (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;
index 98adadffa4f05541110f2c3478000414b715a759..1101470be9b355d91a6d48b4fe522e126644ba19 100644 (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;
+                       }
+                       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;
                        }
-                       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) {
+                               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;
                        }
index 9949a885aeb255ee06935086801f092c5b2b8004..25743d92ccc4a71b3c6be7573b6b19917f859c37 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -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;
                }
index 711ac809eff611cf1f012cd0cba4cd2669cf3fae..f20b2640baf41fdce61734e24f98e5a748c7a721 100644 (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;
index ef796327dc59493d8cd8b7434b9c1b36bbf4a871..28abd0836e630d57796d440483f7c7f288a593ec 100644 (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;
        }
index 51d10a553da234572083568923fd92571b0b8cda..64ffb83c5d29e649802a3740b6dc77d4886d7b56 100644 (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;
        }
index 575a8eff66dd65aa38470ed6cfe116f0312e932d..78babd5bb707a077722fefecdbc099587cbc180f 100644 (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;
        }
index 14e1a938c3c71fe66a02a093cbf6d3878e5958b0..0cbba7866f47d6d8029d5e5110060ea842e66029 100644 (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;
index 5cc005b7c73252f06f08e16145fbb9f74a745198..b6364faa70f9e8df1bd4a15c69602f0211718398 100644 (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;
        }
index a67948ba59c1d280e8ddc0ad7fd60bea75adcd23..3651f5e35ddb3dc0e4b1ff2e92ca7f6ef2334681 100644 (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;
 }
 
index a555e646315728fae40eedf0fd45b3b49537b3a5..4b04f18ccad5977917a784ba487bb4456a0c9ad0 100644 (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;
                        }
index a70c4c076a8417819e09c65aa7ad60000e82003b..72b11ae369559064c76231966b8d19d9dba56937 100644 (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;
                }