diff options
| author | Paul Eggert | 2014-09-07 00:04:01 -0700 |
|---|---|---|
| committer | Paul Eggert | 2014-09-07 00:04:01 -0700 |
| commit | b3bf18b3b87ac8f00857b8bfc3f2c74cf0e2fb7d (patch) | |
| tree | cf138164e4f8887394f52cb22da594d1713da316 /src/keyboard.c | |
| parent | 930fb80f9e2815e599eb1de699668d42e305fa21 (diff) | |
| download | emacs-b3bf18b3b87ac8f00857b8bfc3f2c74cf0e2fb7d.tar.gz emacs-b3bf18b3b87ac8f00857b8bfc3f2c74cf0e2fb7d.zip | |
Use SAFE_ALLOCA etc. to avoid unbounded stack allocation.
This follows up on the recent thread in emacs-devel on alloca; see:
http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00042.html
This patch also cleans up alloca-related glitches noted while
examining the code looking for unbounded alloca.
* alloc.c (listn):
* callproc.c (init_callproc):
Rewrite to avoid need for alloca.
* buffer.c (mouse_face_overlay_overlaps)
(report_overlay_modification):
* buffer.h (GET_OVERLAYS_AT):
* coding.c (make_subsidiaries):
* doc.c (Fsnarf_documentation):
* editfns.c (Fuser_full_name):
* fileio.c (Ffile_name_directory, Fexpand_file_name)
(search_embedded_absfilename, Fsubstitute_in_file_name):
* fns.c (Fmake_hash_table):
* font.c (font_vconcat_entity_vectors, font_update_drivers):
* fontset.c (fontset_pattern_regexp, Ffontset_info):
* frame.c (Fmake_terminal_frame, x_set_frame_parameters)
(xrdb_get_resource, x_get_resource_string):
* ftfont.c (ftfont_get_charset, ftfont_check_otf, ftfont_drive_otf):
* ftxfont.c (ftxfont_draw):
* image.c (xbm_load, xpm_load, jpeg_load_body):
* keyboard.c (echo_add_key, menu_bar_items, tool_bar_items):
* keymap.c (Fdescribe_buffer_bindings, describe_map):
* lread.c (openp):
* menu.c (digest_single_submenu, find_and_call_menu_selection)
(find_and_return_menu_selection):
* print.c (PRINTFINISH):
* process.c (Fformat_network_address):
* scroll.c (do_scrolling, do_direct_scrolling, scrolling_1):
* search.c (search_buffer, Fmatch_data, Fregexp_quote):
* sound.c (wav_play, au_play):
* syntax.c (skip_chars):
* term.c (tty_menu_activate, tty_menu_show):
* textprop.c (get_char_property_and_overlay):
* window.c (Fset_window_configuration):
* xdisp.c (safe__call, next_overlay_change, vmessage)
(compute_overhangs_and_x, draw_glyphs, note_mouse_highlight):
* xfaces.c (face_at_buffer_position):
* xmenu.c (x_menu_show):
Use SAFE_ALLOCA etc. instead of plain alloca, since the
allocation size isn't bounded.
* callint.c (Fcall_interactively): Redo memory_full check
so that it can be done at compile-time on some platforms.
* coding.c (MAX_LOOKUP_MAX): New constant.
(get_translation_table): Use it.
* callproc.c (call_process): Use SAFE_NALLOCA instead of
SAFE_ALLOCA, to catch integer overflows on size calculation.
(exec_failed) [!DOS_NT]: New function.
(child_setup) [!DOS_NT]: Use it.
* editfns.c (Ftranspose_regions):
Hoist USE_SAFE_ALLOC + SAFE_FREE out of 'if'.
* editfns.c (check_translation):
Allocate larger buffers on the heap.
* eval.c (internal_lisp_condition_case):
Check for MAX_ALLOCA overflow.
* fns.c (sort_vector): Use SAFE_ALLOCA_LISP rather than Fmake_vector.
(Fbase64_encode_region, Fbase64_decode_region):
Avoid unnecessary calls to SAFE_FREE before 'error'.
* buffer.c (mouse_face_overlay_overlaps):
* editfns.c (Fget_pos_property, check_translation):
* eval.c (Ffuncall):
* font.c (font_unparse_xlfd, font_find_for_lface):
* ftfont.c (ftfont_drive_otf):
* keyboard.c (echo_add_key, read_decoded_event_from_main_queue)
(menu_bar_items, tool_bar_items):
* sound.c (Fplay_sound_internal):
* xdisp.c (load_overlay_strings, dump_glyph_row):
Use an ordinary auto buffer rather than alloca, since the
allocation size is fixed and small.
* ftfont.c: Include <c-strcase.h>.
(matching_prefix): New function.
(get_adstyle_property): Use it, to avoid need for alloca.
* keyboard.c (echo_add_key):
* keymap.c (describe_map): Use ptrdiff_t, not int.
* keyboard.c (echo_add_key): Prefer sizeof to strlen.
* keymap.c (Fdescribe_buffer_bindings): Use SBYTES, not SCHARS,
when counting bytes.
* lisp.h (xlispstrdupa): Remove, replacing with ...
(SAFE_ALLOCA_STRING): ... new macro with different API.
This fixes a portability problem, namely, alloca result
passed to another function. All uses changed.
(SAFE_ALLOCA, SAFE_ALLOCA_LISP): Check for MAX_ALLOCA,
not MAX_ALLOCA - 1.
* regex.c (REGEX_USE_SAFE_ALLOCA, REGEX_SAFE_FREE)
(REGEX_ALLOCATE): New macros.
(REGEX_REALLOCATE, REGEX_ALLOCATE_STACK, REGEX_REALLOCATE_STACK)
(REGEX_FREE_STACK, FREE_VARIABLES, re_match_2_internal):
Use them.
* xdisp.c (message3): Use SAFE_ALLOCA_STRING rather than doing it
by hand.
(decode_mode_spec_coding): Store directly into buf rather than
into an alloca temporary and copying the temporary to the buf.
Fixes: debbugs:18410
Diffstat (limited to 'src/keyboard.c')
| -rw-r--r-- | src/keyboard.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index a8083fa4271..9e14560404b 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -500,10 +500,12 @@ kset_system_key_syms (struct kboard *kb, Lisp_Object val) | |||
| 500 | static void | 500 | static void |
| 501 | echo_add_key (Lisp_Object c) | 501 | echo_add_key (Lisp_Object c) |
| 502 | { | 502 | { |
| 503 | int size = KEY_DESCRIPTION_SIZE + 100; | 503 | char initbuf[KEY_DESCRIPTION_SIZE + 100]; |
| 504 | char *buffer = alloca (size); | 504 | ptrdiff_t size = sizeof initbuf; |
| 505 | char *buffer = initbuf; | ||
| 505 | char *ptr = buffer; | 506 | char *ptr = buffer; |
| 506 | Lisp_Object echo_string; | 507 | Lisp_Object echo_string; |
| 508 | USE_SAFE_ALLOCA; | ||
| 507 | 509 | ||
| 508 | echo_string = KVAR (current_kboard, echo_string); | 510 | echo_string = KVAR (current_kboard, echo_string); |
| 509 | 511 | ||
| @@ -515,13 +517,13 @@ echo_add_key (Lisp_Object c) | |||
| 515 | else if (SYMBOLP (c)) | 517 | else if (SYMBOLP (c)) |
| 516 | { | 518 | { |
| 517 | Lisp_Object name = SYMBOL_NAME (c); | 519 | Lisp_Object name = SYMBOL_NAME (c); |
| 518 | int nbytes = SBYTES (name); | 520 | ptrdiff_t nbytes = SBYTES (name); |
| 519 | 521 | ||
| 520 | if (size - (ptr - buffer) < nbytes) | 522 | if (size - (ptr - buffer) < nbytes) |
| 521 | { | 523 | { |
| 522 | int offset = ptr - buffer; | 524 | ptrdiff_t offset = ptr - buffer; |
| 523 | size = max (2 * size, size + nbytes); | 525 | size = max (2 * size, size + nbytes); |
| 524 | buffer = alloca (size); | 526 | buffer = SAFE_ALLOCA (size); |
| 525 | ptr = buffer + offset; | 527 | ptr = buffer + offset; |
| 526 | } | 528 | } |
| 527 | 529 | ||
| @@ -532,14 +534,14 @@ echo_add_key (Lisp_Object c) | |||
| 532 | if ((NILP (echo_string) || SCHARS (echo_string) == 0) | 534 | if ((NILP (echo_string) || SCHARS (echo_string) == 0) |
| 533 | && help_char_p (c)) | 535 | && help_char_p (c)) |
| 534 | { | 536 | { |
| 535 | const char *text = " (Type ? for further options)"; | 537 | static const char text[] = " (Type ? for further options)"; |
| 536 | int len = strlen (text); | 538 | int len = sizeof text - 1; |
| 537 | 539 | ||
| 538 | if (size - (ptr - buffer) < len) | 540 | if (size - (ptr - buffer) < len) |
| 539 | { | 541 | { |
| 540 | int offset = ptr - buffer; | 542 | ptrdiff_t offset = ptr - buffer; |
| 541 | size += len; | 543 | size += len; |
| 542 | buffer = alloca (size); | 544 | buffer = SAFE_ALLOCA (size); |
| 543 | ptr = buffer + offset; | 545 | ptr = buffer + offset; |
| 544 | } | 546 | } |
| 545 | 547 | ||
| @@ -572,6 +574,7 @@ echo_add_key (Lisp_Object c) | |||
| 572 | kset_echo_string | 574 | kset_echo_string |
| 573 | (current_kboard, | 575 | (current_kboard, |
| 574 | concat2 (echo_string, make_string (buffer, ptr - buffer))); | 576 | concat2 (echo_string, make_string (buffer, ptr - buffer))); |
| 577 | SAFE_FREE (); | ||
| 575 | } | 578 | } |
| 576 | 579 | ||
| 577 | /* Add C to the echo string, if echoing is going on. C can be a | 580 | /* Add C to the echo string, if echoing is going on. C can be a |
| @@ -1147,7 +1150,7 @@ static Lisp_Object top_level_1 (Lisp_Object); | |||
| 1147 | Lisp_Object | 1150 | Lisp_Object |
| 1148 | command_loop (void) | 1151 | command_loop (void) |
| 1149 | { | 1152 | { |
| 1150 | #ifdef HAVE_STACK_OVERFLOW_HANDLING | 1153 | #ifdef HAVE_STACK_OVERFLOW_HANDLING |
| 1151 | /* At least on GNU/Linux, saving signal mask is important here. */ | 1154 | /* At least on GNU/Linux, saving signal mask is important here. */ |
| 1152 | if (sigsetjmp (return_to_command_loop, 1) != 0) | 1155 | if (sigsetjmp (return_to_command_loop, 1) != 0) |
| 1153 | { | 1156 | { |
| @@ -2351,14 +2354,15 @@ read_decoded_event_from_main_queue (struct timespec *end_time, | |||
| 2351 | { /* An encoded byte sequence, let's try to decode it. */ | 2354 | { /* An encoded byte sequence, let's try to decode it. */ |
| 2352 | struct coding_system *coding | 2355 | struct coding_system *coding |
| 2353 | = TERMINAL_KEYBOARD_CODING (terminal); | 2356 | = TERMINAL_KEYBOARD_CODING (terminal); |
| 2354 | unsigned char *src = alloca (n); | 2357 | unsigned char src[MAX_ENCODED_BYTES]; |
| 2358 | unsigned char dest[4 * sizeof src]; | ||
| 2355 | int i; | 2359 | int i; |
| 2356 | for (i = 0; i < n; i++) | 2360 | for (i = 0; i < n; i++) |
| 2357 | src[i] = XINT (events[i]); | 2361 | src[i] = XINT (events[i]); |
| 2358 | if (meta_key != 2) | 2362 | if (meta_key != 2) |
| 2359 | for (i = 0; i < n; i++) | 2363 | for (i = 0; i < n; i++) |
| 2360 | src[i] &= ~0x80; | 2364 | src[i] &= ~0x80; |
| 2361 | coding->destination = alloca (n * 4); | 2365 | coding->destination = dest; |
| 2362 | coding->dst_bytes = n * 4; | 2366 | coding->dst_bytes = n * 4; |
| 2363 | decode_coding_c_string (coding, src, n, Qnil); | 2367 | decode_coding_c_string (coding, src, n, Qnil); |
| 2364 | eassert (coding->produced_char <= n); | 2368 | eassert (coding->produced_char <= n); |
| @@ -7434,11 +7438,14 @@ menu_bar_items (Lisp_Object old) | |||
| 7434 | in the current keymaps, or nil where it is not a prefix. */ | 7438 | in the current keymaps, or nil where it is not a prefix. */ |
| 7435 | Lisp_Object *maps; | 7439 | Lisp_Object *maps; |
| 7436 | 7440 | ||
| 7441 | Lisp_Object mapsbuf[3]; | ||
| 7437 | Lisp_Object def, tail; | 7442 | Lisp_Object def, tail; |
| 7438 | 7443 | ||
| 7439 | ptrdiff_t mapno; | 7444 | ptrdiff_t mapno; |
| 7440 | Lisp_Object oquit; | 7445 | Lisp_Object oquit; |
| 7441 | 7446 | ||
| 7447 | USE_SAFE_ALLOCA; | ||
| 7448 | |||
| 7442 | /* In order to build the menus, we need to call the keymap | 7449 | /* In order to build the menus, we need to call the keymap |
| 7443 | accessors. They all call QUIT. But this function is called | 7450 | accessors. They all call QUIT. But this function is called |
| 7444 | during redisplay, during which a quit is fatal. So inhibit | 7451 | during redisplay, during which a quit is fatal. So inhibit |
| @@ -7467,7 +7474,7 @@ menu_bar_items (Lisp_Object old) | |||
| 7467 | && !NILP (Voverriding_local_map)) | 7474 | && !NILP (Voverriding_local_map)) |
| 7468 | { | 7475 | { |
| 7469 | /* Yes, use them (if non-nil) as well as the global map. */ | 7476 | /* Yes, use them (if non-nil) as well as the global map. */ |
| 7470 | maps = alloca (3 * sizeof (maps[0])); | 7477 | maps = mapsbuf; |
| 7471 | nmaps = 0; | 7478 | nmaps = 0; |
| 7472 | if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map))) | 7479 | if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map))) |
| 7473 | maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map); | 7480 | maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map); |
| @@ -7484,7 +7491,7 @@ menu_bar_items (Lisp_Object old) | |||
| 7484 | Lisp_Object tem; | 7491 | Lisp_Object tem; |
| 7485 | ptrdiff_t nminor; | 7492 | ptrdiff_t nminor; |
| 7486 | nminor = current_minor_maps (NULL, &tmaps); | 7493 | nminor = current_minor_maps (NULL, &tmaps); |
| 7487 | maps = alloca ((nminor + 4) * sizeof *maps); | 7494 | SAFE_NALLOCA (maps, 1, nminor + 4); |
| 7488 | nmaps = 0; | 7495 | nmaps = 0; |
| 7489 | tem = KVAR (current_kboard, Voverriding_terminal_local_map); | 7496 | tem = KVAR (current_kboard, Voverriding_terminal_local_map); |
| 7490 | if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag)) | 7497 | if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag)) |
| @@ -7556,6 +7563,7 @@ menu_bar_items (Lisp_Object old) | |||
| 7556 | } | 7563 | } |
| 7557 | 7564 | ||
| 7558 | Vinhibit_quit = oquit; | 7565 | Vinhibit_quit = oquit; |
| 7566 | SAFE_FREE (); | ||
| 7559 | return menu_bar_items_vector; | 7567 | return menu_bar_items_vector; |
| 7560 | } | 7568 | } |
| 7561 | 7569 | ||
| @@ -7992,9 +8000,11 @@ Lisp_Object | |||
| 7992 | tool_bar_items (Lisp_Object reuse, int *nitems) | 8000 | tool_bar_items (Lisp_Object reuse, int *nitems) |
| 7993 | { | 8001 | { |
| 7994 | Lisp_Object *maps; | 8002 | Lisp_Object *maps; |
| 8003 | Lisp_Object mapsbuf[3]; | ||
| 7995 | ptrdiff_t nmaps, i; | 8004 | ptrdiff_t nmaps, i; |
| 7996 | Lisp_Object oquit; | 8005 | Lisp_Object oquit; |
| 7997 | Lisp_Object *tmaps; | 8006 | Lisp_Object *tmaps; |
| 8007 | USE_SAFE_ALLOCA; | ||
| 7998 | 8008 | ||
| 7999 | *nitems = 0; | 8009 | *nitems = 0; |
| 8000 | 8010 | ||
| @@ -8018,7 +8028,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems) | |||
| 8018 | && !NILP (Voverriding_local_map)) | 8028 | && !NILP (Voverriding_local_map)) |
| 8019 | { | 8029 | { |
| 8020 | /* Yes, use them (if non-nil) as well as the global map. */ | 8030 | /* Yes, use them (if non-nil) as well as the global map. */ |
| 8021 | maps = alloca (3 * sizeof *maps); | 8031 | maps = mapsbuf; |
| 8022 | nmaps = 0; | 8032 | nmaps = 0; |
| 8023 | if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map))) | 8033 | if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map))) |
| 8024 | maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map); | 8034 | maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map); |
| @@ -8035,7 +8045,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems) | |||
| 8035 | Lisp_Object tem; | 8045 | Lisp_Object tem; |
| 8036 | ptrdiff_t nminor; | 8046 | ptrdiff_t nminor; |
| 8037 | nminor = current_minor_maps (NULL, &tmaps); | 8047 | nminor = current_minor_maps (NULL, &tmaps); |
| 8038 | maps = alloca ((nminor + 4) * sizeof *maps); | 8048 | SAFE_NALLOCA (maps, 1, nminor + 4); |
| 8039 | nmaps = 0; | 8049 | nmaps = 0; |
| 8040 | tem = KVAR (current_kboard, Voverriding_terminal_local_map); | 8050 | tem = KVAR (current_kboard, Voverriding_terminal_local_map); |
| 8041 | if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag)) | 8051 | if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag)) |
| @@ -8064,6 +8074,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems) | |||
| 8064 | 8074 | ||
| 8065 | Vinhibit_quit = oquit; | 8075 | Vinhibit_quit = oquit; |
| 8066 | *nitems = ntool_bar_items / TOOL_BAR_ITEM_NSLOTS; | 8076 | *nitems = ntool_bar_items / TOOL_BAR_ITEM_NSLOTS; |
| 8077 | SAFE_FREE (); | ||
| 8067 | return tool_bar_items_vector; | 8078 | return tool_bar_items_vector; |
| 8068 | } | 8079 | } |
| 8069 | 8080 | ||