Skip to content

Commit d777b65

Browse files
authored
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.
1 parent 1411ce6 commit d777b65

File tree

1 file changed

+31
-24
lines changed

1 file changed

+31
-24
lines changed

src/util.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -818,40 +818,47 @@ again: switch (c = *fmt++) {
818818
LEGAL_ALT(ALT_O);
819819
continue;
820820

821-
#ifndef TIME_MAX
822-
#define TIME_MAX INT64_MAX
821+
case 's': { /* seconds since the epoch */
822+
#ifdef _WIN32
823+
const time_t TIME_MAX = INT32_MAX;
824+
#else
825+
const time_t TIME_MAX = INT64_MAX;
823826
#endif
824-
case 's': /* seconds since the epoch */
825-
{
826-
time_t sse = 0;
827-
uint64_t rulim = TIME_MAX;
827+
time_t sse;
828+
time_t d;
829+
830+
if (*bp < '0' || *bp > '9') {
831+
bp = NULL;
832+
continue;
833+
}
828834

829-
if (*bp < '0' || *bp > '9') {
835+
sse = *bp++ - '0';
836+
while (*bp >= '0' && *bp <= '9') {
837+
d = *bp++ - '0';
838+
if (sse > TIME_MAX/10) {
830839
bp = NULL;
831-
continue;
840+
break;
832841
}
833-
834-
do {
835-
sse *= 10;
836-
sse += *bp++ - '0';
837-
rulim /= 10;
838-
} while ((sse * 10 <= TIME_MAX) &&
839-
rulim && *bp >= '0' && *bp <= '9');
840-
841-
if (sse < 0 || (uint64_t)sse > TIME_MAX) {
842+
sse *= 10;
843+
if (sse > TIME_MAX - d) {
842844
bp = NULL;
843-
continue;
845+
break;
844846
}
847+
sse += d;
848+
}
849+
if (bp == NULL)
850+
continue;
851+
845852
#ifdef _WIN32
846-
if (localtime_s(tm, &sse) == 0)
853+
if (localtime_s(tm, &sse))
847854
#else
848-
if (localtime_r(&sse, tm))
855+
if (localtime_r(&sse, tm) == NULL)
849856
#endif
850-
state |= S_YDAY | S_WDAY | S_MON | S_MDAY | S_YEAR;
851-
else
852-
bp = NULL;
853-
}
857+
bp = NULL;
858+
else
859+
state |= S_YDAY | S_WDAY | S_MON | S_MDAY | S_YEAR;
854860
continue;
861+
}
855862

856863
case 'U': /* The week of year, beginning on sunday. */
857864
case 'W': /* The week of year, beginning on monday. */

0 commit comments

Comments
 (0)