]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix format-time-string bignum bug
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 5 Sep 2018 02:14:01 +0000 (19:14 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 5 Sep 2018 02:15:57 +0000 (19:15 -0700)
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.

src/editfns.c
test/src/editfns-tests.el

index 4ea702537937313fdd5e6dd3078854efd3c0a263..191a9ab8f8aaf76b85ddbbd87d992b1736c21e81 100644 (file)
@@ -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;
index 487f3aaa6667737cd213e2e7f82c9a211af6486c..4a840c8d7d1f17410d5f0d748c2d9cd43ce5b9a7 100644 (file)
            (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"))