summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmanuele Torre <torreemanuele6@gmail.com>2024-03-18 17:22:59 +0100
committerGitHub <noreply@github.com>2024-03-18 17:22:59 +0100
commitd777b6570c5225cdd946894fb99b6746df6dfa85 (patch)
tree22e40a0e3e2be9e9e84ba15df74b68c8f90f56ec
parent1411ce63d5314ad8771d2bae01d0a4144b30049c (diff)
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.
-rw-r--r--src/util.c55
1 files changed, 31 insertions, 24 deletions
diff --git a/src/util.c b/src/util.c
index 2ce6a73d..1ef134f6 100644
--- a/src/util.c
+++ b/src/util.c
@@ -818,40 +818,47 @@ recurse:
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. */