diff --git a/src/basic/time-util.c b/src/basic/time-util.c index fe201c398d..81d3f3f38f 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include #include #include #include @@ -996,10 +997,10 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { } for (;;) { - long long l, z = 0; - char *e; - unsigned n = 0; usec_t multiplier = default_unit, k; + long long l, z = 0; + unsigned n = 0; + char *e; p += strspn(p, WHITESPACE); @@ -1010,6 +1011,9 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { break; } + if (*p == '-') /* Don't allow "-0" */ + return -ERANGE; + errno = 0; l = strtoll(p, &e, 10); if (errno > 0) @@ -1020,14 +1024,16 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { if (*e == '.') { char *b = e + 1; + /* Don't allow "0.-0", "3.+1" or "3. 1" */ + if (*b == '-' || *b == '+' || isspace(*b)) + return -EINVAL; + errno = 0; z = strtoll(b, &e, 10); if (errno > 0) return -errno; - if (z < 0) return -ERANGE; - if (e == b) return -EINVAL; @@ -1144,26 +1150,28 @@ int parse_nsec(const char *t, nsec_t *nsec) { break; } + if (*p == '-') + return -ERANGE; + errno = 0; l = strtoll(p, &e, 10); - if (errno > 0) return -errno; - if (l < 0) return -ERANGE; if (*e == '.') { char *b = e + 1; + if (*b == '-' || *b == '+' || isspace(*b)) + return -EINVAL; + errno = 0; z = strtoll(b, &e, 10); if (errno > 0) return -errno; - if (z < 0) return -ERANGE; - if (e == b) return -EINVAL; diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c index 87de8d172c..58c365df57 100644 --- a/src/test/test-time-util.c +++ b/src/test/test-time-util.c @@ -36,14 +36,25 @@ static void test_parse_sec(void) { assert_se(u == USEC_INFINITY); assert_se(parse_sec(" infinity ", &u) >= 0); assert_se(u == USEC_INFINITY); + assert_se(parse_sec("+3.1s", &u) >= 0); + assert_se(u == 3100 * USEC_PER_MSEC); assert_se(parse_sec(" xyz ", &u) < 0); assert_se(parse_sec("", &u) < 0); assert_se(parse_sec(" . ", &u) < 0); assert_se(parse_sec(" 5. ", &u) < 0); assert_se(parse_sec(".s ", &u) < 0); + assert_se(parse_sec("-5s ", &u) < 0); + assert_se(parse_sec("-0.3s ", &u) < 0); + assert_se(parse_sec("-0.0s ", &u) < 0); + assert_se(parse_sec("-0.-0s ", &u) < 0); + assert_se(parse_sec("0.-0s ", &u) < 0); + assert_se(parse_sec("3.-0s ", &u) < 0); assert_se(parse_sec(" infinity .7", &u) < 0); assert_se(parse_sec(".3 infinity", &u) < 0); + assert_se(parse_sec("3.+1s", &u) < 0); + assert_se(parse_sec("3. 1s", &u) < 0); + assert_se(parse_sec("3.s", &u) < 0); } static void test_parse_sec_fix_0(void) { @@ -112,6 +123,8 @@ static void test_parse_nsec(void) { assert_se(u == NSEC_INFINITY); assert_se(parse_nsec(" infinity ", &u) >= 0); assert_se(u == NSEC_INFINITY); + assert_se(parse_nsec("+3.1s", &u) >= 0); + assert_se(u == 3100 * NSEC_PER_MSEC); assert_se(parse_nsec(" xyz ", &u) < 0); assert_se(parse_nsec("", &u) < 0); @@ -120,6 +133,17 @@ static void test_parse_nsec(void) { assert_se(parse_nsec(".s ", &u) < 0); assert_se(parse_nsec(" infinity .7", &u) < 0); assert_se(parse_nsec(".3 infinity", &u) < 0); + assert_se(parse_nsec("-5s ", &u) < 0); + assert_se(parse_nsec("-0.3s ", &u) < 0); + assert_se(parse_nsec("-0.0s ", &u) < 0); + assert_se(parse_nsec("-0.-0s ", &u) < 0); + assert_se(parse_nsec("0.-0s ", &u) < 0); + assert_se(parse_nsec("3.-0s ", &u) < 0); + assert_se(parse_nsec(" infinity .7", &u) < 0); + assert_se(parse_nsec(".3 infinity", &u) < 0); + assert_se(parse_nsec("3.+1s", &u) < 0); + assert_se(parse_nsec("3. 1s", &u) < 0); + assert_se(parse_nsec("3.s", &u) < 0); } static void test_format_timespan_one(usec_t x, usec_t accuracy) {