From: Paul Eggert Date: Wed, 5 Sep 2018 02:14:01 +0000 (-0700) Subject: Fix format-time-string bignum bug X-Git-Tag: emacs-27.0.90~4461 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=ccb3891ff5446b578b9306aec0fd9c5ec3ed8e98;p=emacs.git Fix format-time-string bignum bug The problem can occur on 32-bit platforms with current timestamps. * src/editfns.c (disassemble_lisp_time, decode_time_components): Support seconds counts that are bignums. * test/src/editfns-tests.el (editfns-tests--have-leap-seconds): New function. (format-time-string-with-bignum-on-32-bit): New test. --- diff --git a/src/editfns.c b/src/editfns.c index 4ea70253793..191a9ab8f8a 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -1743,10 +1743,10 @@ disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh, /* When combining components, require LOW to be an integer, as otherwise it would be a pain to add up times. */ - if (! FIXNUMP (low)) + if (! INTEGERP (low)) return 0; } - else if (FIXNUMP (specified_time)) + else if (INTEGERP (specified_time)) len = 2; *phigh = high; @@ -1807,11 +1807,12 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, Lisp_Object psec, struct lisp_time *result, double *dresult) { - EMACS_INT hi, lo, us, ps; + EMACS_INT hi, us, ps; + intmax_t lo; if (! (FIXNUMP (high) && FIXNUMP (usec) && FIXNUMP (psec))) return 0; - if (! FIXNUMP (low)) + if (! INTEGERP (low)) { if (FLOATP (low)) { @@ -1841,7 +1842,8 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, } hi = XFIXNUM (high); - lo = XFIXNUM (low); + if (! integer_to_intmax (low, &lo)) + return -1; us = XFIXNUM (usec); ps = XFIXNUM (psec); @@ -1849,7 +1851,8 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, each overflow into the next higher-order component. */ us += ps / 1000000 - (ps % 1000000 < 0); lo += us / 1000000 - (us % 1000000 < 0); - hi += lo >> LO_TIME_BITS; + if (INT_ADD_WRAPV (lo >> LO_TIME_BITS, hi, &hi)) + return -1; ps = ps % 1000000 + 1000000 * (ps % 1000000 < 0); us = us % 1000000 + 1000000 * (us % 1000000 < 0); lo &= (1 << LO_TIME_BITS) - 1; diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 487f3aaa666..4a840c8d7d1 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -253,6 +253,16 @@ (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" nil (concat (make-string 2048 ?X) "0"))))) +(defun editfns-tests--have-leap-seconds () + (string-equal (format-time-string "%Y-%m-%d %H:%M:%S" 78796800 t) + "1972-06-30 23:59:60")) + +(ert-deftest format-time-string-with-bignum-on-32-bit () + (should (or (string-equal + (format-time-string "%Y-%m-%d %H:%M:%S" (- (ash 1 31) 3600) t) + "2038-01-19 02:14:08") + (editfns-tests--have-leap-seconds)))) + (ert-deftest format-with-field () (should (equal (format "First argument %2$s, then %3$s, then %1$s" 1 2 3) "First argument 2, then 3, then 1"))