From aa754e6a9ef5fb65e6a4f582101d7284adc01656 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 28 Jun 2012 08:50:11 -0700 Subject: [PATCH] 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. --- src/ChangeLog | 7 +++++++ src/window.c | 31 ++++++++++++++++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 7bb418fab5a..262ed2ce4d6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2012-06-28 Paul Eggert + + 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 * window.h (struct window): Change type of 'hscroll', diff --git a/src/window.c b/src/window.c index 4f3d40c51e3..9d78a3efa60 100644 --- a/src/window.c +++ b/src/window.c @@ -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; } +/* 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)) -- 2.39.2