[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"))