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/fileio.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/fileio.c')
| -rw-r--r-- | src/fileio.c | 58 |
1 files changed, 31 insertions, 27 deletions
diff --git a/src/fileio.c b/src/fileio.c index 80b7abc5c74..f98cdc5d3e4 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -396,13 +396,6 @@ Otherwise return a directory name. | |||
| 396 | Given a Unix syntax file name, returns a string ending in slash. */) | 396 | Given a Unix syntax file name, returns a string ending in slash. */) |
| 397 | (Lisp_Object filename) | 397 | (Lisp_Object filename) |
| 398 | { | 398 | { |
| 399 | #ifndef DOS_NT | ||
| 400 | register const char *beg; | ||
| 401 | #else | ||
| 402 | register char *beg; | ||
| 403 | Lisp_Object tem_fn; | ||
| 404 | #endif | ||
| 405 | register const char *p; | ||
| 406 | Lisp_Object handler; | 399 | Lisp_Object handler; |
| 407 | 400 | ||
| 408 | CHECK_STRING (filename); | 401 | CHECK_STRING (filename); |
| @@ -417,12 +410,8 @@ Given a Unix syntax file name, returns a string ending in slash. */) | |||
| 417 | return STRINGP (handled_name) ? handled_name : Qnil; | 410 | return STRINGP (handled_name) ? handled_name : Qnil; |
| 418 | } | 411 | } |
| 419 | 412 | ||
| 420 | #ifdef DOS_NT | 413 | char *beg = SSDATA (filename); |
| 421 | beg = xlispstrdupa (filename); | 414 | char const *p = beg + SBYTES (filename); |
| 422 | #else | ||
| 423 | beg = SSDATA (filename); | ||
| 424 | #endif | ||
| 425 | p = beg + SBYTES (filename); | ||
| 426 | 415 | ||
| 427 | while (p != beg && !IS_DIRECTORY_SEP (p[-1]) | 416 | while (p != beg && !IS_DIRECTORY_SEP (p[-1]) |
| 428 | #ifdef DOS_NT | 417 | #ifdef DOS_NT |
| @@ -438,6 +427,11 @@ Given a Unix syntax file name, returns a string ending in slash. */) | |||
| 438 | return Qnil; | 427 | return Qnil; |
| 439 | #ifdef DOS_NT | 428 | #ifdef DOS_NT |
| 440 | /* Expansion of "c:" to drive and default directory. */ | 429 | /* Expansion of "c:" to drive and default directory. */ |
| 430 | Lisp_Object tem_fn; | ||
| 431 | USE_SAFE_ALLOCA; | ||
| 432 | SAFE_ALLOCA_STRING (beg, filename); | ||
| 433 | p = beg + (p - SSDATA (filename)); | ||
| 434 | |||
| 441 | if (p[-1] == ':') | 435 | if (p[-1] == ':') |
| 442 | { | 436 | { |
| 443 | /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ | 437 | /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ |
| @@ -481,6 +475,7 @@ Given a Unix syntax file name, returns a string ending in slash. */) | |||
| 481 | dostounix_filename (beg); | 475 | dostounix_filename (beg); |
| 482 | tem_fn = make_specified_string (beg, -1, p - beg, 0); | 476 | tem_fn = make_specified_string (beg, -1, p - beg, 0); |
| 483 | } | 477 | } |
| 478 | SAFE_FREE (); | ||
| 484 | return tem_fn; | 479 | return tem_fn; |
| 485 | #else /* DOS_NT */ | 480 | #else /* DOS_NT */ |
| 486 | return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename)); | 481 | return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename)); |
| @@ -1019,7 +1014,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1019 | #endif | 1014 | #endif |
| 1020 | 1015 | ||
| 1021 | /* Make a local copy of NAME to protect it from GC in DECODE_FILE below. */ | 1016 | /* Make a local copy of NAME to protect it from GC in DECODE_FILE below. */ |
| 1022 | nm = xlispstrdupa (name); | 1017 | SAFE_ALLOCA_STRING (nm, name); |
| 1023 | nmlim = nm + SBYTES (name); | 1018 | nmlim = nm + SBYTES (name); |
| 1024 | 1019 | ||
| 1025 | #ifdef DOS_NT | 1020 | #ifdef DOS_NT |
| @@ -1122,12 +1117,12 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1122 | if (!NILP (Vw32_downcase_file_names)) | 1117 | if (!NILP (Vw32_downcase_file_names)) |
| 1123 | name = Fdowncase (name); | 1118 | name = Fdowncase (name); |
| 1124 | #endif | 1119 | #endif |
| 1125 | return name; | ||
| 1126 | #else /* not DOS_NT */ | 1120 | #else /* not DOS_NT */ |
| 1127 | if (strcmp (nm, SSDATA (name)) == 0) | 1121 | if (strcmp (nm, SSDATA (name)) != 0) |
| 1128 | return name; | 1122 | name = make_specified_string (nm, -1, nmlim - nm, multibyte); |
| 1129 | return make_specified_string (nm, -1, nmlim - nm, multibyte); | ||
| 1130 | #endif /* not DOS_NT */ | 1123 | #endif /* not DOS_NT */ |
| 1124 | SAFE_FREE (); | ||
| 1125 | return name; | ||
| 1131 | } | 1126 | } |
| 1132 | } | 1127 | } |
| 1133 | 1128 | ||
| @@ -1729,7 +1724,8 @@ search_embedded_absfilename (char *nm, char *endp) | |||
| 1729 | for (s = p; *s && !IS_DIRECTORY_SEP (*s); s++); | 1724 | for (s = p; *s && !IS_DIRECTORY_SEP (*s); s++); |
| 1730 | if (p[0] == '~' && s > p + 1) /* We've got "/~something/". */ | 1725 | if (p[0] == '~' && s > p + 1) /* We've got "/~something/". */ |
| 1731 | { | 1726 | { |
| 1732 | char *o = alloca (s - p + 1); | 1727 | USE_SAFE_ALLOCA; |
| 1728 | char *o = SAFE_ALLOCA (s - p + 1); | ||
| 1733 | struct passwd *pw; | 1729 | struct passwd *pw; |
| 1734 | memcpy (o, p, s - p); | 1730 | memcpy (o, p, s - p); |
| 1735 | o [s - p] = 0; | 1731 | o [s - p] = 0; |
| @@ -1740,6 +1736,7 @@ search_embedded_absfilename (char *nm, char *endp) | |||
| 1740 | block_input (); | 1736 | block_input (); |
| 1741 | pw = getpwnam (o + 1); | 1737 | pw = getpwnam (o + 1); |
| 1742 | unblock_input (); | 1738 | unblock_input (); |
| 1739 | SAFE_FREE (); | ||
| 1743 | if (pw) | 1740 | if (pw) |
| 1744 | return p; | 1741 | return p; |
| 1745 | } | 1742 | } |
| @@ -1788,7 +1785,8 @@ those `/' is discarded. */) | |||
| 1788 | /* Always work on a copy of the string, in case GC happens during | 1785 | /* Always work on a copy of the string, in case GC happens during |
| 1789 | decode of environment variables, causing the original Lisp_String | 1786 | decode of environment variables, causing the original Lisp_String |
| 1790 | data to be relocated. */ | 1787 | data to be relocated. */ |
| 1791 | nm = xlispstrdupa (filename); | 1788 | USE_SAFE_ALLOCA; |
| 1789 | SAFE_ALLOCA_STRING (nm, filename); | ||
| 1792 | 1790 | ||
| 1793 | #ifdef DOS_NT | 1791 | #ifdef DOS_NT |
| 1794 | dostounix_filename (nm); | 1792 | dostounix_filename (nm); |
| @@ -1802,8 +1800,13 @@ those `/' is discarded. */) | |||
| 1802 | /* Start over with the new string, so we check the file-name-handler | 1800 | /* Start over with the new string, so we check the file-name-handler |
| 1803 | again. Important with filenames like "/home/foo//:/hello///there" | 1801 | again. Important with filenames like "/home/foo//:/hello///there" |
| 1804 | which would substitute to "/:/hello///there" rather than "/there". */ | 1802 | which would substitute to "/:/hello///there" rather than "/there". */ |
| 1805 | return Fsubstitute_in_file_name | 1803 | { |
| 1806 | (make_specified_string (p, -1, endp - p, multibyte)); | 1804 | Lisp_Object result |
| 1805 | = (Fsubstitute_in_file_name | ||
| 1806 | (make_specified_string (p, -1, endp - p, multibyte))); | ||
| 1807 | SAFE_FREE (); | ||
| 1808 | return result; | ||
| 1809 | } | ||
| 1807 | 1810 | ||
| 1808 | /* See if any variables are substituted into the string. */ | 1811 | /* See if any variables are substituted into the string. */ |
| 1809 | 1812 | ||
| @@ -1825,6 +1828,7 @@ those `/' is discarded. */) | |||
| 1825 | if (!NILP (Vw32_downcase_file_names)) | 1828 | if (!NILP (Vw32_downcase_file_names)) |
| 1826 | filename = Fdowncase (filename); | 1829 | filename = Fdowncase (filename); |
| 1827 | #endif | 1830 | #endif |
| 1831 | SAFE_FREE (); | ||
| 1828 | return filename; | 1832 | return filename; |
| 1829 | } | 1833 | } |
| 1830 | 1834 | ||
| @@ -1843,14 +1847,14 @@ those `/' is discarded. */) | |||
| 1843 | { | 1847 | { |
| 1844 | Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte); | 1848 | Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte); |
| 1845 | 1849 | ||
| 1846 | xname = Fdowncase (xname); | 1850 | filename = Fdowncase (xname); |
| 1847 | return xname; | ||
| 1848 | } | 1851 | } |
| 1849 | else | 1852 | else |
| 1850 | #endif | 1853 | #endif |
| 1851 | return (xnm == SSDATA (filename) | 1854 | if (xnm != SSDATA (filename)) |
| 1852 | ? filename | 1855 | filename = make_specified_string (xnm, -1, x - xnm, multibyte); |
| 1853 | : make_specified_string (xnm, -1, x - xnm, multibyte)); | 1856 | SAFE_FREE (); |
| 1857 | return filename; | ||
| 1854 | } | 1858 | } |
| 1855 | 1859 | ||
| 1856 | /* A slightly faster and more convenient way to get | 1860 | /* A slightly faster and more convenient way to get |