Skip to content

Commit 32a86c8

Browse files
committed
util.c: fix _WIN32 port of strptime
In _WIN32 builds, TIME_MAX needs to be INT32_MAX. Also fix UB overflow, and useless check in NetBSD's strptime: (time_t_value * 10) <= TIME_MAX is always true since time_t is signed, and TIME_MAX is its maximum value. And, if it is not optimised out, it causes a signed integer overflow (undefined in standard C) for inputs that start with a sequence of characters between "922337203685477581" and "999999999999999999" (inclusive, 64-bit time_t). Also, since the check does not do what it is supposed to do, even if we assume that signed integer overflow is defined like for unsigned integers, on builds where time_t is int32_t, and TIME_MAX is INT32_MAX, this will cause strptime("%s") to accept 9999999999 as a valid timestamp, equivalent to 1410065398 (Sat 20 Nov 17:46:39 UTC) instead of rejecting it. This works because floor(log10(UINT32_MAX)) == floor(log10(INT32_MAX)) in 32-bit. Noticed thanks to a compiler warning in the windows build CI.
1 parent 1411ce6 commit 32a86c8

File tree

1 file changed

+11
-4
lines changed

1 file changed

+11
-4
lines changed

src/util.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -819,11 +819,16 @@ again: switch (c = *fmt++) {
819819
continue;
820820

821821
#ifndef TIME_MAX
822+
#ifdef _WIN32
823+
#define TIME_MAX INT32_MAX
824+
#else
822825
#define TIME_MAX INT64_MAX
826+
#endif
823827
#endif
824828
case 's': /* seconds since the epoch */
825829
{
826-
time_t sse = 0;
830+
time_t tsse;
831+
uint64_t sse = 0;
827832
uint64_t rulim = TIME_MAX;
828833

829834
if (*bp < '0' || *bp > '9') {
@@ -838,14 +843,16 @@ again: switch (c = *fmt++) {
838843
} while ((sse * 10 <= TIME_MAX) &&
839844
rulim && *bp >= '0' && *bp <= '9');
840845

841-
if (sse < 0 || (uint64_t)sse > TIME_MAX) {
846+
if (sse > TIME_MAX) {
842847
bp = NULL;
843848
continue;
844849
}
850+
851+
tsse = sse;
845852
#ifdef _WIN32
846-
if (localtime_s(tm, &sse) == 0)
853+
if (localtime_s(tm, &tsse) == 0)
847854
#else
848-
if (localtime_r(&sse, tm))
855+
if (localtime_r(&tsse, tm))
849856
#endif
850857
state |= S_YDAY | S_WDAY | S_MON | S_MDAY | S_YEAR;
851858
else

0 commit comments

Comments
 (0)