+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',
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);
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.
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))
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))