]> code.delx.au - gnu-emacs/commitdiff
Avoid signed integer overflow when converting Time to ptrdiff_t.
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 24 Sep 2014 20:30:28 +0000 (13:30 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 24 Sep 2014 20:30:28 +0000 (13:30 -0700)
* 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.

src/ChangeLog
src/keyboard.c
src/systime.h
src/termhooks.h

index 9ee4a3de1d0367cf3cfae1b1135f45993062679b..5f95c1594ef72b4aae3dd6f6bd7120833f6c1edb 100644 (file)
@@ -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.
index 718614f080acb6a108270d22012432bb5d5bb91b..704109e167110c20457c64c7f722b33fc22ae731 100644 (file)
@@ -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);
index 30a13d0ebcf2b897b24348d9777ce9f1da0e0911..a834bce76dca240bfc13a2d552d3c719e666511b 100644 (file)
@@ -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
 
index 6412f0da6ca5cde8a4f892126e52394fa56d2299..8d85fba8af86cb2a3b8671aff57de129ca123b74 100644 (file)
@@ -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.