emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master ccb3891 2/2: Fix format-time-string bignum bug


From: Paul Eggert
Subject: [Emacs-diffs] master ccb3891 2/2: Fix format-time-string bignum bug
Date: Tue, 4 Sep 2018 22:16:04 -0400 (EDT)

branch: master
commit ccb3891ff5446b578b9306aec0fd9c5ec3ed8e98
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    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.
---
 src/editfns.c             | 15 +++++++++------
 test/src/editfns-tests.el | 10 ++++++++++
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/editfns.c b/src/editfns.c
index 4ea7025..191a9ab 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 487f3aa..4a840c8 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"))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]