Skip to content

Commit

Permalink
util.c: fix _WIN32 port of strptime (#3071)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
emanuele6 authored Mar 18, 2024
1 parent 1411ce6 commit d777b65
Showing 1 changed file with 31 additions and 24 deletions.
55 changes: 31 additions & 24 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,40 +818,47 @@ again: switch (c = *fmt++) {
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. */
Expand Down

0 comments on commit d777b65

Please sign in to comment.