diff options
| author | Paul Eggert | 2019-01-01 11:33:10 -0800 |
|---|---|---|
| committer | Paul Eggert | 2019-01-01 11:33:37 -0800 |
| commit | 227343947f083e1094ebd3770f774b480beb2590 (patch) | |
| tree | 54c05f6690abbe94c80426c36ebe64231b275da7 /src | |
| parent | 355b1c3cb91a226d1f58098944542142eddccb60 (diff) | |
| download | emacs-227343947f083e1094ebd3770f774b480beb2590.tar.gz emacs-227343947f083e1094ebd3770f774b480beb2590.zip | |
decode-time: allow bignum years
* src/timefns.c (TM_YEAR_BASE):
Now a constant as it need not be a macro.
(Fdecode_time): Do not signal an overflow merely because the
Gregorian year number does not fix in a fixnum (which can
happen on hosts with 64-bit time_t and with 32-bit int and
EMACS_INT).
Diffstat (limited to 'src')
| -rw-r--r-- | src/timefns.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/src/timefns.c b/src/timefns.c index 437b5b22131..4c99fe58061 100644 --- a/src/timefns.c +++ b/src/timefns.c | |||
| @@ -44,7 +44,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 44 | # define HAVE_TZALLOC_BUG false | 44 | # define HAVE_TZALLOC_BUG false |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | #define TM_YEAR_BASE 1900 | 47 | enum { TM_YEAR_BASE = 1900 }; |
| 48 | 48 | ||
| 49 | #ifndef HAVE_TM_GMTOFF | 49 | #ifndef HAVE_TM_GMTOFF |
| 50 | # define HAVE_TM_GMTOFF false | 50 | # define HAVE_TM_GMTOFF false |
| @@ -1336,12 +1336,22 @@ usage: (decode-time &optional TIME ZONE) */) | |||
| 1336 | 1336 | ||
| 1337 | if (!tm) | 1337 | if (!tm) |
| 1338 | time_error (localtime_errno); | 1338 | time_error (localtime_errno); |
| 1339 | if (! (MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year | ||
| 1340 | && local_tm.tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)) | ||
| 1341 | time_overflow (); | ||
| 1342 | 1339 | ||
| 1343 | /* Avoid overflow when INT_MAX < EMACS_INT_MAX. */ | 1340 | Lisp_Object year; |
| 1344 | EMACS_INT tm_year_base = TM_YEAR_BASE; | 1341 | if (FASTER_TIMEFNS |
| 1342 | && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year | ||
| 1343 | && local_tm.tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE) | ||
| 1344 | { | ||
| 1345 | /* Avoid overflow when INT_MAX - TM_YEAR_BASE < local_tm.tm_year. */ | ||
| 1346 | EMACS_INT tm_year_base = TM_YEAR_BASE; | ||
| 1347 | year = make_fixnum (local_tm.tm_year + tm_year_base); | ||
| 1348 | } | ||
| 1349 | else | ||
| 1350 | { | ||
| 1351 | mpz_set_si (mpz[0], local_tm.tm_year); | ||
| 1352 | mpz_add_ui (mpz[0], mpz[0], TM_YEAR_BASE); | ||
| 1353 | year = make_integer_mpz (); | ||
| 1354 | } | ||
| 1345 | 1355 | ||
| 1346 | return CALLN (Flist, | 1356 | return CALLN (Flist, |
| 1347 | make_fixnum (local_tm.tm_sec), | 1357 | make_fixnum (local_tm.tm_sec), |
| @@ -1349,7 +1359,7 @@ usage: (decode-time &optional TIME ZONE) */) | |||
| 1349 | make_fixnum (local_tm.tm_hour), | 1359 | make_fixnum (local_tm.tm_hour), |
| 1350 | make_fixnum (local_tm.tm_mday), | 1360 | make_fixnum (local_tm.tm_mday), |
| 1351 | make_fixnum (local_tm.tm_mon + 1), | 1361 | make_fixnum (local_tm.tm_mon + 1), |
| 1352 | make_fixnum (local_tm.tm_year + tm_year_base), | 1362 | year, |
| 1353 | make_fixnum (local_tm.tm_wday), | 1363 | make_fixnum (local_tm.tm_wday), |
| 1354 | (local_tm.tm_isdst < 0 ? make_fixnum (-1) | 1364 | (local_tm.tm_isdst < 0 ? make_fixnum (-1) |
| 1355 | : local_tm.tm_isdst == 0 ? Qnil : Qt), | 1365 | : local_tm.tm_isdst == 0 ? Qnil : Qt), |
| @@ -1360,7 +1370,7 @@ usage: (decode-time &optional TIME ZONE) */) | |||
| 1360 | : Qnil)); | 1370 | : Qnil)); |
| 1361 | } | 1371 | } |
| 1362 | 1372 | ||
| 1363 | /* Return OBJ - OFFSET, checking that OBJ is a valid fixnum and that | 1373 | /* Return OBJ - OFFSET, checking that OBJ is a valid integer and that |
| 1364 | the result is representable as an int. 0 <= OFFSET <= TM_YEAR_BASE. */ | 1374 | the result is representable as an int. 0 <= OFFSET <= TM_YEAR_BASE. */ |
| 1365 | static int | 1375 | static int |
| 1366 | check_tm_member (Lisp_Object obj, int offset) | 1376 | check_tm_member (Lisp_Object obj, int offset) |