diff options
| author | Paul Eggert | 2015-04-13 23:26:13 -0700 |
|---|---|---|
| committer | Paul Eggert | 2015-04-13 23:26:59 -0700 |
| commit | b80c5ebc4f6afd54597012583c6a1390db0ade9c (patch) | |
| tree | 96d02d47732d4dd9fd3c16f66db9fd929b4efd41 /src | |
| parent | e84d1ca3c6a643370c4273ad569b618d8cd72b53 (diff) | |
| download | emacs-b80c5ebc4f6afd54597012583c6a1390db0ade9c.tar.gz emacs-b80c5ebc4f6afd54597012583c6a1390db0ade9c.zip | |
Avoid some int overflows in window.c
* src/print.c (print_object):
* src/window.c (sequence_number):
* src/window.h (struct window.sequence_number):
Don't assume window sequence number fits in int.
* src/window.c (window_select_count):
* src/window.h (struct window.use_time, window_select_count):
Don't assume window use time fits in int.
* src/window.c (Fsplit_window_internal):
Don't assume user-supplied integer, or sum, fits in int.
(Fset_window_configuration, count_windows, get_leaf_windows)
(save_window_save, Fcurrent_window_configuration):
Use ptrdiff_t for object counts.
(Fset_window_configuration): Omit unused local 'n'.
(count_windows): Simplify by writing in terms of get_leaf_windows.
(get_leaf_windows): Don't store through FLAT if it's null.
(extract_dimension): New static function.
(set_window_margins, set_window_fringes, set_window_scroll_bars):
Use it to avoid undefined behavior when converting user-supplied
integer to 'int'.
Diffstat (limited to 'src')
| -rw-r--r-- | src/print.c | 5 | ||||
| -rw-r--r-- | src/window.c | 109 | ||||
| -rw-r--r-- | src/window.h | 6 |
3 files changed, 56 insertions, 64 deletions
diff --git a/src/print.c b/src/print.c index 838d03666d4..58b9c706bae 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -1774,9 +1774,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1774 | } | 1774 | } |
| 1775 | else if (WINDOWP (obj)) | 1775 | else if (WINDOWP (obj)) |
| 1776 | { | 1776 | { |
| 1777 | int len; | 1777 | int len = sprintf (buf, "#<window %"pI"d", |
| 1778 | strout ("#<window ", -1, -1, printcharfun); | 1778 | XWINDOW (obj)->sequence_number); |
| 1779 | len = sprintf (buf, "%d", XWINDOW (obj)->sequence_number); | ||
| 1780 | strout (buf, len, len, printcharfun); | 1779 | strout (buf, len, len, printcharfun); |
| 1781 | if (BUFFERP (XWINDOW (obj)->contents)) | 1780 | if (BUFFERP (XWINDOW (obj)->contents)) |
| 1782 | { | 1781 | { |
diff --git a/src/window.c b/src/window.c index eb68672e2e0..461bb627df7 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -45,8 +45,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 45 | #include "msdos.h" | 45 | #include "msdos.h" |
| 46 | #endif | 46 | #endif |
| 47 | 47 | ||
| 48 | static int count_windows (struct window *); | 48 | static ptrdiff_t count_windows (struct window *); |
| 49 | static int get_leaf_windows (struct window *, struct window **, int); | 49 | static ptrdiff_t get_leaf_windows (struct window *, struct window **, |
| 50 | ptrdiff_t); | ||
| 50 | static void window_scroll_pixel_based (Lisp_Object, int, bool, bool); | 51 | static void window_scroll_pixel_based (Lisp_Object, int, bool, bool); |
| 51 | static void window_scroll_line_based (Lisp_Object, int, bool, bool); | 52 | static void window_scroll_line_based (Lisp_Object, int, bool, bool); |
| 52 | static void foreach_window (struct frame *, | 53 | static void foreach_window (struct frame *, |
| @@ -93,7 +94,7 @@ Lisp_Object minibuf_window; | |||
| 93 | Lisp_Object minibuf_selected_window; | 94 | Lisp_Object minibuf_selected_window; |
| 94 | 95 | ||
| 95 | /* Incremented for each window created. */ | 96 | /* Incremented for each window created. */ |
| 96 | static int sequence_number; | 97 | static EMACS_INT sequence_number; |
| 97 | 98 | ||
| 98 | /* Used by the function window_scroll_pixel_based. */ | 99 | /* Used by the function window_scroll_pixel_based. */ |
| 99 | static int window_scroll_pixel_based_preserve_x; | 100 | static int window_scroll_pixel_based_preserve_x; |
| @@ -451,7 +452,7 @@ selected windows appears and to which many commands apply. */) | |||
| 451 | return selected_window; | 452 | return selected_window; |
| 452 | } | 453 | } |
| 453 | 454 | ||
| 454 | int window_select_count; | 455 | EMACS_INT window_select_count; |
| 455 | 456 | ||
| 456 | /* If select_window is called with inhibit_point_swap true it will | 457 | /* If select_window is called with inhibit_point_swap true it will |
| 457 | not store point of the old selected window's buffer back into that | 458 | not store point of the old selected window's buffer back into that |
| @@ -4275,7 +4276,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) | |||
| 4275 | DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0, | 4276 | DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0, |
| 4276 | doc: /* Split window OLD. | 4277 | doc: /* Split window OLD. |
| 4277 | Second argument PIXEL-SIZE specifies the number of pixels of the | 4278 | Second argument PIXEL-SIZE specifies the number of pixels of the |
| 4278 | new window. In any case TOTAL-SIZE must be a positive integer. | 4279 | new window. It must be a positive integer. |
| 4279 | 4280 | ||
| 4280 | Third argument SIDE nil (or `below') specifies that the new window shall | 4281 | Third argument SIDE nil (or `below') specifies that the new window shall |
| 4281 | be located below WINDOW. SIDE `above' means the new window shall be | 4282 | be located below WINDOW. SIDE `above' means the new window shall be |
| @@ -4315,7 +4316,7 @@ set correctly. See the code of `split-window' for how this is done. */) | |||
| 4315 | f = XFRAME (frame); | 4316 | f = XFRAME (frame); |
| 4316 | 4317 | ||
| 4317 | CHECK_NUMBER (pixel_size); | 4318 | CHECK_NUMBER (pixel_size); |
| 4318 | int total_size | 4319 | EMACS_INT total_size |
| 4319 | = XINT (pixel_size) / (horflag | 4320 | = XINT (pixel_size) / (horflag |
| 4320 | ? FRAME_COLUMN_WIDTH (f) | 4321 | ? FRAME_COLUMN_WIDTH (f) |
| 4321 | : FRAME_LINE_HEIGHT (f)); | 4322 | : FRAME_LINE_HEIGHT (f)); |
| @@ -4452,7 +4453,7 @@ set correctly. See the code of `split-window' for how this is done. */) | |||
| 4452 | /* Iso-coordinates and sizes are assigned by window_resize_apply, | 4453 | /* Iso-coordinates and sizes are assigned by window_resize_apply, |
| 4453 | get them ready here. */ | 4454 | get them ready here. */ |
| 4454 | wset_new_pixel (n, pixel_size); | 4455 | wset_new_pixel (n, pixel_size); |
| 4455 | int sum = 0; | 4456 | EMACS_INT sum = 0; |
| 4456 | c = XWINDOW (p->contents); | 4457 | c = XWINDOW (p->contents); |
| 4457 | while (c) | 4458 | while (c) |
| 4458 | { | 4459 | { |
| @@ -6204,14 +6205,12 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6204 | { | 6205 | { |
| 6205 | Lisp_Object window; | 6206 | Lisp_Object window; |
| 6206 | Lisp_Object dead_windows = Qnil; | 6207 | Lisp_Object dead_windows = Qnil; |
| 6207 | register Lisp_Object tem, par, pers; | 6208 | Lisp_Object tem, par, pers; |
| 6208 | register struct window *w; | 6209 | struct window *w; |
| 6209 | register struct saved_window *p; | 6210 | struct saved_window *p; |
| 6210 | struct window *root_window; | 6211 | struct window *root_window; |
| 6211 | struct window **leaf_windows; | 6212 | struct window **leaf_windows; |
| 6212 | int n_leaf_windows; | 6213 | ptrdiff_t i, k, n_leaf_windows; |
| 6213 | ptrdiff_t k; | ||
| 6214 | int i, n; | ||
| 6215 | 6214 | ||
| 6216 | /* Don't do this within the main loop below: This may call Lisp | 6215 | /* Don't do this within the main loop below: This may call Lisp |
| 6217 | code and is thus potentially unsafe while input is blocked. */ | 6216 | code and is thus potentially unsafe while input is blocked. */ |
| @@ -6256,7 +6255,7 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6256 | really like to do is to free only those matrices not reused | 6255 | really like to do is to free only those matrices not reused |
| 6257 | below. */ | 6256 | below. */ |
| 6258 | root_window = XWINDOW (FRAME_ROOT_WINDOW (f)); | 6257 | root_window = XWINDOW (FRAME_ROOT_WINDOW (f)); |
| 6259 | int nwindows = count_windows (root_window); | 6258 | ptrdiff_t nwindows = count_windows (root_window); |
| 6260 | SAFE_NALLOCA (leaf_windows, 1, nwindows); | 6259 | SAFE_NALLOCA (leaf_windows, 1, nwindows); |
| 6261 | n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0); | 6260 | n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0); |
| 6262 | 6261 | ||
| @@ -6430,13 +6429,9 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6430 | Fredirect_frame_focus (frame, data->focus_frame); | 6429 | Fredirect_frame_focus (frame, data->focus_frame); |
| 6431 | 6430 | ||
| 6432 | /* Now, free glyph matrices in windows that were not reused. */ | 6431 | /* Now, free glyph matrices in windows that were not reused. */ |
| 6433 | for (i = n = 0; i < n_leaf_windows; ++i) | 6432 | for (i = 0; i < n_leaf_windows; i++) |
| 6434 | { | 6433 | if (NILP (leaf_windows[i]->contents)) |
| 6435 | if (NILP (leaf_windows[i]->contents)) | 6434 | free_window_matrices (leaf_windows[i]); |
| 6436 | free_window_matrices (leaf_windows[i]); | ||
| 6437 | else if (EQ (leaf_windows[i]->contents, new_current_buffer)) | ||
| 6438 | ++n; | ||
| 6439 | } | ||
| 6440 | 6435 | ||
| 6441 | /* Allow x_set_window_size again and apply frame size changes if | 6436 | /* Allow x_set_window_size again and apply frame size changes if |
| 6442 | needed. */ | 6437 | needed. */ |
| @@ -6529,29 +6524,27 @@ delete_all_child_windows (Lisp_Object window) | |||
| 6529 | Vwindow_list = Qnil; | 6524 | Vwindow_list = Qnil; |
| 6530 | } | 6525 | } |
| 6531 | 6526 | ||
| 6532 | static int | 6527 | static ptrdiff_t |
| 6533 | count_windows (register struct window *window) | 6528 | count_windows (struct window *window) |
| 6534 | { | 6529 | { |
| 6535 | register int count = 1; | 6530 | return get_leaf_windows (window, NULL, 0); |
| 6536 | if (!NILP (window->next)) | ||
| 6537 | count += count_windows (XWINDOW (window->next)); | ||
| 6538 | if (WINDOWP (window->contents)) | ||
| 6539 | count += count_windows (XWINDOW (window->contents)); | ||
| 6540 | return count; | ||
| 6541 | } | 6531 | } |
| 6542 | 6532 | ||
| 6543 | 6533 | /* If vector FLAT is non-null, fill it with leaf windows under W, | |
| 6544 | /* Fill vector FLAT with leaf windows under W, starting at index I. | 6534 | starting at index I. Value is last index + 1. */ |
| 6545 | Value is last index + 1. */ | 6535 | static ptrdiff_t |
| 6546 | static int | 6536 | get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i) |
| 6547 | get_leaf_windows (struct window *w, struct window **flat, int i) | ||
| 6548 | { | 6537 | { |
| 6549 | while (w) | 6538 | while (w) |
| 6550 | { | 6539 | { |
| 6551 | if (WINDOWP (w->contents)) | 6540 | if (WINDOWP (w->contents)) |
| 6552 | i = get_leaf_windows (XWINDOW (w->contents), flat, i); | 6541 | i = get_leaf_windows (XWINDOW (w->contents), flat, i); |
| 6553 | else | 6542 | else |
| 6554 | flat[i++] = w; | 6543 | { |
| 6544 | if (flat) | ||
| 6545 | flat[i] = w; | ||
| 6546 | i++; | ||
| 6547 | } | ||
| 6555 | 6548 | ||
| 6556 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | 6549 | w = NILP (w->next) ? 0 : XWINDOW (w->next); |
| 6557 | } | 6550 | } |
| @@ -6598,12 +6591,12 @@ get_phys_cursor_glyph (struct window *w) | |||
| 6598 | } | 6591 | } |
| 6599 | 6592 | ||
| 6600 | 6593 | ||
| 6601 | static int | 6594 | static ptrdiff_t |
| 6602 | save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) | 6595 | save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i) |
| 6603 | { | 6596 | { |
| 6604 | register struct saved_window *p; | 6597 | struct saved_window *p; |
| 6605 | register struct window *w; | 6598 | struct window *w; |
| 6606 | register Lisp_Object tem, pers, par; | 6599 | Lisp_Object tem, pers, par; |
| 6607 | 6600 | ||
| 6608 | for (; !NILP (window); window = w->next) | 6601 | for (; !NILP (window); window = w->next) |
| 6609 | { | 6602 | { |
| @@ -6741,10 +6734,9 @@ redirection (see `redirect-frame-focus'). The variable | |||
| 6741 | saved by this function. */) | 6734 | saved by this function. */) |
| 6742 | (Lisp_Object frame) | 6735 | (Lisp_Object frame) |
| 6743 | { | 6736 | { |
| 6744 | register Lisp_Object tem; | 6737 | Lisp_Object tem; |
| 6745 | register int n_windows; | 6738 | ptrdiff_t i, n_windows; |
| 6746 | register struct save_window_data *data; | 6739 | struct save_window_data *data; |
| 6747 | register int i; | ||
| 6748 | struct frame *f = decode_live_frame (frame); | 6740 | struct frame *f = decode_live_frame (frame); |
| 6749 | 6741 | ||
| 6750 | n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f))); | 6742 | n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f))); |
| @@ -6794,17 +6786,22 @@ apply_window_adjustment (struct window *w) | |||
| 6794 | Marginal Areas | 6786 | Marginal Areas |
| 6795 | ***********************************************************************/ | 6787 | ***********************************************************************/ |
| 6796 | 6788 | ||
| 6789 | static int | ||
| 6790 | extract_dimension (Lisp_Object dimension) | ||
| 6791 | { | ||
| 6792 | if (NILP (dimension)) | ||
| 6793 | return -1; | ||
| 6794 | CHECK_RANGED_INTEGER (dimension, 0, INT_MAX); | ||
| 6795 | return XINT (dimension); | ||
| 6796 | } | ||
| 6797 | |||
| 6797 | static struct window * | 6798 | static struct window * |
| 6798 | set_window_margins (struct window *w, Lisp_Object left_width, | 6799 | set_window_margins (struct window *w, Lisp_Object left_width, |
| 6799 | Lisp_Object right_width) | 6800 | Lisp_Object right_width) |
| 6800 | { | 6801 | { |
| 6801 | int left, right; | ||
| 6802 | int unit = WINDOW_FRAME_COLUMN_WIDTH (w); | 6802 | int unit = WINDOW_FRAME_COLUMN_WIDTH (w); |
| 6803 | 6803 | int left = NILP (left_width) ? 0 : extract_dimension (left_width); | |
| 6804 | left = (NILP (left_width) ? 0 | 6804 | int right = NILP (right_width) ? 0 : extract_dimension (right_width); |
| 6805 | : (CHECK_NATNUM (left_width), XINT (left_width))); | ||
| 6806 | right = (NILP (right_width) ? 0 | ||
| 6807 | : (CHECK_NATNUM (right_width), XINT (right_width))); | ||
| 6808 | 6805 | ||
| 6809 | if (w->left_margin_cols != left || w->right_margin_cols != right) | 6806 | if (w->left_margin_cols != left || w->right_margin_cols != right) |
| 6810 | { | 6807 | { |
| @@ -6873,13 +6870,9 @@ static struct window * | |||
| 6873 | set_window_fringes (struct window *w, Lisp_Object left_width, | 6870 | set_window_fringes (struct window *w, Lisp_Object left_width, |
| 6874 | Lisp_Object right_width, Lisp_Object outside_margins) | 6871 | Lisp_Object right_width, Lisp_Object outside_margins) |
| 6875 | { | 6872 | { |
| 6876 | int left, right; | ||
| 6877 | bool outside = !NILP (outside_margins); | 6873 | bool outside = !NILP (outside_margins); |
| 6878 | 6874 | int left = extract_dimension (left_width); | |
| 6879 | left = (NILP (left_width) ? -1 | 6875 | int right = extract_dimension (right_width); |
| 6880 | : (CHECK_NATNUM (left_width), XINT (left_width))); | ||
| 6881 | right = (NILP (right_width) ? -1 | ||
| 6882 | : (CHECK_NATNUM (right_width), XINT (right_width))); | ||
| 6883 | 6876 | ||
| 6884 | /* Do nothing on a tty or if nothing to actually change. */ | 6877 | /* Do nothing on a tty or if nothing to actually change. */ |
| 6885 | if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) | 6878 | if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) |
| @@ -6959,7 +6952,7 @@ set_window_scroll_bars (struct window *w, Lisp_Object width, | |||
| 6959 | Lisp_Object vertical_type, Lisp_Object height, | 6952 | Lisp_Object vertical_type, Lisp_Object height, |
| 6960 | Lisp_Object horizontal_type) | 6953 | Lisp_Object horizontal_type) |
| 6961 | { | 6954 | { |
| 6962 | int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width))); | 6955 | int iwidth = extract_dimension (width); |
| 6963 | bool changed = false; | 6956 | bool changed = false; |
| 6964 | 6957 | ||
| 6965 | if (iwidth == 0) | 6958 | if (iwidth == 0) |
| @@ -6989,7 +6982,7 @@ set_window_scroll_bars (struct window *w, Lisp_Object width, | |||
| 6989 | 6982 | ||
| 6990 | #if USE_HORIZONTAL_SCROLL_BARS | 6983 | #if USE_HORIZONTAL_SCROLL_BARS |
| 6991 | { | 6984 | { |
| 6992 | int iheight = (NILP (height) ? -1 : (CHECK_NATNUM (height), XINT (height))); | 6985 | int iheight = extract_dimension (height); |
| 6993 | 6986 | ||
| 6994 | if (MINI_WINDOW_P (w) || iheight == 0) | 6987 | if (MINI_WINDOW_P (w) || iheight == 0) |
| 6995 | horizontal_type = Qnil; | 6988 | horizontal_type = Qnil; |
diff --git a/src/window.h b/src/window.h index 96e7438f46e..eaff57eaedf 100644 --- a/src/window.h +++ b/src/window.h | |||
| @@ -195,10 +195,10 @@ struct window | |||
| 195 | Lisp_Object next_buffers; | 195 | Lisp_Object next_buffers; |
| 196 | 196 | ||
| 197 | /* Number saying how recently window was selected. */ | 197 | /* Number saying how recently window was selected. */ |
| 198 | int use_time; | 198 | EMACS_INT use_time; |
| 199 | 199 | ||
| 200 | /* Unique number of window assigned when it was created. */ | 200 | /* Unique number of window assigned when it was created. */ |
| 201 | int sequence_number; | 201 | EMACS_INT sequence_number; |
| 202 | 202 | ||
| 203 | /* The upper left corner pixel coordinates of this window, as | 203 | /* The upper left corner pixel coordinates of this window, as |
| 204 | integers relative to upper left corner of frame = 0, 0. */ | 204 | integers relative to upper left corner of frame = 0, 0. */ |
| @@ -990,7 +990,7 @@ extern Lisp_Object selected_window; | |||
| 990 | recently used window. Its only users are Fselect_window, | 990 | recently used window. Its only users are Fselect_window, |
| 991 | init_window_once, and make_frame. */ | 991 | init_window_once, and make_frame. */ |
| 992 | 992 | ||
| 993 | extern int window_select_count; | 993 | extern EMACS_INT window_select_count; |
| 994 | 994 | ||
| 995 | /* The minibuffer window of the selected frame. | 995 | /* The minibuffer window of the selected frame. |
| 996 | Note that you cannot test for minibufferness of an arbitrary window | 996 | Note that you cannot test for minibufferness of an arbitrary window |