From aa0d1e7800903f2d75432d78aa64a0e9770e83f2 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 5 Feb 2022 11:05:44 -0800 Subject: [PATCH] parse-datetime: allow calculations to yield -1 Problem reported by Jeremy Cantrell . * lib/parse-datetime.y (parse_datetime_body): When calling mktime, use an unmodifed and negative tm_wday or tm_yday to detect an error, as a (time_t) -1 return value is valid on most hosts. * tests/test-parse-datetime.c (main): Add a test for the bug. --- ChangeLog | 9 +++++++++ lib/parse-datetime.y | 22 +++++++++++----------- tests/test-parse-datetime.c | 8 ++++++++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5445802ea2..18dcb3fe3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2022-02-05 Paul Eggert + + parse-datetime: allow calculations to yield -1 + Problem reported by Jeremy Cantrell . + * lib/parse-datetime.y (parse_datetime_body): When calling mktime, + use an unmodifed and negative tm_wday or tm_yday to detect an error, + as a (time_t) -1 return value is valid on most hosts. + * tests/test-parse-datetime.c (main): Add a test for the bug. + 2022-02-04 Paul Eggert userspec: help fix GNU ‘id’ incompatibility diff --git a/lib/parse-datetime.y b/lib/parse-datetime.y index c40fdcef7f..9fc14c9d46 100644 --- a/lib/parse-datetime.y +++ b/lib/parse-datetime.y @@ -2076,21 +2076,20 @@ parse_datetime_body (struct timespec *result, char const *p, if (pc.days_seen && ! pc.dates_seen) { intmax_t dayincr; - if (INT_MULTIPLY_WRAPV ((pc.day_ordinal - - (0 < pc.day_ordinal - && tm.tm_wday != pc.day_number)), - 7, &dayincr) - || INT_ADD_WRAPV ((pc.day_number - tm.tm_wday + 7) % 7, - dayincr, &dayincr) - || INT_ADD_WRAPV (dayincr, tm.tm_mday, &tm.tm_mday)) - Start = -1; - else + tm.tm_yday = -1; + if (! (INT_MULTIPLY_WRAPV ((pc.day_ordinal + - (0 < pc.day_ordinal + && tm.tm_wday != pc.day_number)), + 7, &dayincr) + || INT_ADD_WRAPV ((pc.day_number - tm.tm_wday + 7) % 7, + dayincr, &dayincr) + || INT_ADD_WRAPV (dayincr, tm.tm_mday, &tm.tm_mday))) { tm.tm_isdst = -1; Start = mktime_z (tz, &tm); } - if (Start == (time_t) -1) + if (tm.tm_yday < 0) { if (debugging (&pc)) dbg_printf (_("error: day '%s' " @@ -2156,8 +2155,9 @@ parse_datetime_body (struct timespec *result, char const *p, tm.tm_min = tm0.tm_min; tm.tm_sec = tm0.tm_sec; tm.tm_isdst = tm0.tm_isdst; + tm.tm_wday = -1; Start = mktime_z (tz, &tm); - if (Start == (time_t) -1) + if (tm.tm_wday < 0) { if (debugging (&pc)) dbg_printf (_("error: adding relative date resulted " diff --git a/tests/test-parse-datetime.c b/tests/test-parse-datetime.c index 059c810cd1..1e7955bc96 100644 --- a/tests/test-parse-datetime.c +++ b/tests/test-parse-datetime.c @@ -398,6 +398,14 @@ main (_GL_UNUSED int argc, char **argv) ASSERT (result.tv_sec == thur2 + ((i + 3) % 7 - 7) * 24 * 3600); } + p = "1970-12-31T23:59:59+00:00 - 1 year"; /* Bug#50115 */ + now.tv_sec = -1; + now.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, &now)); + LOG (p, now, result); + ASSERT (result.tv_sec == now.tv_sec + && result.tv_nsec == now.tv_nsec); + p = "THURSDAY UTC+00"; /* The epoch was on Thursday. */ now.tv_sec = 0; now.tv_nsec = 0; -- 2.32.0