diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2014-09-24 13:30:28 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2014-09-24 13:30:28 -0700 |
commit | 203a9eb0ec0e1f28958df5fa1a49c5a7e3f4cae8 (patch) | |
tree | 52781d0a379ff1927d2461265bd0b94f68254454 | |
parent | 0e176389a723f7eec072af62cde12314de7f70e2 (diff) | |
download | emacs-203a9eb0ec0e1f28958df5fa1a49c5a7e3f4cae8.tar.gz emacs-203a9eb0ec0e1f28958df5fa1a49c5a7e3f4cae8.tar.bz2 emacs-203a9eb0ec0e1f28958df5fa1a49c5a7e3f4cae8.zip |
Avoid signed integer overflow when converting Time to ptrdiff_t.
* keyboard.c (INPUT_EVENT_POS_MAX, INPUT_EVENT_POS_MIN):
New macros.
(position_to_Time, Time_to_position): New functions.
(gen_help_event, kbd_buffer_get_event): Use them.
* systime.h (Time) [emacs && !HAVE_X_WINDOWS]:
Go back to plain 'unsigned long', so that 'Time' is the same
for both X and non-X builds; this is less likely to cause surprise.
* termhooks.h: Remove compile-time check that Time and ptrdiff_t
are the same size; this is no longer required.
-rw-r--r-- | src/ChangeLog | 11 | ||||
-rw-r--r-- | src/keyboard.c | 32 | ||||
-rw-r--r-- | src/systime.h | 3 | ||||
-rw-r--r-- | src/termhooks.h | 3 |
4 files changed, 42 insertions, 7 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 9ee4a3de1d0..5f95c1594ef 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,16 @@ 2014-09-24 Paul Eggert <eggert@cs.ucla.edu> + Avoid signed integer overflow when converting Time to ptrdiff_t. + * keyboard.c (INPUT_EVENT_POS_MAX, INPUT_EVENT_POS_MIN): + New macros. + (position_to_Time, Time_to_position): New functions. + (gen_help_event, kbd_buffer_get_event): Use them. + * systime.h (Time) [emacs && !HAVE_X_WINDOWS]: + Go back to plain 'unsigned long', so that 'Time' is the same + for both X and non-X builds; this is less likely to cause surprise. + * termhooks.h: Remove compile-time check that Time and ptrdiff_t + are the same size; this is no longer required. + * keyboard.c (make_lispy_event): Avoid unnecessary tests of bit 28 and of whether an unsigned value is negative. This simplifies the code a bit, and pacifies clang 3.4. diff --git a/src/keyboard.c b/src/keyboard.c index 718614f080a..704109e1671 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -3729,6 +3729,34 @@ kbd_buffer_unget_event (register struct input_event *event) } } +/* Limit help event positions to this range, to avoid overflow problems. */ +#define INPUT_EVENT_POS_MAX \ + ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \ + MOST_POSITIVE_FIXNUM))) +#define INPUT_EVENT_POS_MIN (-1 - INPUT_EVENT_POS_MAX) + +/* Return a Time that encodes position POS. POS must be in range. */ + +static Time +position_to_Time (ptrdiff_t pos) +{ + eassert (INPUT_EVENT_POS_MIN <= pos && pos <= INPUT_EVENT_POS_MAX); + return pos; +} + +/* Return the position that ENCODED_POS encodes. + Avoid signed integer overflow. */ + +static ptrdiff_t +Time_to_position (Time encoded_pos) +{ + if (encoded_pos <= INPUT_EVENT_POS_MAX) + return encoded_pos; + Time encoded_pos_min = INPUT_EVENT_POS_MIN; + eassert (encoded_pos_min <= encoded_pos); + ptrdiff_t notpos = -1 - encoded_pos; + return -1 - notpos; +} /* Generate a HELP_EVENT input_event and store it in the keyboard buffer. @@ -3752,7 +3780,7 @@ gen_help_event (Lisp_Object help, Lisp_Object frame, Lisp_Object window, event.arg = object; event.x = WINDOWP (window) ? window : frame; event.y = help; - event.timestamp = pos; + event.timestamp = position_to_Time (pos); kbd_buffer_store_event (&event); } @@ -4084,7 +4112,7 @@ kbd_buffer_get_event (KBOARD **kbp, frame = event->frame_or_window; object = event->arg; - position = make_number (event->timestamp); + position = make_number (Time_to_position (event->timestamp)); window = event->x; help = event->y; clear_event (event); diff --git a/src/systime.h b/src/systime.h index 30a13d0ebcf..a834bce76dc 100644 --- a/src/systime.h +++ b/src/systime.h @@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #ifndef EMACS_SYSTIME_H #define EMACS_SYSTIME_H -#include <sys/types.h> #include <timespec.h> INLINE_HEADER_BEGIN @@ -28,7 +27,7 @@ INLINE_HEADER_BEGIN # ifdef HAVE_X_WINDOWS # include <X11/X.h> # else -typedef size_t Time; +typedef unsigned long Time; # endif #endif diff --git a/src/termhooks.h b/src/termhooks.h index 6412f0da6ca..8d85fba8af8 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -288,9 +288,6 @@ struct input_event Lisp_Object arg; }; -/* To make sure we don't break HELP_EVENT. */ -verify (sizeof (Time) == sizeof (ptrdiff_t)); - #define EVENT_INIT(event) memset (&(event), 0, sizeof (struct input_event)) /* Bits in the modifiers member of the input_event structure. |