diff options
author | Emanuele Torre <torreemanuele6@gmail.com> | 2024-03-18 17:22:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-18 17:22:59 +0100 |
commit | d777b6570c5225cdd946894fb99b6746df6dfa85 (patch) | |
tree | 22e40a0e3e2be9e9e84ba15df74b68c8f90f56ec /src | |
parent | 1411ce63d5314ad8771d2bae01d0a4144b30049c (diff) |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/util.c | 55 |
1 files changed, 31 insertions, 24 deletions
@@ -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. */ |