]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid integer overflow on scroll-left and scroll-right.
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 28 Jun 2012 15:50:11 +0000 (08:50 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 28 Jun 2012 15:50:11 +0000 (08:50 -0700)
* window.c (HSCROLL_MAX): New macro.
(Fscroll_left, Fscroll_right): Avoid undefined behavior on integer
overflow when requested scroll falls outside ptrdiff_t range.

src/ChangeLog
src/window.c

index 7bb418fab5a759fd573cb5868fcf7bea523c52c0..262ed2ce4d67ea2f715dc8ceb4a29046d48b0018 100644 (file)
@@ -1,3 +1,10 @@
+2012-06-28  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Avoid integer overflow on scroll-left and scroll-right.
+       * window.c (HSCROLL_MAX): New macro.
+       (Fscroll_left, Fscroll_right): Avoid undefined behavior on integer
+       overflow when requested scroll falls outside ptrdiff_t range.
+
 2012-06-28  Dmitry Antipov  <dmantipov@yandex.ru>
 
        * window.h (struct window): Change type of 'hscroll',
index 4f3d40c51e3acc34065fa46881bc51cfaf744721..9d78a3efa607bcd0d6295a022db45e43a7e6b634 100644 (file)
@@ -3244,7 +3244,7 @@ make_parent_window (Lisp_Object window, int horflag)
 
   o = XWINDOW (window);
   p = allocate_window ();
-  memcpy ((char *) p + sizeof (struct vectorlike_header), 
+  memcpy ((char *) p + sizeof (struct vectorlike_header),
          (char *) o + sizeof (struct vectorlike_header),
          sizeof (Lisp_Object) * VECSIZE (struct window));
   XSETWINDOW (parent, p);
@@ -4857,6 +4857,9 @@ specifies the window to scroll.  This takes precedence over
   return Qnil;
 }
 \f
+/* Scrolling amount must fit in both ptrdiff_t and Emacs fixnum.  */
+#define HSCROLL_MAX min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM)
+
 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
        doc: /* Scroll selected window display ARG columns left.
 Default for ARG is window width minus 2.
@@ -4871,13 +4874,12 @@ by this function.  This happens in an interactive call.  */)
   Lisp_Object result;
   ptrdiff_t hscroll;
   struct window *w = XWINDOW (selected_window);
-
-  if (NILP (arg))
-    XSETFASTINT (arg, window_body_cols (w) - 2);
-  else
-    arg = Fprefix_numeric_value (arg);
-
-  hscroll = w->hscroll + XINT (arg);
+  EMACS_INT requested_arg = (NILP (arg)
+                            ? window_body_cols (w) - 2
+                            : XINT (Fprefix_numeric_value (arg)));
+  ptrdiff_t clipped_arg =
+    clip_to_bounds (- w->hscroll, requested_arg, HSCROLL_MAX - w->hscroll);
+  hscroll = w->hscroll + clipped_arg;
   result = Fset_window_hscroll (selected_window, make_number (hscroll));
 
   if (!NILP (set_minimum))
@@ -4900,13 +4902,12 @@ by this function.  This happens in an interactive call.  */)
   Lisp_Object result;
   ptrdiff_t hscroll;
   struct window *w = XWINDOW (selected_window);
-
-  if (NILP (arg))
-    XSETFASTINT (arg, window_body_cols (w) - 2);
-  else
-    arg = Fprefix_numeric_value (arg);
-
-  hscroll = w->hscroll - XINT (arg);
+  EMACS_INT requested_arg = (NILP (arg)
+                            ? window_body_cols (w) - 2
+                            : XINT (Fprefix_numeric_value (arg)));
+  ptrdiff_t clipped_arg =
+    clip_to_bounds (w->hscroll - HSCROLL_MAX, requested_arg, w->hscroll);
+  hscroll = w->hscroll - clipped_arg;
   result = Fset_window_hscroll (selected_window, make_number (hscroll));
 
   if (!NILP (set_minimum))