From: Yu Watanabe Date: Sat, 8 Jul 2017 19:59:07 +0000 (+0900) Subject: time-util: make parse_timestamp() set 0 if the input is very old date (#6297) X-Git-Tag: v234~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7635ab8e74ea4a94e81143c3077570a986df375c;p=thirdparty%2Fsystemd.git time-util: make parse_timestamp() set 0 if the input is very old date (#6297) If the input is older than "1970-01-01 UTC", then `parse_timestamp()` fails and returns -EINVAL. However, if the input is e.g. `-100years`, then the function succeeds and sets `usec = 0`. This commit makes the function also succeed for old dates and set `usec = 0`. Fixes #6290. --- diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 3b44985c697..151b44a8d9d 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -847,19 +847,23 @@ parse_usec: from_tm: x = mktime_or_timegm(&tm, utc); - if (x < 0) - return -EINVAL; + if (x == (time_t) -1) + return -EOVERFLOW; if (weekday >= 0 && tm.tm_wday != weekday) return -EINVAL; - ret = (usec_t) x * USEC_PER_SEC + x_usec; + if (x < 0) + ret = 0; + else + ret = (usec_t) x * USEC_PER_SEC + x_usec; + if (ret > USEC_TIMESTAMP_FORMATTABLE_MAX) return -EINVAL; finish: if (ret + plus < ret) /* overflow? */ - return -EINVAL; + return -EOVERFLOW; ret += plus; if (ret > USEC_TIMESTAMP_FORMATTABLE_MAX) return -EINVAL; diff --git a/src/test/test-date.c b/src/test/test-date.c index a952f779dc7..4984b023797 100644 --- a/src/test/test-date.c +++ b/src/test/test-date.c @@ -27,6 +27,7 @@ static void test_should_pass(const char *p) { usec_t t, q; char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *sp; + log_info("Test: %s", p); assert_se(parse_timestamp(p, &t) >= 0); format_timestamp_us(buf, sizeof(buf), t); log_info("\"%s\" → \"%s\"", p, buf); @@ -41,25 +42,32 @@ static void test_should_pass(const char *p) { format_timestamp_relative(buf_relative, sizeof(buf_relative), t); log_info("%s", strna(buf_relative)); - assert_se(parse_timestamp(buf, &q) >= 0); } static void test_should_parse(const char *p) { usec_t t; + log_info("Test: %s", p); assert_se(parse_timestamp(p, &t) >= 0); + log_info("\"%s\" → \"@%" PRI_USEC "\"", p, t); } static void test_should_fail(const char *p) { usec_t t; + int r; - assert_se(parse_timestamp(p, &t) < 0); + log_info("Test: %s", p); + r = parse_timestamp(p, &t); + if (r >= 0) + log_info("\"%s\" → \"@%" PRI_USEC "\" (unexpected)", p, t); + else + log_info("parse_timestamp() returns %d (expected)", r); + assert_se(r < 0); } static void test_one(const char *p) { _cleanup_free_ char *with_utc; - log_info("Test: %s", p); with_utc = strjoin(p, " UTC"); test_should_pass(p); test_should_pass(with_utc); @@ -68,7 +76,6 @@ static void test_one(const char *p) { static void test_one_noutc(const char *p) { _cleanup_free_ char *with_utc; - log_info("Test: %s", p); with_utc = strjoin(p, " UTC"); test_should_pass(p); test_should_fail(with_utc); @@ -93,17 +100,17 @@ int main(int argc, char *argv[]) { test_one_noutc("+2y 4d"); test_one_noutc("5months ago"); test_one_noutc("@1395716396"); - test_should_parse("today UTC"); test_should_fail("today UTC UTC"); test_should_parse("1970-1-1 UTC"); - test_should_fail("1969-1-1 UTC"); + test_should_parse("1969-12-31 UTC"); + test_should_parse("-100y"); #if SIZEOF_TIME_T == 8 - test_should_parse("9999-12-30 23:59:59 UTC"); + test_should_pass("9999-12-30 23:59:59 UTC"); test_should_fail("9999-12-31 00:00:00 UTC"); test_should_fail("10000-01-01 00:00:00 UTC"); #elif SIZEOF_TIME_T == 4 - test_should_parse("2038-01-19 03:14:07 UTC"); - test_should_fail( "2038-01-19 03:14:08 UTC"); + test_should_pass("2038-01-19 03:14:07 UTC"); + test_should_fail("2038-01-19 03:14:08 UTC"); #endif return 0;