diff options
| author | Paul Eggert | 2014-09-24 13:30:28 -0700 |
|---|---|---|
| committer | Paul Eggert | 2014-09-24 13:30:28 -0700 |
| commit | 203a9eb0ec0e1f28958df5fa1a49c5a7e3f4cae8 (patch) | |
| tree | 52781d0a379ff1927d2461265bd0b94f68254454 /src/keyboard.c | |
| parent | 0e176389a723f7eec072af62cde12314de7f70e2 (diff) | |
| download | emacs-203a9eb0ec0e1f28958df5fa1a49c5a7e3f4cae8.tar.gz 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.
Diffstat (limited to 'src/keyboard.c')
| -rw-r--r-- | src/keyboard.c | 32 |
1 files changed, 30 insertions, 2 deletions
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) | |||
| 3729 | } | 3729 | } |
| 3730 | } | 3730 | } |
| 3731 | 3731 | ||
| 3732 | /* Limit help event positions to this range, to avoid overflow problems. */ | ||
| 3733 | #define INPUT_EVENT_POS_MAX \ | ||
| 3734 | ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \ | ||
| 3735 | MOST_POSITIVE_FIXNUM))) | ||
| 3736 | #define INPUT_EVENT_POS_MIN (-1 - INPUT_EVENT_POS_MAX) | ||
| 3737 | |||
| 3738 | /* Return a Time that encodes position POS. POS must be in range. */ | ||
| 3739 | |||
| 3740 | static Time | ||
| 3741 | position_to_Time (ptrdiff_t pos) | ||
| 3742 | { | ||
| 3743 | eassert (INPUT_EVENT_POS_MIN <= pos && pos <= INPUT_EVENT_POS_MAX); | ||
| 3744 | return pos; | ||
| 3745 | } | ||
| 3746 | |||
| 3747 | /* Return the position that ENCODED_POS encodes. | ||
| 3748 | Avoid signed integer overflow. */ | ||
| 3749 | |||
| 3750 | static ptrdiff_t | ||
| 3751 | Time_to_position (Time encoded_pos) | ||
| 3752 | { | ||
| 3753 | if (encoded_pos <= INPUT_EVENT_POS_MAX) | ||
| 3754 | return encoded_pos; | ||
| 3755 | Time encoded_pos_min = INPUT_EVENT_POS_MIN; | ||
| 3756 | eassert (encoded_pos_min <= encoded_pos); | ||
| 3757 | ptrdiff_t notpos = -1 - encoded_pos; | ||
| 3758 | return -1 - notpos; | ||
| 3759 | } | ||
| 3732 | 3760 | ||
| 3733 | /* Generate a HELP_EVENT input_event and store it in the keyboard | 3761 | /* Generate a HELP_EVENT input_event and store it in the keyboard |
| 3734 | buffer. | 3762 | buffer. |
| @@ -3752,7 +3780,7 @@ gen_help_event (Lisp_Object help, Lisp_Object frame, Lisp_Object window, | |||
| 3752 | event.arg = object; | 3780 | event.arg = object; |
| 3753 | event.x = WINDOWP (window) ? window : frame; | 3781 | event.x = WINDOWP (window) ? window : frame; |
| 3754 | event.y = help; | 3782 | event.y = help; |
| 3755 | event.timestamp = pos; | 3783 | event.timestamp = position_to_Time (pos); |
| 3756 | kbd_buffer_store_event (&event); | 3784 | kbd_buffer_store_event (&event); |
| 3757 | } | 3785 | } |
| 3758 | 3786 | ||
| @@ -4084,7 +4112,7 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 4084 | 4112 | ||
| 4085 | frame = event->frame_or_window; | 4113 | frame = event->frame_or_window; |
| 4086 | object = event->arg; | 4114 | object = event->arg; |
| 4087 | position = make_number (event->timestamp); | 4115 | position = make_number (Time_to_position (event->timestamp)); |
| 4088 | window = event->x; | 4116 | window = event->x; |
| 4089 | help = event->y; | 4117 | help = event->y; |
| 4090 | clear_event (event); | 4118 | clear_event (event); |