Skip to content

Commit 83ba247

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 BSD'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 for input that start with a sequence of characters between "922337203685477581" and "999999999999999999" (inclusive, 64-bit time_t) that is unspecified in standard C. 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 99999999999 as a valid timestamp, equivalent to 1215752191 (Fri 11 Jul 04:56:31 UTC 2008) 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 83ba247

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)