aboutsummaryrefslogtreecommitdiffstats
path: root/src/fileio.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/fileio.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/fileio.c')
-rw-r--r--src/fileio.c58
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.
396Given a Unix syntax file name, returns a string ending in slash. */) 396Given 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