Unfortunately we cannot use strtonum(3) here since there may be non-digit characters following the number. So, strtoll(3) it is then.
- todd Index: lib/libc/time/strptime.c =================================================================== RCS file: /cvs/src/lib/libc/time/strptime.c,v retrieving revision 1.30 diff -u -p -u -r1.30 strptime.c --- lib/libc/time/strptime.c 12 May 2019 12:49:52 -0000 1.30 +++ lib/libc/time/strptime.c 29 Jan 2023 15:13:53 -0000 @@ -29,8 +29,10 @@ */ #include <ctype.h> +#include <errno.h> +#include <limits.h> #include <locale.h> -#include <stdint.h> +#include <stdlib.h> #include <string.h> #include <time.h> @@ -72,8 +74,8 @@ static const int mon_lengths[2][MONSPERY { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; -static int _conv_num64(const unsigned char **, int64_t *, int64_t, int64_t); static int _conv_num(const unsigned char **, int *, int, int); +static int epoch_to_tm(const unsigned char **, struct tm *); static int leaps_thru_end_of(const int y); static char *_strptime(const char *, const char *, struct tm *, int); static const u_char *_find_string(const u_char *, int *, const char * const *, @@ -338,15 +340,10 @@ literal: if (!(_conv_num(&bp, &tm->tm_sec, 0, 60))) return (NULL); break; - case 's': /* Seconds since epoch */ - { - int64_t i64; - if (!(_conv_num64(&bp, &i64, 0, INT64_MAX))) - return (NULL); - if (!gmtime_r(&i64, tm)) - return (NULL); - fields = 0xffff; /* everything */ - } + case 's': /* Seconds since epoch. */ + if (!(epoch_to_tm(&bp, tm))) + return (NULL); + fields = 0xffff; /* everything */ break; case 'U': /* The week of year, beginning on sunday. */ case 'W': /* The week of year, beginning on monday. */ @@ -610,26 +607,27 @@ _conv_num(const unsigned char **buf, int } static int -_conv_num64(const unsigned char **buf, int64_t *dest, int64_t llim, int64_t ulim) +epoch_to_tm(const unsigned char **buf, struct tm *tm) { - int result = 0; - int64_t rulim = ulim; - - if (**buf < '0' || **buf > '9') - return (0); - - /* we use rulim to break out of the loop when we run out of digits */ - do { - result *= 10; - result += *(*buf)++ - '0'; - rulim /= 10; - } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); - - if (result < llim || result > ulim) - return (0); - - *dest = result; - return (1); + int saved_errno = errno; + int ret = 0; + time_t secs; + char *ep; + + errno = 0; + secs = strtoll(*buf, &ep, 10); + if (*buf == (unsigned char *)ep) + goto done; + if (secs < 0 || + secs == LLONG_MAX && errno == ERANGE) + goto done; + if (localtime_r(&secs, tm) == NULL) + goto done; + ret = 1; +done: + *buf = ep; + errno = saved_errno; + return (ret); } static const u_char *