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/process.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/process.c')
| -rw-r--r-- | src/process.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/src/process.c b/src/process.c index 0d6994bdab1..ef9f295fd89 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -1386,9 +1386,10 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1386 | (ptrdiff_t nargs, Lisp_Object *args) | 1386 | (ptrdiff_t nargs, Lisp_Object *args) |
| 1387 | { | 1387 | { |
| 1388 | Lisp_Object buffer, name, program, proc, current_dir, tem; | 1388 | Lisp_Object buffer, name, program, proc, current_dir, tem; |
| 1389 | register unsigned char **new_argv; | 1389 | unsigned char **new_argv; |
| 1390 | ptrdiff_t i; | 1390 | ptrdiff_t i; |
| 1391 | ptrdiff_t count = SPECPDL_INDEX (); | 1391 | ptrdiff_t count = SPECPDL_INDEX (); |
| 1392 | USE_SAFE_ALLOCA; | ||
| 1392 | 1393 | ||
| 1393 | buffer = args[1]; | 1394 | buffer = args[1]; |
| 1394 | if (!NILP (buffer)) | 1395 | if (!NILP (buffer)) |
| @@ -1464,7 +1465,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1464 | val = Vcoding_system_for_read; | 1465 | val = Vcoding_system_for_read; |
| 1465 | if (NILP (val)) | 1466 | if (NILP (val)) |
| 1466 | { | 1467 | { |
| 1467 | args2 = alloca ((nargs + 1) * sizeof *args2); | 1468 | SAFE_ALLOCA_LISP (args2, nargs + 1); |
| 1468 | args2[0] = Qstart_process; | 1469 | args2[0] = Qstart_process; |
| 1469 | for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; | 1470 | for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; |
| 1470 | GCPRO2 (proc, current_dir); | 1471 | GCPRO2 (proc, current_dir); |
| @@ -1483,7 +1484,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1483 | { | 1484 | { |
| 1484 | if (EQ (coding_systems, Qt)) | 1485 | if (EQ (coding_systems, Qt)) |
| 1485 | { | 1486 | { |
| 1486 | args2 = alloca ((nargs + 1) * sizeof *args2); | 1487 | SAFE_ALLOCA_LISP (args2, nargs + 1); |
| 1487 | args2[0] = Qstart_process; | 1488 | args2[0] = Qstart_process; |
| 1488 | for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; | 1489 | for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; |
| 1489 | GCPRO2 (proc, current_dir); | 1490 | GCPRO2 (proc, current_dir); |
| @@ -1578,7 +1579,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1578 | 1579 | ||
| 1579 | /* Now that everything is encoded we can collect the strings into | 1580 | /* Now that everything is encoded we can collect the strings into |
| 1580 | NEW_ARGV. */ | 1581 | NEW_ARGV. */ |
| 1581 | new_argv = alloca ((nargs - 1) * sizeof *new_argv); | 1582 | SAFE_NALLOCA (new_argv, 1, nargs - 1); |
| 1582 | new_argv[nargs - 2] = 0; | 1583 | new_argv[nargs - 2] = 0; |
| 1583 | 1584 | ||
| 1584 | for (i = nargs - 2; i-- != 0; ) | 1585 | for (i = nargs - 2; i-- != 0; ) |
| @@ -1592,6 +1593,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1592 | else | 1593 | else |
| 1593 | create_pty (proc); | 1594 | create_pty (proc); |
| 1594 | 1595 | ||
| 1596 | SAFE_FREE (); | ||
| 1595 | return unbind_to (count, proc); | 1597 | return unbind_to (count, proc); |
| 1596 | } | 1598 | } |
| 1597 | 1599 | ||
| @@ -2071,8 +2073,10 @@ get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp) | |||
| 2071 | && VECTORP (XCDR (address))) | 2073 | && VECTORP (XCDR (address))) |
| 2072 | { | 2074 | { |
| 2073 | struct sockaddr *sa; | 2075 | struct sockaddr *sa; |
| 2074 | *familyp = XINT (XCAR (address)); | ||
| 2075 | p = XVECTOR (XCDR (address)); | 2076 | p = XVECTOR (XCDR (address)); |
| 2077 | if (MAX_ALLOCA - sizeof sa->sa_family < p->header.size) | ||
| 2078 | return 0; | ||
| 2079 | *familyp = XINT (XCAR (address)); | ||
| 2076 | return p->header.size + sizeof (sa->sa_family); | 2080 | return p->header.size + sizeof (sa->sa_family); |
| 2077 | } | 2081 | } |
| 2078 | return 0; | 2082 | return 0; |
| @@ -4973,18 +4977,17 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars, | |||
| 4973 | for decoding. */ | 4977 | for decoding. */ |
| 4974 | 4978 | ||
| 4975 | static int | 4979 | static int |
| 4976 | read_process_output (Lisp_Object proc, register int channel) | 4980 | read_process_output (Lisp_Object proc, int channel) |
| 4977 | { | 4981 | { |
| 4978 | register ssize_t nbytes; | 4982 | ssize_t nbytes; |
| 4979 | char *chars; | 4983 | struct Lisp_Process *p = XPROCESS (proc); |
| 4980 | register struct Lisp_Process *p = XPROCESS (proc); | ||
| 4981 | struct coding_system *coding = proc_decode_coding_system[channel]; | 4984 | struct coding_system *coding = proc_decode_coding_system[channel]; |
| 4982 | int carryover = p->decoding_carryover; | 4985 | int carryover = p->decoding_carryover; |
| 4983 | int readmax = 4096; | 4986 | enum { readmax = 4096 }; |
| 4984 | ptrdiff_t count = SPECPDL_INDEX (); | 4987 | ptrdiff_t count = SPECPDL_INDEX (); |
| 4985 | Lisp_Object odeactivate; | 4988 | Lisp_Object odeactivate; |
| 4989 | char chars[sizeof coding->carryover + readmax]; | ||
| 4986 | 4990 | ||
| 4987 | chars = alloca (carryover + readmax); | ||
| 4988 | if (carryover) | 4991 | if (carryover) |
| 4989 | /* See the comment above. */ | 4992 | /* See the comment above. */ |
| 4990 | memcpy (chars, SDATA (p->decoding_buf), carryover); | 4993 | memcpy (chars, SDATA (p->decoding_buf), carryover); |
| @@ -6837,7 +6840,7 @@ add_timer_wait_descriptor (int fd) | |||
| 6837 | { | 6840 | { |
| 6838 | FD_SET (fd, &input_wait_mask); | 6841 | FD_SET (fd, &input_wait_mask); |
| 6839 | FD_SET (fd, &non_keyboard_wait_mask); | 6842 | FD_SET (fd, &non_keyboard_wait_mask); |
| 6840 | FD_SET (fd, &non_process_wait_mask); | 6843 | FD_SET (fd, &non_process_wait_mask); |
| 6841 | fd_callback_info[fd].func = timerfd_callback; | 6844 | fd_callback_info[fd].func = timerfd_callback; |
| 6842 | fd_callback_info[fd].data = NULL; | 6845 | fd_callback_info[fd].data = NULL; |
| 6843 | fd_callback_info[fd].condition |= FOR_READ; | 6846 | fd_callback_info[fd].condition |= FOR_READ; |