From 313c1e544ab88d0ca95015b30e23dfbabe36a2ac Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 12 Mar 2011 22:27:18 -0800 Subject: [PATCH] * editfns.c (lisp_time_argument): Check for time stamp overflow. --- src/ChangeLog | 4 ++++ src/editfns.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index b3362b9fbca..546b02d2a96 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2011-03-13 Paul Eggert + + * editfns.c (lisp_time_argument): Check for time stamp overflow. + 2011-03-12 Paul Eggert Improve quality of tests for time stamp overflow. For example, diff --git a/src/editfns.c b/src/editfns.c index e55502bdb89..d92d3482d09 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -1439,12 +1439,17 @@ static EMACS_INT hi_time (time_t t) { time_t hi = t >> 16; - if ((TYPE_SIGNED (time_t) - && TIME_T_MIN >> 16 < MOST_NEGATIVE_FIXNUM - && hi < MOST_NEGATIVE_FIXNUM) - || (MOST_POSITIVE_FIXNUM < TIME_T_MAX >> 16 - && MOST_POSITIVE_FIXNUM < hi)) + + /* Check for overflow, helping the compiler for common cases where + no runtime check is needed, and taking care not to convert + negative numbers to unsigned before comparing them. */ + if (! ((! TYPE_SIGNED (time_t) + || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> 16 + || MOST_NEGATIVE_FIXNUM <= hi) + && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM + || hi <= MOST_POSITIVE_FIXNUM))) time_overflow (); + return hi; } @@ -1551,6 +1556,7 @@ lisp_time_argument (Lisp_Object specified_time, time_t *result, int *usec) else { Lisp_Object high, low; + EMACS_INT hi; high = Fcar (specified_time); CHECK_NUMBER (high); low = Fcdr (specified_time); @@ -1574,8 +1580,21 @@ lisp_time_argument (Lisp_Object specified_time, time_t *result, int *usec) else if (usec) *usec = 0; CHECK_NUMBER (low); - *result = (XINT (high) << 16) + (XINT (low) & 0xffff); - return *result >> 16 == XINT (high); + hi = XINT (high); + + /* Check for overflow, helping the compiler for common cases + where no runtime check is needed, and taking care not to + convert negative numbers to unsigned before comparing them. */ + if (! ((TYPE_SIGNED (time_t) + ? (TIME_T_MIN >> 16 <= MOST_NEGATIVE_FIXNUM + || TIME_T_MIN >> 16 <= hi) + : 0 <= hi) + && (MOST_POSITIVE_FIXNUM <= TIME_T_MAX >> 16 + || hi <= TIME_T_MAX >> 16))) + return 0; + + *result = (hi << 16) + (XINT (low) & 0xffff); + return 1; } } -- 2.39.5