Skip to content

Commit

Permalink
util.c: fix _WIN32 port of strptime
Browse files Browse the repository at this point in the history
In _WIN32 builds, TIME_MAX needs to be INT32_MAX.

Also fix UB-overflow/useless-check in BSD's strptime:
  (time_t_value * 10) < TIME_MAX  is always true since time_t is signed
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.

Noticed thanks to a compiler warning in the windows build CI.
  • Loading branch information
emanuele6 committed Mar 15, 2024
1 parent 1411ce6 commit 0fbc381
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -819,11 +819,15 @@ again: switch (c = *fmt++) {
continue;

#ifndef TIME_MAX
#ifdef _WIN32
#define TIME_MAX INT32_MAX
#else
#define TIME_MAX INT64_MAX
#endif
#endif
case 's': /* seconds since the epoch */
{
time_t sse = 0;
uint64_t sse = 0;
uint64_t rulim = TIME_MAX;

if (*bp < '0' || *bp > '9') {
Expand All @@ -835,17 +839,18 @@ again: switch (c = *fmt++) {
sse *= 10;
sse += *bp++ - '0';
rulim /= 10;
} while ((sse * 10 <= TIME_MAX) &&
} while (sse * 10 <= TIME_MAX &&
rulim && *bp >= '0' && *bp <= '9');

if (sse < 0 || (uint64_t)sse > TIME_MAX) {
if (sse > TIME_MAX) {
bp = NULL;
continue;
}
time_t tsse = sse;
#ifdef _WIN32
if (localtime_s(tm, &sse) == 0)
if (localtime_s(tm, &tsse) == 0)
#else
if (localtime_r(&sse, tm))
if (localtime_r(&tsse, tm))
#endif
state |= S_YDAY | S_WDAY | S_MON | S_MDAY | S_YEAR;
else
Expand Down

0 comments on commit 0fbc381

Please sign in to comment.