From fd6f7d1449c8496ab5c019d2aad7ca5e2980713a Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 8 Feb 2015 16:21:11 -0800 Subject: [PATCH] Better distinguish infinite from invalid times * editfns.c (check_time_validity): New function. (decode_time_components): Return int, not bool. Return -1 (not 0) if the time is out of range. All callers changed. (lisp_time_struct, lisp_seconds_argument): Distinguish better between time overflow and invalid time values. --- src/ChangeLog | 10 ++++++++++ src/editfns.c | 58 +++++++++++++++++++++++++++++++++++++++------------------- src/keyboard.c | 11 +++++------ src/systime.h | 4 ++-- 4 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 56f88f5bec4..017b8f15e3b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2015-02-09 Paul Eggert + + Better distinguish infinite from invalid times + * editfns.c (check_time_validity): New function. + (decode_time_components): Return int, not bool. + Return -1 (not 0) if the time is out of range. + All callers changed. + (lisp_time_struct, lisp_seconds_argument): Distinguish better + between time overflow and invalid time values. + 2015-02-08 Paul Eggert Minor tweaks to frame_size_history_add diff --git a/src/editfns.c b/src/editfns.c index 7026ccc084e..c205ca3688f 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -1395,6 +1395,19 @@ invalid_time (void) error ("Invalid time specification"); } +/* Check a return value compatible with that of decode_time_components. */ +static void +check_time_validity (int validity) +{ + if (validity <= 0) + { + if (validity < 0) + time_overflow (); + else + invalid_time (); + } +} + /* A substitute for mktime_z on platforms that lack it. It's not thread-safe, but should be good enough for Emacs in typical use. */ #ifndef HAVE_TZALLOC @@ -1698,9 +1711,9 @@ decode_float_time (double t, struct lisp_time *result) If *DRESULT is not null, store into *DRESULT the number of seconds since the start of the POSIX Epoch. - Return true if successful, false if the components are of the - wrong type or represent a time out of range. */ -bool + Return 1 if successful, 0 if the components are of the + wrong type, and -1 if the time is out of range. */ +int decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, Lisp_Object psec, struct lisp_time *result, double *dresult) @@ -1708,17 +1721,17 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, EMACS_INT hi, lo, us, ps; if (! (INTEGERP (high) && INTEGERP (usec) && INTEGERP (psec))) - return false; + return 0; if (! INTEGERP (low)) { if (FLOATP (low)) { double t = XFLOAT_DATA (low); if (result && ! decode_float_time (t, result)) - return false; + return -1; if (dresult) *dresult = t; - return true; + return 1; } else if (NILP (low)) { @@ -1732,10 +1745,10 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, } if (dresult) *dresult = now.tv_sec + now.tv_nsec / 1e9; - return true; + return 1; } else - return false; + return 0; } hi = XINT (high); @@ -1755,7 +1768,7 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, if (result) { if (! (MOST_NEGATIVE_FIXNUM <= hi && hi <= MOST_POSITIVE_FIXNUM)) - return false; + return -1; result->hi = hi; result->lo = lo; result->us = us; @@ -1768,7 +1781,7 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, *dresult = (us * 1e6 + ps) / 1e12 + lo + dhi * (1 << LO_TIME_BITS); } - return true; + return 1; } struct timespec @@ -1792,8 +1805,8 @@ lisp_time_struct (Lisp_Object specified_time, int *plen) Lisp_Object high, low, usec, psec; struct lisp_time t; int len = disassemble_lisp_time (specified_time, &high, &low, &usec, &psec); - if (! (len && decode_time_components (high, low, usec, psec, &t, 0))) - invalid_time (); + int val = len ? decode_time_components (high, low, usec, psec, &t, 0) : 0; + check_time_validity (val); *plen = len; return t; } @@ -1818,13 +1831,20 @@ lisp_seconds_argument (Lisp_Object specified_time) { Lisp_Object high, low, usec, psec; struct lisp_time t; - if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec) - && decode_time_components (high, low, make_number (0), - make_number (0), &t, 0))) - invalid_time (); - if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> LO_TIME_BITS <= t.hi : 0 <= t.hi) - && t.hi <= TIME_T_MAX >> LO_TIME_BITS)) - time_overflow (); + + int val = disassemble_lisp_time (specified_time, &high, &low, &usec, &psec); + if (val != 0) + { + val = decode_time_components (high, low, make_number (0), + make_number (0), &t, 0); + if (0 < val + && ! ((TYPE_SIGNED (time_t) + ? TIME_T_MIN >> LO_TIME_BITS <= t.hi + : 0 <= t.hi) + && t.hi <= TIME_T_MAX >> LO_TIME_BITS)) + val = -1; + } + check_time_validity (val); return (t.hi << LO_TIME_BITS) + t.lo; } diff --git a/src/keyboard.c b/src/keyboard.c index 1176d701f2a..ee621923c67 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4369,19 +4369,18 @@ Lisp_Object pending_funcalls; static bool decode_timer (Lisp_Object timer, struct timespec *result) { - Lisp_Object *vector; + Lisp_Object *vec; if (! (VECTORP (timer) && ASIZE (timer) == 9)) return 0; - vector = XVECTOR (timer)->contents; - if (! NILP (vector[0])) + vec = XVECTOR (timer)->contents; + if (! NILP (vec[0])) return 0; - if (! INTEGERP (vector[2])) + if (! INTEGERP (vec[2])) return false; struct lisp_time t; - if (! decode_time_components (vector[1], vector[2], vector[3], vector[8], - &t, 0)) + if (decode_time_components (vec[1], vec[2], vec[3], vec[8], &t, 0) <= 0) return false; *result = lisp_to_timespec (t); return timespec_valid_p (*result); diff --git a/src/systime.h b/src/systime.h index 1d3a4ba2914..4787c512aaa 100644 --- a/src/systime.h +++ b/src/systime.h @@ -100,8 +100,8 @@ struct lisp_time /* defined in editfns.c */ extern Lisp_Object make_lisp_time (struct timespec); -extern bool decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object, - Lisp_Object, struct lisp_time *, double *); +extern int decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object, + Lisp_Object, struct lisp_time *, double *); extern struct timespec lisp_to_timespec (struct lisp_time); extern struct timespec lisp_time_argument (Lisp_Object); #endif -- 2.11.4.GIT