From d777b6570c5225cdd946894fb99b6746df6dfa85 Mon Sep 17 00:00:00 2001 From: Emanuele Torre Date: Mon, 18 Mar 2024 17:22:59 +0100 Subject: util.c: fix _WIN32 port of strptime (#3071) In windows, time_t is a signed 32-bit integer type, so TIME_MAX needs to be declared as INT32_MAX instead of INT64_MAX. Also bump NetBSD's strptime to revision 1.65 from 1.63 to fix undefined behaviour (signed integer overflow) bugs. Related NetBSD problem report: https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58041 Noticed thanks to a compiler warning in the windows build CI. I declared the d variable as time_t instead of as unsigned to ensure that the signedness/size of TIME_MAX-d in the sse > TIME_MAX-d check is always correct, and to prevent -Wsign-compare warnings from triggering in the windows build. --- src/util.c | 55 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/util.c b/src/util.c index 2ce6a73d..1ef134f6 100644 --- a/src/util.c +++ b/src/util.c @@ -818,40 +818,47 @@ recurse: LEGAL_ALT(ALT_O); continue; -#ifndef TIME_MAX -#define TIME_MAX INT64_MAX + case 's': { /* seconds since the epoch */ +#ifdef _WIN32 + const time_t TIME_MAX = INT32_MAX; +#else + const time_t TIME_MAX = INT64_MAX; #endif - case 's': /* seconds since the epoch */ - { - time_t sse = 0; - uint64_t rulim = TIME_MAX; + time_t sse; + time_t d; + + if (*bp < '0' || *bp > '9') { + bp = NULL; + continue; + } - if (*bp < '0' || *bp > '9') { + sse = *bp++ - '0'; + while (*bp >= '0' && *bp <= '9') { + d = *bp++ - '0'; + if (sse > TIME_MAX/10) { bp = NULL; - continue; + break; } - - do { - sse *= 10; - sse += *bp++ - '0'; - rulim /= 10; - } while ((sse * 10 <= TIME_MAX) && - rulim && *bp >= '0' && *bp <= '9'); - - if (sse < 0 || (uint64_t)sse > TIME_MAX) { + sse *= 10; + if (sse > TIME_MAX - d) { bp = NULL; - continue; + break; } + sse += d; + } + if (bp == NULL) + continue; + #ifdef _WIN32 - if (localtime_s(tm, &sse) == 0) + if (localtime_s(tm, &sse)) #else - if (localtime_r(&sse, tm)) + if (localtime_r(&sse, tm) == NULL) #endif - state |= S_YDAY | S_WDAY | S_MON | S_MDAY | S_YEAR; - else - bp = NULL; - } + bp = NULL; + else + state |= S_YDAY | S_WDAY | S_MON | S_MDAY | S_YEAR; continue; + } case 'U': /* The week of year, beginning on sunday. */ case 'W': /* The week of year, beginning on monday. */ -- cgit v1.2.3