aboutsummaryrefslogtreecommitdiffstats
path: root/src/keyboard.c
diff options
context:
space:
mode:
authorPaul Eggert2014-09-07 00:04:01 -0700
committerPaul Eggert2014-09-07 00:04:01 -0700
commitb3bf18b3b87ac8f00857b8bfc3f2c74cf0e2fb7d (patch)
treecf138164e4f8887394f52cb22da594d1713da316 /src/keyboard.c
parent930fb80f9e2815e599eb1de699668d42e305fa21 (diff)
downloademacs-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.c43
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)
500static void 500static void
501echo_add_key (Lisp_Object c) 501echo_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);
1147Lisp_Object 1150Lisp_Object
1148command_loop (void) 1151command_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
7992tool_bar_items (Lisp_Object reuse, int *nitems) 8000tool_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