aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/ChangeLog98
-rw-r--r--src/alloc.c37
-rw-r--r--src/buffer.c17
-rw-r--r--src/buffer.h14
-rw-r--r--src/callint.c34
-rw-r--r--src/callproc.c53
-rw-r--r--src/coding.c13
-rw-r--r--src/doc.c21
-rw-r--r--src/editfns.c54
-rw-r--r--src/eval.c12
-rw-r--r--src/fileio.c58
-rw-r--r--src/fns.c24
-rw-r--r--src/font.c39
-rw-r--r--src/fontset.c16
-rw-r--r--src/frame.c56
-rw-r--r--src/ftfont.c111
-rw-r--r--src/ftxfont.c4
-rw-r--r--src/image.c35
-rw-r--r--src/keyboard.c43
-rw-r--r--src/keymap.c18
-rw-r--r--src/lisp.h20
-rw-r--r--src/lread.c10
-rw-r--r--src/menu.c22
-rw-r--r--src/print.c4
-rw-r--r--src/process.c27
-rw-r--r--src/regex.c36
-rw-r--r--src/scroll.c28
-rw-r--r--src/search.c73
-rw-r--r--src/sound.c15
-rw-r--r--src/syntax.c6
-rw-r--r--src/term.c10
-rw-r--r--src/textprop.c3
-rw-r--r--src/window.c6
-rw-r--r--src/xdisp.c41
-rw-r--r--src/xfaces.c8
-rw-r--r--src/xmenu.c25
36 files changed, 688 insertions, 403 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 351e46259f1..72bdb87fc70 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,101 @@
12014-09-07 Paul Eggert <eggert@cs.ucla.edu>
2
3 Use SAFE_ALLOCA etc. to avoid unbounded stack allocation (Bug#18410).
4 This follows up on the recent thread in emacs-devel on alloca; see:
5 http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00042.html
6 This patch also cleans up alloca-related glitches noted while
7 examining the code looking for unbounded alloca.
8 * alloc.c (listn):
9 * callproc.c (init_callproc):
10 Rewrite to avoid need for alloca.
11 * buffer.c (mouse_face_overlay_overlaps)
12 (report_overlay_modification):
13 * buffer.h (GET_OVERLAYS_AT):
14 * coding.c (make_subsidiaries):
15 * doc.c (Fsnarf_documentation):
16 * editfns.c (Fuser_full_name):
17 * fileio.c (Ffile_name_directory, Fexpand_file_name)
18 (search_embedded_absfilename, Fsubstitute_in_file_name):
19 * fns.c (Fmake_hash_table):
20 * font.c (font_vconcat_entity_vectors, font_update_drivers):
21 * fontset.c (fontset_pattern_regexp, Ffontset_info):
22 * frame.c (Fmake_terminal_frame, x_set_frame_parameters)
23 (xrdb_get_resource, x_get_resource_string):
24 * ftfont.c (ftfont_get_charset, ftfont_check_otf, ftfont_drive_otf):
25 * ftxfont.c (ftxfont_draw):
26 * image.c (xbm_load, xpm_load, jpeg_load_body):
27 * keyboard.c (echo_add_key, menu_bar_items, tool_bar_items):
28 * keymap.c (Fdescribe_buffer_bindings, describe_map):
29 * lread.c (openp):
30 * menu.c (digest_single_submenu, find_and_call_menu_selection)
31 (find_and_return_menu_selection):
32 * print.c (PRINTFINISH):
33 * process.c (Fformat_network_address):
34 * scroll.c (do_scrolling, do_direct_scrolling, scrolling_1):
35 * search.c (search_buffer, Fmatch_data, Fregexp_quote):
36 * sound.c (wav_play, au_play):
37 * syntax.c (skip_chars):
38 * term.c (tty_menu_activate, tty_menu_show):
39 * textprop.c (get_char_property_and_overlay):
40 * window.c (Fset_window_configuration):
41 * xdisp.c (safe__call, next_overlay_change, vmessage)
42 (compute_overhangs_and_x, draw_glyphs, note_mouse_highlight):
43 * xfaces.c (face_at_buffer_position):
44 * xmenu.c (x_menu_show):
45 Use SAFE_ALLOCA etc. instead of plain alloca, since the
46 allocation size isn't bounded.
47 * callint.c (Fcall_interactively): Redo memory_full check
48 so that it can be done at compile-time on some platforms.
49 * coding.c (MAX_LOOKUP_MAX): New constant.
50 (get_translation_table): Use it.
51 * callproc.c (call_process): Use SAFE_NALLOCA instead of
52 SAFE_ALLOCA, to catch integer overflows on size calculation.
53 (exec_failed) [!DOS_NT]: New function.
54 (child_setup) [!DOS_NT]: Use it.
55 * editfns.c (Ftranspose_regions):
56 Hoist USE_SAFE_ALLOC + SAFE_FREE out of 'if'.
57 * editfns.c (check_translation):
58 Allocate larger buffers on the heap.
59 * eval.c (internal_lisp_condition_case):
60 Check for MAX_ALLOCA overflow.
61 * fns.c (sort_vector): Use SAFE_ALLOCA_LISP rather than Fmake_vector.
62 (Fbase64_encode_region, Fbase64_decode_region):
63 Avoid unnecessary calls to SAFE_FREE before 'error'.
64 * buffer.c (mouse_face_overlay_overlaps):
65 * editfns.c (Fget_pos_property, check_translation):
66 * eval.c (Ffuncall):
67 * font.c (font_unparse_xlfd, font_find_for_lface):
68 * ftfont.c (ftfont_drive_otf):
69 * keyboard.c (echo_add_key, read_decoded_event_from_main_queue)
70 (menu_bar_items, tool_bar_items):
71 * sound.c (Fplay_sound_internal):
72 * xdisp.c (load_overlay_strings, dump_glyph_row):
73 Use an ordinary auto buffer rather than alloca, since the
74 allocation size is fixed and small.
75 * ftfont.c: Include <c-strcase.h>.
76 (matching_prefix): New function.
77 (get_adstyle_property): Use it, to avoid need for alloca.
78 * keyboard.c (echo_add_key):
79 * keymap.c (describe_map): Use ptrdiff_t, not int.
80 * keyboard.c (echo_add_key): Prefer sizeof to strlen.
81 * keymap.c (Fdescribe_buffer_bindings): Use SBYTES, not SCHARS,
82 when counting bytes.
83 * lisp.h (xlispstrdupa): Remove, replacing with ...
84 (SAFE_ALLOCA_STRING): ... new macro with different API.
85 This fixes a portability problem, namely, alloca result
86 passed to another function. All uses changed.
87 (SAFE_ALLOCA, SAFE_ALLOCA_LISP): Check for MAX_ALLOCA,
88 not MAX_ALLOCA - 1.
89 * regex.c (REGEX_USE_SAFE_ALLOCA, REGEX_SAFE_FREE)
90 (REGEX_ALLOCATE): New macros.
91 (REGEX_REALLOCATE, REGEX_ALLOCATE_STACK, REGEX_REALLOCATE_STACK)
92 (REGEX_FREE_STACK, FREE_VARIABLES, re_match_2_internal):
93 Use them.
94 * xdisp.c (message3): Use SAFE_ALLOCA_STRING rather than doing it
95 by hand.
96 (decode_mode_spec_coding): Store directly into buf rather than
97 into an alloca temporary and copying the temporary to the buf.
98
12014-09-06 Eli Zaretskii <eliz@gnu.org> 992014-09-06 Eli Zaretskii <eliz@gnu.org>
2 100
3 * Makefile.in (EMACS_HEAPSIZE): Remove, no longer used. (Bug#18416) 101 * Makefile.in (EMACS_HEAPSIZE): Remove, no longer used. (Bug#18416)
diff --git a/src/alloc.c b/src/alloc.c
index bb47a24d905..31b0644c285 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -2618,29 +2618,28 @@ list5 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, L
2618Lisp_Object 2618Lisp_Object
2619listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...) 2619listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...)
2620{ 2620{
2621 va_list ap; 2621 Lisp_Object (*cons) (Lisp_Object, Lisp_Object);
2622 ptrdiff_t i; 2622 switch (type)
2623 Lisp_Object val, *objp; 2623 {
2624 case CONSTYPE_PURE: cons = pure_cons; break;
2625 case CONSTYPE_HEAP: cons = Fcons; break;
2626 default: emacs_abort ();
2627 }
2624 2628
2625 /* Change to SAFE_ALLOCA if you hit this eassert. */ 2629 eassume (0 < count);
2626 eassert (count <= MAX_ALLOCA / word_size); 2630 Lisp_Object val = cons (arg, Qnil);
2631 Lisp_Object tail = val;
2627 2632
2628 objp = alloca (count * word_size); 2633 va_list ap;
2629 objp[0] = arg;
2630 va_start (ap, arg); 2634 va_start (ap, arg);
2631 for (i = 1; i < count; i++) 2635 for (ptrdiff_t i = 1; i < count; i++)
2632 objp[i] = va_arg (ap, Lisp_Object);
2633 va_end (ap);
2634
2635 for (val = Qnil, i = count - 1; i >= 0; i--)
2636 { 2636 {
2637 if (type == CONSTYPE_PURE) 2637 Lisp_Object elem = cons (va_arg (ap, Lisp_Object), Qnil);
2638 val = pure_cons (objp[i], val); 2638 XSETCDR (tail, elem);
2639 else if (type == CONSTYPE_HEAP) 2639 tail = elem;
2640 val = Fcons (objp[i], val);
2641 else
2642 emacs_abort ();
2643 } 2640 }
2641 va_end (ap);
2642
2644 return val; 2643 return val;
2645} 2644}
2646 2645
@@ -3620,7 +3619,7 @@ make_save_int_obj (ptrdiff_t a, Lisp_Object b)
3620 p->data[1].object = b; 3619 p->data[1].object = b;
3621 return val; 3620 return val;
3622} 3621}
3623 3622
3624#if ! (defined USE_X_TOOLKIT || defined USE_GTK) 3623#if ! (defined USE_X_TOOLKIT || defined USE_GTK)
3625Lisp_Object 3624Lisp_Object
3626make_save_ptr_ptr (void *a, void *b) 3625make_save_ptr_ptr (void *a, void *b)
diff --git a/src/buffer.c b/src/buffer.c
index 45e614fb449..7a6ddfa719d 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -3053,13 +3053,15 @@ mouse_face_overlay_overlaps (Lisp_Object overlay)
3053 ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay)); 3053 ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay));
3054 ptrdiff_t n, i, size; 3054 ptrdiff_t n, i, size;
3055 Lisp_Object *v, tem; 3055 Lisp_Object *v, tem;
3056 Lisp_Object vbuf[10];
3057 USE_SAFE_ALLOCA;
3056 3058
3057 size = 10; 3059 size = ARRAYELTS (vbuf);
3058 v = alloca (size * sizeof *v); 3060 v = vbuf;
3059 n = overlays_in (start, end, 0, &v, &size, NULL, NULL); 3061 n = overlays_in (start, end, 0, &v, &size, NULL, NULL);
3060 if (n > size) 3062 if (n > size)
3061 { 3063 {
3062 v = alloca (n * sizeof *v); 3064 SAFE_NALLOCA (v, 1, n);
3063 overlays_in (start, end, 0, &v, &n, NULL, NULL); 3065 overlays_in (start, end, 0, &v, &n, NULL, NULL);
3064 } 3066 }
3065 3067
@@ -3069,6 +3071,7 @@ mouse_face_overlay_overlaps (Lisp_Object overlay)
3069 !NILP (tem))) 3071 !NILP (tem)))
3070 break; 3072 break;
3071 3073
3074 SAFE_FREE ();
3072 return i < n; 3075 return i < n;
3073} 3076}
3074 3077
@@ -4517,13 +4520,13 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4517 First copy the vector contents, in case some of these hooks 4520 First copy the vector contents, in case some of these hooks
4518 do subsequent modification of the buffer. */ 4521 do subsequent modification of the buffer. */
4519 ptrdiff_t size = last_overlay_modification_hooks_used; 4522 ptrdiff_t size = last_overlay_modification_hooks_used;
4520 Lisp_Object *copy = alloca (size * sizeof *copy); 4523 Lisp_Object *copy;
4521 ptrdiff_t i; 4524 ptrdiff_t i;
4522 4525
4526 USE_SAFE_ALLOCA;
4527 SAFE_ALLOCA_LISP (copy, size);
4523 memcpy (copy, XVECTOR (last_overlay_modification_hooks)->contents, 4528 memcpy (copy, XVECTOR (last_overlay_modification_hooks)->contents,
4524 size * word_size); 4529 size * word_size);
4525 gcpro1.var = copy;
4526 gcpro1.nvars = size;
4527 4530
4528 for (i = 0; i < size;) 4531 for (i = 0; i < size;)
4529 { 4532 {
@@ -4532,6 +4535,8 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4532 overlay_i = copy[i++]; 4535 overlay_i = copy[i++];
4533 call_overlay_mod_hooks (prop_i, overlay_i, after, arg1, arg2, arg3); 4536 call_overlay_mod_hooks (prop_i, overlay_i, after, arg1, arg2, arg3);
4534 } 4537 }
4538
4539 SAFE_FREE ();
4535 } 4540 }
4536 UNGCPRO; 4541 UNGCPRO;
4537} 4542}
diff --git a/src/buffer.h b/src/buffer.h
index 7511a5aab1e..61ef15d9c3d 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1127,15 +1127,15 @@ record_unwind_current_buffer (void)
1127#define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \ 1127#define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \
1128 do { \ 1128 do { \
1129 ptrdiff_t maxlen = 40; \ 1129 ptrdiff_t maxlen = 40; \
1130 overlays = alloca (maxlen * sizeof *overlays); \ 1130 SAFE_NALLOCA (overlays, 1, maxlen); \
1131 noverlays = overlays_at (posn, false, &overlays, &maxlen, \ 1131 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \
1132 nextp, NULL, chrq); \ 1132 nextp, NULL, chrq); \
1133 if (noverlays > maxlen) \ 1133 if ((noverlays) > maxlen) \
1134 { \ 1134 { \
1135 maxlen = noverlays; \ 1135 maxlen = noverlays; \
1136 overlays = alloca (maxlen * sizeof *overlays); \ 1136 SAFE_NALLOCA (overlays, 1, maxlen); \
1137 noverlays = overlays_at (posn, false, &overlays, &maxlen, \ 1137 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \
1138 nextp, NULL, chrq); \ 1138 nextp, NULL, chrq); \
1139 } \ 1139 } \
1140 } while (false) 1140 } while (false)
1141 1141
diff --git a/src/callint.c b/src/callint.c
index 817f84d897b..9a4573c77be 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -297,6 +297,7 @@ invoke it. If KEYS is omitted or nil, the return value of
297 Lisp_Object teml; 297 Lisp_Object teml;
298 Lisp_Object up_event; 298 Lisp_Object up_event;
299 Lisp_Object enable; 299 Lisp_Object enable;
300 USE_SAFE_ALLOCA;
300 ptrdiff_t speccount = SPECPDL_INDEX (); 301 ptrdiff_t speccount = SPECPDL_INDEX ();
301 302
302 /* The index of the next element of this_command_keys to examine for 303 /* The index of the next element of this_command_keys to examine for
@@ -366,12 +367,8 @@ invoke it. If KEYS is omitted or nil, the return value of
366 wrong_type_argument (Qcommandp, function); 367 wrong_type_argument (Qcommandp, function);
367 } 368 }
368 369
369 /* If SPECS is set to a string, use it as an interactive prompt. */ 370 /* If SPECS is not a string, invent one. */
370 if (STRINGP (specs)) 371 if (! STRINGP (specs))
371 /* Make a copy of string so that if a GC relocates specs,
372 `string' will still be valid. */
373 string = xlispstrdupa (specs);
374 else
375 { 372 {
376 Lisp_Object input; 373 Lisp_Object input;
377 Lisp_Object funval = Findirect_function (function, Qt); 374 Lisp_Object funval = Findirect_function (function, Qt);
@@ -416,10 +413,16 @@ invoke it. If KEYS is omitted or nil, the return value of
416 args[0] = Qfuncall_interactively; 413 args[0] = Qfuncall_interactively;
417 args[1] = function; 414 args[1] = function;
418 args[2] = specs; 415 args[2] = specs;
419 return unbind_to (speccount, Fapply (3, args)); 416 Lisp_Object result = unbind_to (speccount, Fapply (3, args));
417 SAFE_FREE ();
418 return result;
420 } 419 }
421 } 420 }
422 421
422 /* SPECS is set to a string; use it as an interactive prompt.
423 Copy it so that STRING will be valid even if a GC relocates SPECS. */
424 SAFE_ALLOCA_STRING (string, specs);
425
423 /* Here if function specifies a string to control parsing the defaults. */ 426 /* Here if function specifies a string to control parsing the defaults. */
424 427
425 /* Set next_event to point to the first event with parameters. */ 428 /* Set next_event to point to the first event with parameters. */
@@ -507,14 +510,15 @@ invoke it. If KEYS is omitted or nil, the return value of
507 break; 510 break;
508 } 511 }
509 512
510 if (min (MOST_POSITIVE_FIXNUM, 513 if (MOST_POSITIVE_FIXNUM < min (PTRDIFF_MAX, SIZE_MAX) / word_size
511 min (PTRDIFF_MAX, SIZE_MAX) / word_size) 514 && MOST_POSITIVE_FIXNUM < nargs)
512 < nargs)
513 memory_full (SIZE_MAX); 515 memory_full (SIZE_MAX);
514 516
515 args = alloca (nargs * sizeof *args); 517 /* Allocate them all at one go. This wastes a bit of memory, but
516 visargs = alloca (nargs * sizeof *visargs); 518 it's OK to trade space for speed. */
517 varies = alloca (nargs * sizeof *varies); 519 SAFE_NALLOCA (args, 3, nargs);
520 visargs = args + nargs;
521 varies = (signed char *) (visargs + nargs);
518 522
519 for (i = 0; i < nargs; i++) 523 for (i = 0; i < nargs; i++)
520 { 524 {
@@ -871,7 +875,9 @@ invoke it. If KEYS is omitted or nil, the return value of
871 { 875 {
872 Lisp_Object val = Ffuncall (nargs, args); 876 Lisp_Object val = Ffuncall (nargs, args);
873 UNGCPRO; 877 UNGCPRO;
874 return unbind_to (speccount, val); 878 val = unbind_to (speccount, val);
879 SAFE_FREE ();
880 return val;
875 } 881 }
876} 882}
877 883
diff --git a/src/callproc.c b/src/callproc.c
index e8b61b9f01f..0636571b26c 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -466,7 +466,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
466 && SREF (path, 1) == ':') 466 && SREF (path, 1) == ':')
467 path = Fsubstring (path, make_number (2), Qnil); 467 path = Fsubstring (path, make_number (2), Qnil);
468 468
469 new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); 469 SAFE_NALLOCA (new_argv, 1, nargs < 4 ? 2 : nargs - 2);
470 470
471 { 471 {
472 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 472 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -1151,6 +1151,25 @@ add_env (char **env, char **new_env, char *string)
1151 return new_env; 1151 return new_env;
1152} 1152}
1153 1153
1154#ifndef DOS_NT
1155
1156/* 'exec' failed inside a child running NAME, with error number ERR.
1157 Report the error and exit the child. */
1158
1159static _Noreturn void
1160exec_failed (char const *name, int err)
1161{
1162 /* Avoid deadlock if the child's perror writes to a full pipe; the
1163 pipe's reader is the parent, but with vfork the parent can't
1164 run until the child exits. Truncate the diagnostic instead. */
1165 fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
1166
1167 errno = err;
1168 emacs_perror (name);
1169 _exit (err == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
1170}
1171#endif
1172
1154/* This is the last thing run in a newly forked inferior 1173/* This is the last thing run in a newly forked inferior
1155 either synchronous or asynchronous. 1174 either synchronous or asynchronous.
1156 Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2. 1175 Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
@@ -1174,8 +1193,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1174 int cpid; 1193 int cpid;
1175 HANDLE handles[3]; 1194 HANDLE handles[3];
1176#else 1195#else
1177 int exec_errno;
1178
1179 pid_t pid = getpid (); 1196 pid_t pid = getpid ();
1180#endif /* WINDOWSNT */ 1197#endif /* WINDOWSNT */
1181 1198
@@ -1196,6 +1213,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1196 on that. */ 1213 on that. */
1197 pwd_var = xmalloc (i + 5); 1214 pwd_var = xmalloc (i + 5);
1198#else 1215#else
1216 if (MAX_ALLOCA - 5 < i)
1217 exec_failed (new_argv[0], ENOMEM);
1199 pwd_var = alloca (i + 5); 1218 pwd_var = alloca (i + 5);
1200#endif 1219#endif
1201 temp = pwd_var + 4; 1220 temp = pwd_var + 4;
@@ -1262,6 +1281,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1262 } 1281 }
1263 1282
1264 /* new_length + 2 to include PWD and terminating 0. */ 1283 /* new_length + 2 to include PWD and terminating 0. */
1284 if (MAX_ALLOCA / sizeof *env - 2 < new_length)
1285 exec_failed (new_argv[0], ENOMEM);
1265 env = new_env = alloca ((new_length + 2) * sizeof *env); 1286 env = new_env = alloca ((new_length + 2) * sizeof *env);
1266 /* If we have a PWD envvar, pass one down, 1287 /* If we have a PWD envvar, pass one down,
1267 but with corrected value. */ 1288 but with corrected value. */
@@ -1270,6 +1291,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1270 1291
1271 if (STRINGP (display)) 1292 if (STRINGP (display))
1272 { 1293 {
1294 if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display))
1295 exec_failed (new_argv[0], ENOMEM);
1273 char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display)); 1296 char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
1274 strcpy (vdata, "DISPLAY="); 1297 strcpy (vdata, "DISPLAY=");
1275 strcat (vdata, SSDATA (display)); 1298 strcat (vdata, SSDATA (display));
@@ -1345,16 +1368,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1345 tcsetpgrp (0, pid); 1368 tcsetpgrp (0, pid);
1346 1369
1347 execve (new_argv[0], new_argv, env); 1370 execve (new_argv[0], new_argv, env);
1348 exec_errno = errno; 1371 exec_failed (new_argv[0], errno);
1349
1350 /* Avoid deadlock if the child's perror writes to a full pipe; the
1351 pipe's reader is the parent, but with vfork the parent can't
1352 run until the child exits. Truncate the diagnostic instead. */
1353 fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
1354
1355 errno = exec_errno;
1356 emacs_perror (new_argv[0]);
1357 _exit (exec_errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
1358 1372
1359#else /* MSDOS */ 1373#else /* MSDOS */
1360 pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); 1374 pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);
@@ -1543,20 +1557,13 @@ init_callproc_1 (void)
1543void 1557void
1544init_callproc (void) 1558init_callproc (void)
1545{ 1559{
1546 char *data_dir = egetenv ("EMACSDATA"); 1560 bool data_dir = egetenv ("EMACSDATA") != 0;
1547 1561
1548 register char * sh; 1562 char *sh;
1549 Lisp_Object tempdir; 1563 Lisp_Object tempdir;
1550#ifdef HAVE_NS 1564#ifdef HAVE_NS
1551 if (data_dir == 0) 1565 if (data_dir == 0)
1552 { 1566 data_dir == ns_etc_directory () != 0;
1553 const char *etc_dir = ns_etc_directory ();
1554 if (etc_dir)
1555 {
1556 data_dir = alloca (strlen (etc_dir) + 1);
1557 strcpy (data_dir, etc_dir);
1558 }
1559 }
1560#endif 1567#endif
1561 1568
1562 if (!NILP (Vinstallation_directory)) 1569 if (!NILP (Vinstallation_directory))
diff --git a/src/coding.c b/src/coding.c
index 8b620af8695..84b774b4355 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -6867,6 +6867,11 @@ decode_eol (struct coding_system *coding)
6867} 6867}
6868 6868
6869 6869
6870/* MAX_LOOKUP's maximum value. MAX_LOOKUP is an int and so cannot
6871 exceed INT_MAX. Also, MAX_LOOKUP is multiplied by sizeof (int) for
6872 alloca, so it cannot exceed MAX_ALLOCA / sizeof (int). */
6873enum { MAX_LOOKUP_MAX = min (INT_MAX, MAX_ALLOCA / sizeof (int)) };
6874
6870/* Return a translation table (or list of them) from coding system 6875/* Return a translation table (or list of them) from coding system
6871 attribute vector ATTRS for encoding (if ENCODEP) or decoding (if 6876 attribute vector ATTRS for encoding (if ENCODEP) or decoding (if
6872 not ENCODEP). */ 6877 not ENCODEP). */
@@ -6919,7 +6924,7 @@ get_translation_table (Lisp_Object attrs, bool encodep, int *max_lookup)
6919 { 6924 {
6920 val = XCHAR_TABLE (translation_table)->extras[1]; 6925 val = XCHAR_TABLE (translation_table)->extras[1];
6921 if (NATNUMP (val) && *max_lookup < XFASTINT (val)) 6926 if (NATNUMP (val) && *max_lookup < XFASTINT (val))
6922 *max_lookup = XFASTINT (val); 6927 *max_lookup = min (XFASTINT (val), MAX_LOOKUP_MAX);
6923 } 6928 }
6924 else if (CONSP (translation_table)) 6929 else if (CONSP (translation_table))
6925 { 6930 {
@@ -6931,7 +6936,7 @@ get_translation_table (Lisp_Object attrs, bool encodep, int *max_lookup)
6931 { 6936 {
6932 Lisp_Object tailval = XCHAR_TABLE (XCAR (tail))->extras[1]; 6937 Lisp_Object tailval = XCHAR_TABLE (XCAR (tail))->extras[1];
6933 if (NATNUMP (tailval) && *max_lookup < XFASTINT (tailval)) 6938 if (NATNUMP (tailval) && *max_lookup < XFASTINT (tailval))
6934 *max_lookup = XFASTINT (tailval); 6939 *max_lookup = min (XFASTINT (tailval), MAX_LOOKUP_MAX);
6935 } 6940 }
6936 } 6941 }
6937 } 6942 }
@@ -10011,7 +10016,8 @@ make_subsidiaries (Lisp_Object base)
10011{ 10016{
10012 Lisp_Object subsidiaries; 10017 Lisp_Object subsidiaries;
10013 ptrdiff_t base_name_len = SBYTES (SYMBOL_NAME (base)); 10018 ptrdiff_t base_name_len = SBYTES (SYMBOL_NAME (base));
10014 char *buf = alloca (base_name_len + 6); 10019 USE_SAFE_ALLOCA;
10020 char *buf = SAFE_ALLOCA (base_name_len + 6);
10015 int i; 10021 int i;
10016 10022
10017 memcpy (buf, SDATA (SYMBOL_NAME (base)), base_name_len); 10023 memcpy (buf, SDATA (SYMBOL_NAME (base)), base_name_len);
@@ -10021,6 +10027,7 @@ make_subsidiaries (Lisp_Object base)
10021 strcpy (buf + base_name_len, suffixes[i]); 10027 strcpy (buf + base_name_len, suffixes[i]);
10022 ASET (subsidiaries, i, intern (buf)); 10028 ASET (subsidiaries, i, intern (buf));
10023 } 10029 }
10030 SAFE_FREE ();
10024 return subsidiaries; 10031 return subsidiaries;
10025} 10032}
10026 10033
diff --git a/src/doc.c b/src/doc.c
index df8cfba3f2a..be882d4a5c7 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -561,6 +561,8 @@ the same file name is found in the `doc-directory'. */)
561 char *p, *name; 561 char *p, *name;
562 bool skip_file = 0; 562 bool skip_file = 0;
563 ptrdiff_t count; 563 ptrdiff_t count;
564 char const *dirname;
565 ptrdiff_t dirlen;
564 /* Preloaded defcustoms using custom-initialize-delay are added to 566 /* Preloaded defcustoms using custom-initialize-delay are added to
565 this list, but kept unbound. See http://debbugs.gnu.org/11565 */ 567 this list, but kept unbound. See http://debbugs.gnu.org/11565 */
566 Lisp_Object delayed_init = 568 Lisp_Object delayed_init =
@@ -577,15 +579,21 @@ the same file name is found in the `doc-directory'. */)
577 (0) 579 (0)
578#endif /* CANNOT_DUMP */ 580#endif /* CANNOT_DUMP */
579 { 581 {
580 name = alloca (SCHARS (filename) + 14); 582 static char const sibling_etc[] = "../etc/";
581 strcpy (name, "../etc/"); 583 dirname = sibling_etc;
584 dirlen = sizeof sibling_etc - 1;
582 } 585 }
583 else 586 else
584 { 587 {
585 CHECK_STRING (Vdoc_directory); 588 CHECK_STRING (Vdoc_directory);
586 name = alloca (SCHARS (filename) + SCHARS (Vdoc_directory) + 1); 589 dirname = SSDATA (Vdoc_directory);
587 strcpy (name, SSDATA (Vdoc_directory)); 590 dirlen = SBYTES (Vdoc_directory);
588 } 591 }
592
593 count = SPECPDL_INDEX ();
594 USE_SAFE_ALLOCA;
595 name = SAFE_ALLOCA (dirlen + SBYTES (filename) + 1);
596 strcpy (name, dirname);
589 strcat (name, SSDATA (filename)); /*** Add this line ***/ 597 strcat (name, SSDATA (filename)); /*** Add this line ***/
590 598
591 /* Vbuild_files is nil when temacs is run, and non-nil after that. */ 599 /* Vbuild_files is nil when temacs is run, and non-nil after that. */
@@ -608,7 +616,6 @@ the same file name is found in the `doc-directory'. */)
608 report_file_errno ("Opening doc string file", build_string (name), 616 report_file_errno ("Opening doc string file", build_string (name),
609 open_errno); 617 open_errno);
610 } 618 }
611 count = SPECPDL_INDEX ();
612 record_unwind_protect_int (close_file_unwind, fd); 619 record_unwind_protect_int (close_file_unwind, fd);
613 Vdoc_file_name = filename; 620 Vdoc_file_name = filename;
614 filled = 0; 621 filled = 0;
@@ -637,7 +644,7 @@ the same file name is found in the `doc-directory'. */)
637 && (end[-1] == 'o' || end[-1] == 'c')) 644 && (end[-1] == 'o' || end[-1] == 'c'))
638 { 645 {
639 ptrdiff_t len = end - p - 2; 646 ptrdiff_t len = end - p - 2;
640 char *fromfile = alloca (len + 1); 647 char *fromfile = SAFE_ALLOCA (len + 1);
641 memcpy (fromfile, &p[2], len); 648 memcpy (fromfile, &p[2], len);
642 fromfile[len] = 0; 649 fromfile[len] = 0;
643 if (fromfile[len-1] == 'c') 650 if (fromfile[len-1] == 'c')
@@ -688,6 +695,8 @@ the same file name is found in the `doc-directory'. */)
688 filled -= end - buf; 695 filled -= end - buf;
689 memmove (buf, end, filled); 696 memmove (buf, end, filled);
690 } 697 }
698
699 SAFE_FREE ();
691 return unbind_to (count, Qnil); 700 return unbind_to (count, Qnil);
692} 701}
693 702
diff --git a/src/editfns.c b/src/editfns.c
index a906aead09a..7e9a3bf7d3c 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -376,13 +376,14 @@ at POSITION. */)
376 set_buffer_temp (XBUFFER (object)); 376 set_buffer_temp (XBUFFER (object));
377 377
378 /* First try with room for 40 overlays. */ 378 /* First try with room for 40 overlays. */
379 noverlays = 40; 379 Lisp_Object overlay_vecbuf[40];
380 overlay_vec = alloca (noverlays * sizeof *overlay_vec); 380 noverlays = ARRAYELTS (overlay_vecbuf);
381 overlay_vec = overlay_vecbuf;
381 noverlays = overlays_around (posn, overlay_vec, noverlays); 382 noverlays = overlays_around (posn, overlay_vec, noverlays);
382 383
383 /* If there are more than 40, 384 /* If there are more than 40,
384 make enough space for all, and try again. */ 385 make enough space for all, and try again. */
385 if (noverlays > 40) 386 if (ARRAYELTS (overlay_vecbuf) < noverlays)
386 { 387 {
387 SAFE_ALLOCA_LISP (overlay_vec, noverlays); 388 SAFE_ALLOCA_LISP (overlay_vec, noverlays);
388 noverlays = overlays_around (posn, overlay_vec, noverlays); 389 noverlays = overlays_around (posn, overlay_vec, noverlays);
@@ -1325,17 +1326,16 @@ name, or nil if there is no such user. */)
1325 /* Substitute the login name for the &, upcasing the first character. */ 1326 /* Substitute the login name for the &, upcasing the first character. */
1326 if (q) 1327 if (q)
1327 { 1328 {
1328 register char *r; 1329 Lisp_Object login = Fuser_login_name (make_number (pw->pw_uid));
1329 Lisp_Object login; 1330 USE_SAFE_ALLOCA;
1330 1331 char *r = SAFE_ALLOCA (strlen (p) + SBYTES (login) + 1);
1331 login = Fuser_login_name (make_number (pw->pw_uid));
1332 r = alloca (strlen (p) + SCHARS (login) + 1);
1333 memcpy (r, p, q - p); 1332 memcpy (r, p, q - p);
1334 r[q - p] = 0; 1333 r[q - p] = 0;
1335 strcat (r, SSDATA (login)); 1334 strcat (r, SSDATA (login));
1336 r[q - p] = upcase ((unsigned char) r[q - p]); 1335 r[q - p] = upcase ((unsigned char) r[q - p]);
1337 strcat (r, q + 1); 1336 strcat (r, q + 1);
1338 full = build_string (r); 1337 full = build_string (r);
1338 SAFE_FREE ();
1339 } 1339 }
1340#endif /* AMPERSAND_FULL_NAME */ 1340#endif /* AMPERSAND_FULL_NAME */
1341 1341
@@ -3012,8 +3012,12 @@ static Lisp_Object
3012check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end, 3012check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end,
3013 Lisp_Object val) 3013 Lisp_Object val)
3014{ 3014{
3015 int buf_size = 16, buf_used = 0; 3015 int initial_buf[16];
3016 int *buf = alloca (sizeof (int) * buf_size); 3016 int *buf = initial_buf;
3017 ptrdiff_t buf_size = ARRAYELTS (initial_buf);
3018 int *bufalloc = 0;
3019 ptrdiff_t buf_used = 0;
3020 Lisp_Object result = Qnil;
3017 3021
3018 for (; CONSP (val); val = XCDR (val)) 3022 for (; CONSP (val); val = XCDR (val))
3019 { 3023 {
@@ -3038,12 +3042,11 @@ check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end,
3038 3042
3039 if (buf_used == buf_size) 3043 if (buf_used == buf_size)
3040 { 3044 {
3041 int *newbuf; 3045 bufalloc = xpalloc (bufalloc, &buf_size, 1, -1,
3042 3046 sizeof *bufalloc);
3043 buf_size += 16; 3047 if (buf == initial_buf)
3044 newbuf = alloca (sizeof (int) * buf_size); 3048 memcpy (bufalloc, buf, sizeof initial_buf);
3045 memcpy (newbuf, buf, sizeof (int) * buf_used); 3049 buf = bufalloc;
3046 buf = newbuf;
3047 } 3050 }
3048 buf[buf_used++] = STRING_CHAR_AND_LENGTH (p, len1); 3051 buf[buf_used++] = STRING_CHAR_AND_LENGTH (p, len1);
3049 pos_byte += len1; 3052 pos_byte += len1;
@@ -3052,10 +3055,15 @@ check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end,
3052 break; 3055 break;
3053 } 3056 }
3054 if (i == len) 3057 if (i == len)
3055 return XCAR (val); 3058 {
3059 result = XCAR (val);
3060 break;
3061 }
3056 } 3062 }
3057 } 3063 }
3058 return Qnil; 3064
3065 xfree (bufalloc);
3066 return result;
3059} 3067}
3060 3068
3061 3069
@@ -4617,11 +4625,11 @@ Transposing beyond buffer boundaries is an error. */)
4617 if (tmp_interval3) 4625 if (tmp_interval3)
4618 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3); 4626 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
4619 4627
4628 USE_SAFE_ALLOCA;
4629
4620 /* First region smaller than second. */ 4630 /* First region smaller than second. */
4621 if (len1_byte < len2_byte) 4631 if (len1_byte < len2_byte)
4622 { 4632 {
4623 USE_SAFE_ALLOCA;
4624
4625 temp = SAFE_ALLOCA (len2_byte); 4633 temp = SAFE_ALLOCA (len2_byte);
4626 4634
4627 /* Don't precompute these addresses. We have to compute them 4635 /* Don't precompute these addresses. We have to compute them
@@ -4633,21 +4641,19 @@ Transposing beyond buffer boundaries is an error. */)
4633 memcpy (temp, start2_addr, len2_byte); 4641 memcpy (temp, start2_addr, len2_byte);
4634 memcpy (start1_addr + len2_byte, start1_addr, len1_byte); 4642 memcpy (start1_addr + len2_byte, start1_addr, len1_byte);
4635 memcpy (start1_addr, temp, len2_byte); 4643 memcpy (start1_addr, temp, len2_byte);
4636 SAFE_FREE ();
4637 } 4644 }
4638 else 4645 else
4639 /* First region not smaller than second. */ 4646 /* First region not smaller than second. */
4640 { 4647 {
4641 USE_SAFE_ALLOCA;
4642
4643 temp = SAFE_ALLOCA (len1_byte); 4648 temp = SAFE_ALLOCA (len1_byte);
4644 start1_addr = BYTE_POS_ADDR (start1_byte); 4649 start1_addr = BYTE_POS_ADDR (start1_byte);
4645 start2_addr = BYTE_POS_ADDR (start2_byte); 4650 start2_addr = BYTE_POS_ADDR (start2_byte);
4646 memcpy (temp, start1_addr, len1_byte); 4651 memcpy (temp, start1_addr, len1_byte);
4647 memcpy (start1_addr, start2_addr, len2_byte); 4652 memcpy (start1_addr, start2_addr, len2_byte);
4648 memcpy (start1_addr + len2_byte, temp, len1_byte); 4653 memcpy (start1_addr + len2_byte, temp, len1_byte);
4649 SAFE_FREE ();
4650 } 4654 }
4655
4656 SAFE_FREE ();
4651 graft_intervals_into_buffer (tmp_interval1, start1 + len2, 4657 graft_intervals_into_buffer (tmp_interval1, start1 + len2,
4652 len1, current_buffer, 0); 4658 len1, current_buffer, 0);
4653 graft_intervals_into_buffer (tmp_interval2, start1, 4659 graft_intervals_into_buffer (tmp_interval2, start1,
diff --git a/src/eval.c b/src/eval.c
index 02fc3426f83..9ff25859646 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1272,7 +1272,10 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
1272 1272
1273 { /* The first clause is the one that should be checked first, so it should 1273 { /* The first clause is the one that should be checked first, so it should
1274 be added to handlerlist last. So we build in `clauses' a table that 1274 be added to handlerlist last. So we build in `clauses' a table that
1275 contains `handlers' but in reverse order. */ 1275 contains `handlers' but in reverse order. SAFE_ALLOCA won't work
1276 here due to the setjmp, so impose a MAX_ALLOCA limit. */
1277 if (MAX_ALLOCA / word_size < clausenb)
1278 memory_full (SIZE_MAX);
1276 Lisp_Object *clauses = alloca (clausenb * sizeof *clauses); 1279 Lisp_Object *clauses = alloca (clausenb * sizeof *clauses);
1277 Lisp_Object *volatile clauses_volatile = clauses; 1280 Lisp_Object *volatile clauses_volatile = clauses;
1278 int i = clausenb; 1281 int i = clausenb;
@@ -1311,7 +1314,7 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
1311 return val; 1314 return val;
1312 } 1315 }
1313 } 1316 }
1314 } 1317 }
1315 1318
1316 val = eval_sub (bodyform); 1319 val = eval_sub (bodyform);
1317 handlerlist = oldhandlerlist; 1320 handlerlist = oldhandlerlist;
@@ -2789,10 +2792,11 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
2789 val = (XSUBR (fun)->function.aMANY) (numargs, args + 1); 2792 val = (XSUBR (fun)->function.aMANY) (numargs, args + 1);
2790 else 2793 else
2791 { 2794 {
2795 Lisp_Object internal_argbuf[8];
2792 if (XSUBR (fun)->max_args > numargs) 2796 if (XSUBR (fun)->max_args > numargs)
2793 { 2797 {
2794 internal_args = alloca (XSUBR (fun)->max_args 2798 eassert (XSUBR (fun)->max_args <= ARRAYELTS (internal_argbuf));
2795 * sizeof *internal_args); 2799 internal_args = internal_argbuf;
2796 memcpy (internal_args, args + 1, numargs * word_size); 2800 memcpy (internal_args, args + 1, numargs * word_size);
2797 for (i = numargs; i < XSUBR (fun)->max_args; i++) 2801 for (i = numargs; i < XSUBR (fun)->max_args; i++)
2798 internal_args[i] = Qnil; 2802 internal_args[i] = Qnil;
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
diff --git a/src/fns.c b/src/fns.c
index 6cc5cef95df..260bc4e3a12 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1992,17 +1992,14 @@ sort_vector (Lisp_Object vector, Lisp_Object predicate)
1992 return; 1992 return;
1993 ptrdiff_t halflen = len >> 1; 1993 ptrdiff_t halflen = len >> 1;
1994 Lisp_Object *tmp; 1994 Lisp_Object *tmp;
1995 Lisp_Object tmpvec = Qnil; 1995 struct gcpro gcpro1, gcpro2;
1996 struct gcpro gcpro1, gcpro2, gcpro3; 1996 GCPRO2 (vector, predicate);
1997 GCPRO3 (vector, predicate, tmpvec); 1997 USE_SAFE_ALLOCA;
1998 if (halflen < MAX_ALLOCA / word_size) 1998 SAFE_ALLOCA_LISP (tmp, halflen);
1999 tmp = alloca (halflen * word_size); 1999 for (ptrdiff_t i = 0; i < halflen; i++)
2000 else 2000 tmp[i] = make_number (0);
2001 {
2002 tmpvec = Fmake_vector (make_number (halflen), make_number (0));
2003 tmp = XVECTOR (tmpvec)->contents;
2004 }
2005 sort_vector_inplace (predicate, len, XVECTOR (vector)->contents, tmp); 2001 sort_vector_inplace (predicate, len, XVECTOR (vector)->contents, tmp);
2002 SAFE_FREE ();
2006 UNGCPRO; 2003 UNGCPRO;
2007} 2004}
2008 2005
@@ -3289,7 +3286,6 @@ into shorter lines. */)
3289 if (encoded_length < 0) 3286 if (encoded_length < 0)
3290 { 3287 {
3291 /* The encoding wasn't possible. */ 3288 /* The encoding wasn't possible. */
3292 SAFE_FREE ();
3293 error ("Multibyte character in data for base64 encoding"); 3289 error ("Multibyte character in data for base64 encoding");
3294 } 3290 }
3295 3291
@@ -3434,7 +3430,6 @@ If the region can't be decoded, signal an error and don't modify the buffer. */
3434 if (decoded_length < 0) 3430 if (decoded_length < 0)
3435 { 3431 {
3436 /* The decoding wasn't possible. */ 3432 /* The decoding wasn't possible. */
3437 SAFE_FREE ();
3438 error ("Invalid base64 data"); 3433 error ("Invalid base64 data");
3439 } 3434 }
3440 3435
@@ -4581,12 +4576,12 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
4581{ 4576{
4582 Lisp_Object test, size, rehash_size, rehash_threshold, weak; 4577 Lisp_Object test, size, rehash_size, rehash_threshold, weak;
4583 struct hash_table_test testdesc; 4578 struct hash_table_test testdesc;
4584 char *used;
4585 ptrdiff_t i; 4579 ptrdiff_t i;
4580 USE_SAFE_ALLOCA;
4586 4581
4587 /* The vector `used' is used to keep track of arguments that 4582 /* The vector `used' is used to keep track of arguments that
4588 have been consumed. */ 4583 have been consumed. */
4589 used = alloca (nargs * sizeof *used); 4584 char *used = SAFE_ALLOCA (nargs * sizeof *used);
4590 memset (used, 0, nargs * sizeof *used); 4585 memset (used, 0, nargs * sizeof *used);
4591 4586
4592 /* See if there's a `:test TEST' among the arguments. */ 4587 /* See if there's a `:test TEST' among the arguments. */
@@ -4653,6 +4648,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
4653 if (!used[i]) 4648 if (!used[i])
4654 signal_error ("Invalid argument list", args[i]); 4649 signal_error ("Invalid argument list", args[i]);
4655 4650
4651 SAFE_FREE ();
4656 return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak); 4652 return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak);
4657} 4653}
4658 4654
diff --git a/src/font.c b/src/font.c
index 054a68bfd94..90a5c6a2f88 100644
--- a/src/font.c
+++ b/src/font.c
@@ -1299,6 +1299,9 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
1299 1299
1300 val = AREF (font, FONT_SIZE_INDEX); 1300 val = AREF (font, FONT_SIZE_INDEX);
1301 eassert (NUMBERP (val) || NILP (val)); 1301 eassert (NUMBERP (val) || NILP (val));
1302 char font_size_index_buf[sizeof "-*"
1303 + MAX (INT_STRLEN_BOUND (EMACS_INT),
1304 1 + DBL_MAX_10_EXP + 1)];
1302 if (INTEGERP (val)) 1305 if (INTEGERP (val))
1303 { 1306 {
1304 EMACS_INT v = XINT (val); 1307 EMACS_INT v = XINT (val);
@@ -1306,8 +1309,7 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
1306 v = pixel_size; 1309 v = pixel_size;
1307 if (v > 0) 1310 if (v > 0)
1308 { 1311 {
1309 f[XLFD_PIXEL_INDEX] = p = 1312 f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
1310 alloca (sizeof "-*" + INT_STRLEN_BOUND (EMACS_INT));
1311 sprintf (p, "%"pI"d-*", v); 1313 sprintf (p, "%"pI"d-*", v);
1312 } 1314 }
1313 else 1315 else
@@ -1316,21 +1318,22 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
1316 else if (FLOATP (val)) 1318 else if (FLOATP (val))
1317 { 1319 {
1318 double v = XFLOAT_DATA (val) * 10; 1320 double v = XFLOAT_DATA (val) * 10;
1319 f[XLFD_PIXEL_INDEX] = p = alloca (sizeof "*-" + 1 + DBL_MAX_10_EXP + 1); 1321 f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
1320 sprintf (p, "*-%.0f", v); 1322 sprintf (p, "*-%.0f", v);
1321 } 1323 }
1322 else 1324 else
1323 f[XLFD_PIXEL_INDEX] = "*-*"; 1325 f[XLFD_PIXEL_INDEX] = "*-*";
1324 1326
1327 char dpi_index_buf[sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)];
1325 if (INTEGERP (AREF (font, FONT_DPI_INDEX))) 1328 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1326 { 1329 {
1327 EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX)); 1330 EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX));
1328 f[XLFD_RESX_INDEX] = p = 1331 f[XLFD_RESX_INDEX] = p = dpi_index_buf;
1329 alloca (sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT));
1330 sprintf (p, "%"pI"d-%"pI"d", v, v); 1332 sprintf (p, "%"pI"d-%"pI"d", v, v);
1331 } 1333 }
1332 else 1334 else
1333 f[XLFD_RESX_INDEX] = "*-*"; 1335 f[XLFD_RESX_INDEX] = "*-*";
1336
1334 if (INTEGERP (AREF (font, FONT_SPACING_INDEX))) 1337 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1335 { 1338 {
1336 EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX)); 1339 EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX));
@@ -1342,13 +1345,16 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
1342 } 1345 }
1343 else 1346 else
1344 f[XLFD_SPACING_INDEX] = "*"; 1347 f[XLFD_SPACING_INDEX] = "*";
1348
1349 char avgwidth_index_buf[INT_BUFSIZE_BOUND (EMACS_INT)];
1345 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX))) 1350 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1346 { 1351 {
1347 f[XLFD_AVGWIDTH_INDEX] = p = alloca (INT_BUFSIZE_BOUND (EMACS_INT)); 1352 f[XLFD_AVGWIDTH_INDEX] = p = avgwidth_index_buf;
1348 sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX))); 1353 sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX)));
1349 } 1354 }
1350 else 1355 else
1351 f[XLFD_AVGWIDTH_INDEX] = "*"; 1356 f[XLFD_AVGWIDTH_INDEX] = "*";
1357
1352 len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", 1358 len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1353 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX], 1359 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1354 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX], 1360 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
@@ -2185,13 +2191,17 @@ font_score (Lisp_Object entity, Lisp_Object *spec_prop)
2185static Lisp_Object 2191static Lisp_Object
2186font_vconcat_entity_vectors (Lisp_Object list) 2192font_vconcat_entity_vectors (Lisp_Object list)
2187{ 2193{
2188 int nargs = XINT (Flength (list)); 2194 EMACS_INT nargs = XFASTINT (Flength (list));
2189 Lisp_Object *args = alloca (word_size * nargs); 2195 Lisp_Object *args;
2190 int i; 2196 USE_SAFE_ALLOCA;
2197 SAFE_ALLOCA_LISP (args, nargs);
2198 ptrdiff_t i;
2191 2199
2192 for (i = 0; i < nargs; i++, list = XCDR (list)) 2200 for (i = 0; i < nargs; i++, list = XCDR (list))
2193 args[i] = XCAR (list); 2201 args[i] = XCAR (list);
2194 return Fvconcat (nargs, args); 2202 Lisp_Object result = Fvconcat (nargs, args);
2203 SAFE_FREE ();
2204 return result;
2195} 2205}
2196 2206
2197 2207
@@ -3219,9 +3229,10 @@ font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int
3219 val = attrs[LFACE_FAMILY_INDEX]; 3229 val = attrs[LFACE_FAMILY_INDEX];
3220 val = font_intern_prop (SSDATA (val), SBYTES (val), 1); 3230 val = font_intern_prop (SSDATA (val), SBYTES (val), 1);
3221 } 3231 }
3232 Lisp_Object familybuf[3];
3222 if (NILP (val)) 3233 if (NILP (val))
3223 { 3234 {
3224 family = alloca ((sizeof family[0]) * 2); 3235 family = familybuf;
3225 family[0] = Qnil; 3236 family[0] = Qnil;
3226 family[1] = zero_vector; /* terminator. */ 3237 family[1] = zero_vector; /* terminator. */
3227 } 3238 }
@@ -3242,7 +3253,7 @@ font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int
3242 } 3253 }
3243 else 3254 else
3244 { 3255 {
3245 family = alloca ((sizeof family[0]) * 3); 3256 family = familybuf;
3246 i = 0; 3257 i = 0;
3247 family[i++] = val; 3258 family[i++] = val;
3248 if (NILP (AREF (spec, FONT_FAMILY_INDEX))) 3259 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
@@ -3529,8 +3540,9 @@ font_update_drivers (struct frame *f, Lisp_Object new_drivers)
3529 struct font_driver_list **list_table, **next; 3540 struct font_driver_list **list_table, **next;
3530 Lisp_Object tail; 3541 Lisp_Object tail;
3531 int i; 3542 int i;
3543 USE_SAFE_ALLOCA;
3532 3544
3533 list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1)); 3545 SAFE_NALLOCA (list_table, 1, num_font_drivers + 1);
3534 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail)) 3546 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3535 { 3547 {
3536 for (list = f->font_driver_list; list; list = list->next) 3548 for (list = f->font_driver_list; list; list = list->next)
@@ -3551,6 +3563,7 @@ font_update_drivers (struct frame *f, Lisp_Object new_drivers)
3551 next = &(*next)->next; 3563 next = &(*next)->next;
3552 } 3564 }
3553 *next = NULL; 3565 *next = NULL;
3566 SAFE_FREE ();
3554 3567
3555 if (! f->font_driver_list->on) 3568 if (! f->font_driver_list->on)
3556 { /* None of the drivers is enabled: enable them all. 3569 { /* None of the drivers is enabled: enable them all.
diff --git a/src/fontset.c b/src/fontset.c
index d99a3bcb7ef..8ff53a1d3a4 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1079,10 +1079,11 @@ fontset_pattern_regexp (Lisp_Object pattern)
1079 /* If PATTERN is not full XLFD we convert "*" to ".*". Otherwise 1079 /* If PATTERN is not full XLFD we convert "*" to ".*". Otherwise
1080 we convert "*" to "[^-]*" which is much faster in regular 1080 we convert "*" to "[^-]*" which is much faster in regular
1081 expression matching. */ 1081 expression matching. */
1082 if (ndashes < 14) 1082 ptrdiff_t regexsize = (SBYTES (pattern)
1083 p1 = regex = alloca (SBYTES (pattern) + 2 * nstars + 2 * nescs + 1); 1083 + (ndashes < 14 ? 2 : 5) * nstars
1084 else 1084 + 2 * nescs + 1);
1085 p1 = regex = alloca (SBYTES (pattern) + 5 * nstars + 2 * nescs + 1); 1085 USE_SAFE_ALLOCA;
1086 p1 = regex = SAFE_ALLOCA (regexsize);
1086 1087
1087 *p1++ = '^'; 1088 *p1++ = '^';
1088 for (p0 = SDATA (pattern); *p0; p0++) 1089 for (p0 = SDATA (pattern); *p0; p0++)
@@ -1110,6 +1111,7 @@ fontset_pattern_regexp (Lisp_Object pattern)
1110 1111
1111 Vcached_fontset_data = Fcons (build_string (SSDATA (pattern)), 1112 Vcached_fontset_data = Fcons (build_string (SSDATA (pattern)),
1112 build_string ((char *) regex)); 1113 build_string ((char *) regex));
1114 SAFE_FREE ();
1113 } 1115 }
1114 1116
1115 return CACHED_FONTSET_REGEX; 1117 return CACHED_FONTSET_REGEX;
@@ -1892,7 +1894,9 @@ format is the same as above. */)
1892 1894
1893 /* Recode fontsets realized on FRAME from the base fontset FONTSET 1895 /* Recode fontsets realized on FRAME from the base fontset FONTSET
1894 in the table `realized'. */ 1896 in the table `realized'. */
1895 realized[0] = alloca (word_size * ASIZE (Vfontset_table)); 1897 USE_SAFE_ALLOCA;
1898 SAFE_ALLOCA_LISP (realized[0], 2 * ASIZE (Vfontset_table));
1899 realized[1] = realized[0] + ASIZE (Vfontset_table);
1896 for (i = j = 0; i < ASIZE (Vfontset_table); i++) 1900 for (i = j = 0; i < ASIZE (Vfontset_table); i++)
1897 { 1901 {
1898 elt = FONTSET_FROM_ID (i); 1902 elt = FONTSET_FROM_ID (i);
@@ -1903,7 +1907,6 @@ format is the same as above. */)
1903 } 1907 }
1904 realized[0][j] = Qnil; 1908 realized[0][j] = Qnil;
1905 1909
1906 realized[1] = alloca (word_size * ASIZE (Vfontset_table));
1907 for (i = j = 0; ! NILP (realized[0][i]); i++) 1910 for (i = j = 0; ! NILP (realized[0][i]); i++)
1908 { 1911 {
1909 elt = FONTSET_DEFAULT (realized[0][i]); 1912 elt = FONTSET_DEFAULT (realized[0][i]);
@@ -1995,6 +1998,7 @@ format is the same as above. */)
1995 break; 1998 break;
1996 } 1999 }
1997 2000
2001 SAFE_FREE ();
1998 return tables[0]; 2002 return tables[0];
1999} 2003}
2000 2004
diff --git a/src/frame.c b/src/frame.c
index 96617976ecd..7077d42dd1b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -994,22 +994,24 @@ affects all frames on the same terminal device. */)
994 { 994 {
995 char *name = 0, *type = 0; 995 char *name = 0, *type = 0;
996 Lisp_Object tty, tty_type; 996 Lisp_Object tty, tty_type;
997 USE_SAFE_ALLOCA;
997 998
998 tty = get_future_frame_param 999 tty = get_future_frame_param
999 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame)) 1000 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1000 ? FRAME_TTY (XFRAME (selected_frame))->name 1001 ? FRAME_TTY (XFRAME (selected_frame))->name
1001 : NULL)); 1002 : NULL));
1002 if (!NILP (tty)) 1003 if (!NILP (tty))
1003 name = xlispstrdupa (tty); 1004 SAFE_ALLOCA_STRING (name, tty);
1004 1005
1005 tty_type = get_future_frame_param 1006 tty_type = get_future_frame_param
1006 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame)) 1007 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
1007 ? FRAME_TTY (XFRAME (selected_frame))->type 1008 ? FRAME_TTY (XFRAME (selected_frame))->type
1008 : NULL)); 1009 : NULL));
1009 if (!NILP (tty_type)) 1010 if (!NILP (tty_type))
1010 type = xlispstrdupa (tty_type); 1011 SAFE_ALLOCA_STRING (type, tty_type);
1011 1012
1012 t = init_tty (name, type, 0); /* Errors are not fatal. */ 1013 t = init_tty (name, type, 0); /* Errors are not fatal. */
1014 SAFE_FREE ();
1013 } 1015 }
1014 1016
1015 f = make_terminal_frame (t); 1017 f = make_terminal_frame (t);
@@ -3017,14 +3019,14 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3017#ifdef HAVE_X_WINDOWS 3019#ifdef HAVE_X_WINDOWS
3018 bool icon_left_no_change = 0, icon_top_no_change = 0; 3020 bool icon_left_no_change = 0, icon_top_no_change = 0;
3019#endif 3021#endif
3020 struct gcpro gcpro1, gcpro2;
3021 3022
3022 i = 0; 3023 i = 0;
3023 for (tail = alist; CONSP (tail); tail = XCDR (tail)) 3024 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3024 i++; 3025 i++;
3025 3026
3026 parms = alloca (i * sizeof *parms); 3027 USE_SAFE_ALLOCA;
3027 values = alloca (i * sizeof *values); 3028 SAFE_ALLOCA_LISP (parms, 2 * i);
3029 values = parms + i;
3028 3030
3029 /* Extract parm names and values into those vectors. */ 3031 /* Extract parm names and values into those vectors. */
3030 3032
@@ -3041,10 +3043,6 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3041 /* TAIL and ALIST are not used again below here. */ 3043 /* TAIL and ALIST are not used again below here. */
3042 alist = tail = Qnil; 3044 alist = tail = Qnil;
3043 3045
3044 GCPRO2 (*parms, *values);
3045 gcpro1.nvars = i;
3046 gcpro2.nvars = i;
3047
3048 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP, 3046 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
3049 because their values appear in VALUES and strings are not valid. */ 3047 because their values appear in VALUES and strings are not valid. */
3050 top = left = Qunbound; 3048 top = left = Qunbound;
@@ -3273,7 +3271,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3273#endif /* HAVE_X_WINDOWS */ 3271#endif /* HAVE_X_WINDOWS */
3274 } 3272 }
3275 3273
3276 UNGCPRO; 3274 SAFE_FREE ();
3277} 3275}
3278 3276
3279 3277
@@ -4010,10 +4008,6 @@ validate_x_resource_name (void)
4010static Lisp_Object 4008static Lisp_Object
4011xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass) 4009xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
4012{ 4010{
4013 register char *value;
4014 char *name_key;
4015 char *class_key;
4016
4017 CHECK_STRING (attribute); 4011 CHECK_STRING (attribute);
4018 CHECK_STRING (class); 4012 CHECK_STRING (class);
4019 4013
@@ -4028,17 +4022,20 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
4028 4022
4029 /* Allocate space for the components, the dots which separate them, 4023 /* Allocate space for the components, the dots which separate them,
4030 and the final '\0'. Make them big enough for the worst case. */ 4024 and the final '\0'. Make them big enough for the worst case. */
4031 name_key = alloca (SBYTES (Vx_resource_name) 4025 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4032 + (STRINGP (component) 4026 + (STRINGP (component)
4033 ? SBYTES (component) : 0) 4027 ? SBYTES (component) : 0)
4034 + SBYTES (attribute) 4028 + SBYTES (attribute)
4035 + 3); 4029 + 3);
4036 4030
4037 class_key = alloca (SBYTES (Vx_resource_class) 4031 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4038 + SBYTES (class) 4032 + SBYTES (class)
4039 + (STRINGP (subclass) 4033 + (STRINGP (subclass)
4040 ? SBYTES (subclass) : 0) 4034 ? SBYTES (subclass) : 0)
4041 + 3); 4035 + 3);
4036 USE_SAFE_ALLOCA;
4037 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4038 char *class_key = name_key + name_keysize;
4042 4039
4043 /* Start with emacs.FRAMENAME for the name (the specific one) 4040 /* Start with emacs.FRAMENAME for the name (the specific one)
4044 and with `Emacs' for the class key (the general one). */ 4041 and with `Emacs' for the class key (the general one). */
@@ -4060,7 +4057,8 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
4060 strcat (name_key, "."); 4057 strcat (name_key, ".");
4061 strcat (name_key, SSDATA (attribute)); 4058 strcat (name_key, SSDATA (attribute));
4062 4059
4063 value = x_get_string_resource (rdb, name_key, class_key); 4060 char *value = x_get_string_resource (rdb, name_key, class_key);
4061 SAFE_FREE();
4064 4062
4065 if (value && *value) 4063 if (value && *value)
4066 return build_string (value); 4064 return build_string (value);
@@ -4112,8 +4110,10 @@ x_get_resource_string (const char *attribute, const char *class)
4112 4110
4113 /* Allocate space for the components, the dots which separate them, 4111 /* Allocate space for the components, the dots which separate them,
4114 and the final '\0'. */ 4112 and the final '\0'. */
4115 char *name_key = SAFE_ALLOCA (invocation_namelen + strlen (attribute) + 2); 4113 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4116 char *class_key = alloca ((sizeof (EMACS_CLASS) - 1) + strlen (class) + 2); 4114 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4115 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4116 char *class_key = name_key + name_keysize;
4117 4117
4118 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute); 4118 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4119 sprintf (class_key, "%s.%s", EMACS_CLASS, class); 4119 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
diff --git a/src/ftfont.c b/src/ftfont.c
index 1cad158065b..0ab3119365e 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -24,6 +24,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24#include <fontconfig/fontconfig.h> 24#include <fontconfig/fontconfig.h>
25#include <fontconfig/fcfreetype.h> 25#include <fontconfig/fcfreetype.h>
26 26
27#include <c-strcase.h>
28
27#include "lisp.h" 29#include "lisp.h"
28#include "dispextern.h" 30#include "dispextern.h"
29#include "frame.h" 31#include "frame.h"
@@ -140,6 +142,12 @@ static struct
140 { NULL } 142 { NULL }
141 }; 143 };
142 144
145static bool
146matching_prefix (char const *str, ptrdiff_t len, char const *pat)
147{
148 return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0;
149}
150
143/* Dirty hack for handing ADSTYLE property. 151/* Dirty hack for handing ADSTYLE property.
144 152
145 Fontconfig (actually the underlying FreeType) gives such ADSTYLE 153 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
@@ -171,18 +179,10 @@ get_adstyle_property (FcPattern *p)
171 return Qnil; 179 return Qnil;
172 str = (char *) fcstr; 180 str = (char *) fcstr;
173 for (end = str; *end && *end != ' '; end++); 181 for (end = str; *end && *end != ' '; end++);
174 if (*end) 182 if (matching_prefix (str, end - str, "Regular")
175 { 183 || matching_prefix (str, end - str, "Bold")
176 char *newstr = alloca (end - str + 1); 184 || matching_prefix (str, end - str, "Oblique")
177 memcpy (newstr, str, end - str); 185 || matching_prefix (str, end - str, "Italic"))
178 newstr[end - str] = '\0';
179 end = newstr + (end - str);
180 str = newstr;
181 }
182 if (xstrcasecmp (str, "Regular") == 0
183 || xstrcasecmp (str, "Bold") == 0
184 || xstrcasecmp (str, "Oblique") == 0
185 || xstrcasecmp (str, "Italic") == 0)
186 return Qnil; 186 return Qnil;
187 adstyle = font_intern_prop (str, end - str, 1); 187 adstyle = font_intern_prop (str, end - str, 1);
188 if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0) 188 if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
@@ -573,7 +573,8 @@ static int
573ftfont_get_charset (Lisp_Object registry) 573ftfont_get_charset (Lisp_Object registry)
574{ 574{
575 char *str = SSDATA (SYMBOL_NAME (registry)); 575 char *str = SSDATA (SYMBOL_NAME (registry));
576 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1); 576 USE_SAFE_ALLOCA;
577 char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
577 Lisp_Object regexp; 578 Lisp_Object regexp;
578 int i, j; 579 int i, j;
579 580
@@ -589,6 +590,7 @@ ftfont_get_charset (Lisp_Object registry)
589 } 590 }
590 re[j] = '\0'; 591 re[j] = '\0';
591 regexp = make_unibyte_string (re, j); 592 regexp = make_unibyte_string (re, j);
593 SAFE_FREE ();
592 for (i = 0; fc_charset_table[i].name; i++) 594 for (i = 0; fc_charset_table[i].name; i++)
593 if (fast_c_string_match_ignore_case 595 if (fast_c_string_match_ignore_case
594 (regexp, fc_charset_table[i].name, 596 (regexp, fc_charset_table[i].name,
@@ -1688,7 +1690,8 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1688 else if (! otf) 1690 else if (! otf)
1689 return 0; 1691 return 0;
1690 for (n = 1; spec->features[i][n]; n++); 1692 for (n = 1; spec->features[i][n]; n++);
1691 tags = alloca (sizeof (OTF_Tag) * n); 1693 USE_SAFE_ALLOCA;
1694 SAFE_NALLOCA (tags, 1, n);
1692 for (n = 0, negative = 0; spec->features[i][n]; n++) 1695 for (n = 0, negative = 0; spec->features[i][n]; n++)
1693 { 1696 {
1694 if (spec->features[i][n] == 0xFFFFFFFF) 1697 if (spec->features[i][n] == 0xFFFFFFFF)
@@ -1698,16 +1701,17 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1698 else 1701 else
1699 tags[n] = spec->features[i][n]; 1702 tags[n] = spec->features[i][n];
1700 } 1703 }
1701#ifdef M17N_FLT_USE_NEW_FEATURE 1704 bool passed = true;
1702 if (OTF_check_features (otf, i == 0, spec->script, spec->langsys, 1705#ifndef M17N_FLT_USE_NEW_FEATURE
1703 tags, n - negative) != 1) 1706 passed = n - negative > 0;
1704 return 0; 1707#endif
1705#else /* not M17N_FLT_USE_NEW_FEATURE */ 1708 if (passed)
1706 if (n - negative > 0 1709 passed = (OTF_check_features (otf, i == 0, spec->script,
1707 && OTF_check_features (otf, i == 0, spec->script, spec->langsys, 1710 spec->langsys, tags, n - negative)
1708 tags, n - negative) != 1) 1711 != 1);
1712 SAFE_FREE ();
1713 if (passed)
1709 return 0; 1714 return 0;
1710#endif /* not M17N_FLT_USE_NEW_FEATURE */
1711 } 1715 }
1712 return 1; 1716 return 1;
1713#undef FEATURE_NONE 1717#undef FEATURE_NONE
@@ -1799,11 +1803,15 @@ ftfont_drive_otf (MFLTFont *font,
1799 if (len == 0) 1803 if (len == 0)
1800 return from; 1804 return from;
1801 OTF_tag_name (spec->script, script); 1805 OTF_tag_name (spec->script, script);
1806
1807 char langsysbuf[5];
1802 if (spec->langsys) 1808 if (spec->langsys)
1803 { 1809 {
1804 langsys = alloca (5); 1810 langsys = langsysbuf;
1805 OTF_tag_name (spec->langsys, langsys); 1811 OTF_tag_name (spec->langsys, langsys);
1806 } 1812 }
1813
1814 USE_SAFE_ALLOCA;
1807 for (i = 0; i < 2; i++) 1815 for (i = 0; i < 2; i++)
1808 { 1816 {
1809 char *p; 1817 char *p;
@@ -1811,10 +1819,11 @@ ftfont_drive_otf (MFLTFont *font,
1811 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF) 1819 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
1812 { 1820 {
1813 for (j = 0; spec->features[i][j]; j++); 1821 for (j = 0; spec->features[i][j]; j++);
1822 SAFE_NALLOCA (p, 6, j);
1814 if (i == 0) 1823 if (i == 0)
1815 p = gsub_features = alloca (6 * j); 1824 gsub_features = p;
1816 else 1825 else
1817 p = gpos_features = alloca (6 * j); 1826 gpos_features = p;
1818 for (j = 0; spec->features[i][j]; j++) 1827 for (j = 0; spec->features[i][j]; j++)
1819 { 1828 {
1820 if (spec->features[i][j] == 0xFFFFFFFF) 1829 if (spec->features[i][j] == 0xFFFFFFFF)
@@ -1846,7 +1855,10 @@ ftfont_drive_otf (MFLTFont *font,
1846 gsub_features) < 0) 1855 gsub_features) < 0)
1847 goto simple_copy; 1856 goto simple_copy;
1848 if (out->allocated < out->used + otf_gstring.used) 1857 if (out->allocated < out->used + otf_gstring.used)
1849 return -2; 1858 {
1859 SAFE_FREE ();
1860 return -2;
1861 }
1850 features = otf->gsub->FeatureList.Feature; 1862 features = otf->gsub->FeatureList.Feature;
1851 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) 1863 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
1852 { 1864 {
@@ -1935,7 +1947,10 @@ ftfont_drive_otf (MFLTFont *font,
1935 else if (out) 1947 else if (out)
1936 { 1948 {
1937 if (out->allocated < out->used + len) 1949 if (out->allocated < out->used + len)
1938 return -2; 1950 {
1951 SAFE_FREE ();
1952 return -2;
1953 }
1939 for (i = 0; i < len; i++) 1954 for (i = 0; i < len; i++)
1940 out->glyphs[out->used++] = in->glyphs[from + i]; 1955 out->glyphs[out->used++] = in->glyphs[from + i];
1941 } 1956 }
@@ -1947,7 +1962,10 @@ ftfont_drive_otf (MFLTFont *font,
1947 1962
1948 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, 1963 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
1949 gpos_features) < 0) 1964 gpos_features) < 0)
1950 return to; 1965 {
1966 SAFE_FREE ();
1967 return to;
1968 }
1951 features = otf->gpos->FeatureList.Feature; 1969 features = otf->gpos->FeatureList.Feature;
1952 x_ppem = ft_face->size->metrics.x_ppem; 1970 x_ppem = ft_face->size->metrics.x_ppem;
1953 y_ppem = ft_face->size->metrics.y_ppem; 1971 y_ppem = ft_face->size->metrics.y_ppem;
@@ -2069,7 +2087,10 @@ ftfont_drive_otf (MFLTFont *font,
2069 { 2087 {
2070 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, 2088 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
2071 gpos_features) < 0) 2089 gpos_features) < 0)
2072 return to; 2090 {
2091 SAFE_FREE ();
2092 return to;
2093 }
2073 features = otf->gpos->FeatureList.Feature; 2094 features = otf->gpos->FeatureList.Feature;
2074 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; 2095 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
2075 i++, otfg++) 2096 i++, otfg++)
@@ -2089,9 +2110,11 @@ ftfont_drive_otf (MFLTFont *font,
2089 } 2110 }
2090 } 2111 }
2091 } 2112 }
2113 SAFE_FREE ();
2092 return to; 2114 return to;
2093 2115
2094 simple_copy: 2116 simple_copy:
2117 SAFE_FREE ();
2095 if (! out) 2118 if (! out)
2096 return to; 2119 return to;
2097 if (out->allocated < out->used + len) 2120 if (out->allocated < out->used + len)
@@ -2129,11 +2152,15 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2129 if (len == 0) 2152 if (len == 0)
2130 return from; 2153 return from;
2131 OTF_tag_name (spec->script, script); 2154 OTF_tag_name (spec->script, script);
2155
2156 char langsysbuf[5];
2132 if (spec->langsys) 2157 if (spec->langsys)
2133 { 2158 {
2134 langsys = alloca (5); 2159 langsys = langsysbuf;
2135 OTF_tag_name (spec->langsys, langsys); 2160 OTF_tag_name (spec->langsys, langsys);
2136 } 2161 }
2162
2163 USE_SAFE_ALLOCA;
2137 for (i = 0; i < 2; i++) 2164 for (i = 0; i < 2; i++)
2138 { 2165 {
2139 char *p; 2166 char *p;
@@ -2141,10 +2168,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2141 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF) 2168 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
2142 { 2169 {
2143 for (j = 0; spec->features[i][j]; j++); 2170 for (j = 0; spec->features[i][j]; j++);
2171 SAFE_NALLOCA (p, 6, j);
2144 if (i == 0) 2172 if (i == 0)
2145 p = gsub_features = alloca (6 * j); 2173 gsub_features = p;
2146 else 2174 else
2147 p = gpos_features = alloca (6 * j); 2175 gpos_features = p;
2148 for (j = 0; spec->features[i][j]; j++) 2176 for (j = 0; spec->features[i][j]; j++)
2149 { 2177 {
2150 if (spec->features[i][j] == 0xFFFFFFFF) 2178 if (spec->features[i][j] == 0xFFFFFFFF)
@@ -2176,7 +2204,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2176 < 0) 2204 < 0)
2177 goto simple_copy; 2205 goto simple_copy;
2178 if (out->allocated < out->used + otf_gstring.used) 2206 if (out->allocated < out->used + otf_gstring.used)
2179 return -2; 2207 {
2208 SAFE_FREE ();
2209 return -2;
2210 }
2180 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) 2211 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
2181 { 2212 {
2182 MFLTGlyph *g; 2213 MFLTGlyph *g;
@@ -2227,7 +2258,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2227 else 2258 else
2228 { 2259 {
2229 if (out->allocated < out->used + len) 2260 if (out->allocated < out->used + len)
2230 return -2; 2261 {
2262 SAFE_FREE ();
2263 return -2;
2264 }
2231 for (i = 0; i < len; i++) 2265 for (i = 0; i < len; i++)
2232 out->glyphs[out->used++] = in->glyphs[from + i]; 2266 out->glyphs[out->used++] = in->glyphs[from + i];
2233 } 2267 }
@@ -2239,7 +2273,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2239 2273
2240 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features) 2274 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
2241 < 0) 2275 < 0)
2242 return to; 2276 {
2277 SAFE_FREE ();
2278 return to;
2279 }
2243 2280
2244 x_ppem = ft_face->size->metrics.x_ppem; 2281 x_ppem = ft_face->size->metrics.x_ppem;
2245 y_ppem = ft_face->size->metrics.y_ppem; 2282 y_ppem = ft_face->size->metrics.y_ppem;
@@ -2349,9 +2386,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2349 base = g; 2386 base = g;
2350 } 2387 }
2351 } 2388 }
2389 SAFE_FREE ();
2352 return to; 2390 return to;
2353 2391
2354 simple_copy: 2392 simple_copy:
2393 SAFE_FREE ();
2355 if (out->allocated < out->used + len) 2394 if (out->allocated < out->used + len)
2356 return -2; 2395 return -2;
2357 font->get_metrics (font, in, from, to); 2396 font->get_metrics (font, in, from, to);
diff --git a/src/ftxfont.c b/src/ftxfont.c
index 63e3477ebf4..7e4608b9b85 100644
--- a/src/ftxfont.c
+++ b/src/ftxfont.c
@@ -271,10 +271,11 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
271 271
272 n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0; 272 n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0;
273 273
274 USE_SAFE_ALLOCA;
275 SAFE_NALLOCA (code, 1, len);
274 block_input (); 276 block_input ();
275 if (with_background) 277 if (with_background)
276 ftxfont_draw_background (f, font, s->gc, x, y, s->width); 278 ftxfont_draw_background (f, font, s->gc, x, y, s->width);
277 code = alloca (sizeof (unsigned) * len);
278 for (i = 0; i < len; i++) 279 for (i = 0; i < len; i++)
279 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) 280 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
280 | XCHAR2B_BYTE2 (s->char2b + from + i)); 281 | XCHAR2B_BYTE2 (s->char2b + from + i));
@@ -322,6 +323,7 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
322 } 323 }
323 324
324 unblock_input (); 325 unblock_input ();
326 SAFE_FREE ();
325 327
326 return len; 328 return len;
327} 329}
diff --git a/src/image.c b/src/image.c
index 804da436ee9..57f9b7735b6 100644
--- a/src/image.c
+++ b/src/image.c
@@ -3037,13 +3037,16 @@ xbm_load (struct frame *f, struct image *img)
3037 + SBYTES (data))); 3037 + SBYTES (data)));
3038 else 3038 else
3039 { 3039 {
3040 USE_SAFE_ALLOCA;
3041
3040 if (VECTORP (data)) 3042 if (VECTORP (data))
3041 { 3043 {
3042 int i; 3044 int i;
3043 char *p; 3045 char *p;
3044 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR; 3046 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3045 3047
3046 p = bits = alloca (nbytes * img->height); 3048 SAFE_NALLOCA (bits, nbytes, img->height);
3049 p = bits;
3047 for (i = 0; i < img->height; ++i, p += nbytes) 3050 for (i = 0; i < img->height; ++i, p += nbytes)
3048 { 3051 {
3049 Lisp_Object line = AREF (data, i); 3052 Lisp_Object line = AREF (data, i);
@@ -3064,9 +3067,8 @@ xbm_load (struct frame *f, struct image *img)
3064 int nbytes, i; 3067 int nbytes, i;
3065 /* Windows mono bitmaps are reversed compared with X. */ 3068 /* Windows mono bitmaps are reversed compared with X. */
3066 invertedBits = bits; 3069 invertedBits = bits;
3067 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR 3070 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3068 * img->height; 3071 SAFE_NALLOCA (bits, nbytes, img->height);
3069 bits = alloca (nbytes);
3070 for (i = 0; i < nbytes; i++) 3072 for (i = 0; i < nbytes; i++)
3071 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]); 3073 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
3072 } 3074 }
@@ -3088,6 +3090,8 @@ xbm_load (struct frame *f, struct image *img)
3088 img->spec, Qnil); 3090 img->spec, Qnil);
3089 x_clear_image (f, img); 3091 x_clear_image (f, img);
3090 } 3092 }
3093
3094 SAFE_FREE ();
3091 } 3095 }
3092 } 3096 }
3093 3097
@@ -3494,6 +3498,8 @@ xpm_load (struct frame *f, struct image *img)
3494 int rc; 3498 int rc;
3495 XpmAttributes attrs; 3499 XpmAttributes attrs;
3496 Lisp_Object specified_file, color_symbols; 3500 Lisp_Object specified_file, color_symbols;
3501 USE_SAFE_ALLOCA;
3502
3497#ifdef HAVE_NTGUI 3503#ifdef HAVE_NTGUI
3498 HDC hdc; 3504 HDC hdc;
3499 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL; 3505 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
@@ -3536,7 +3542,7 @@ xpm_load (struct frame *f, struct image *img)
3536 { 3542 {
3537 Lisp_Object tail; 3543 Lisp_Object tail;
3538 XpmColorSymbol *xpm_syms; 3544 XpmColorSymbol *xpm_syms;
3539 int i, size; 3545 ptrdiff_t i, size;
3540 3546
3541 attrs.valuemask |= XpmColorSymbols; 3547 attrs.valuemask |= XpmColorSymbols;
3542 3548
@@ -3546,8 +3552,8 @@ xpm_load (struct frame *f, struct image *img)
3546 ++attrs.numsymbols; 3552 ++attrs.numsymbols;
3547 3553
3548 /* Allocate an XpmColorSymbol array. */ 3554 /* Allocate an XpmColorSymbol array. */
3555 SAFE_NALLOCA (xpm_syms, 1, attrs.numsymbols);
3549 size = attrs.numsymbols * sizeof *xpm_syms; 3556 size = attrs.numsymbols * sizeof *xpm_syms;
3550 xpm_syms = alloca (size);
3551 memset (xpm_syms, 0, size); 3557 memset (xpm_syms, 0, size);
3552 attrs.colorsymbols = xpm_syms; 3558 attrs.colorsymbols = xpm_syms;
3553 3559
@@ -3569,17 +3575,11 @@ xpm_load (struct frame *f, struct image *img)
3569 name = XCAR (XCAR (tail)); 3575 name = XCAR (XCAR (tail));
3570 color = XCDR (XCAR (tail)); 3576 color = XCDR (XCAR (tail));
3571 if (STRINGP (name)) 3577 if (STRINGP (name))
3572 { 3578 SAFE_ALLOCA_STRING (xpm_syms[i].name, name);
3573 xpm_syms[i].name = alloca (SCHARS (name) + 1);
3574 strcpy (xpm_syms[i].name, SSDATA (name));
3575 }
3576 else 3579 else
3577 xpm_syms[i].name = empty_string; 3580 xpm_syms[i].name = empty_string;
3578 if (STRINGP (color)) 3581 if (STRINGP (color))
3579 { 3582 SAFE_ALLOCA_STRING (xpm_syms[i].value, color);
3580 xpm_syms[i].value = alloca (SCHARS (color) + 1);
3581 strcpy (xpm_syms[i].value, SSDATA (color));
3582 }
3583 else 3583 else
3584 xpm_syms[i].value = empty_string; 3584 xpm_syms[i].value = empty_string;
3585 } 3585 }
@@ -3610,6 +3610,7 @@ xpm_load (struct frame *f, struct image *img)
3610#ifdef ALLOC_XPM_COLORS 3610#ifdef ALLOC_XPM_COLORS
3611 xpm_free_color_cache (); 3611 xpm_free_color_cache ();
3612#endif 3612#endif
3613 SAFE_FREE ();
3613 return 0; 3614 return 0;
3614 } 3615 }
3615 3616
@@ -3640,6 +3641,7 @@ xpm_load (struct frame *f, struct image *img)
3640#ifdef ALLOC_XPM_COLORS 3641#ifdef ALLOC_XPM_COLORS
3641 xpm_free_color_cache (); 3642 xpm_free_color_cache ();
3642#endif 3643#endif
3644 SAFE_FREE ();
3643 return 0; 3645 return 0;
3644 } 3646 }
3645#ifdef HAVE_NTGUI 3647#ifdef HAVE_NTGUI
@@ -3782,6 +3784,7 @@ xpm_load (struct frame *f, struct image *img)
3782#ifdef ALLOC_XPM_COLORS 3784#ifdef ALLOC_XPM_COLORS
3783 xpm_free_color_cache (); 3785 xpm_free_color_cache ();
3784#endif 3786#endif
3787 SAFE_FREE ();
3785 return rc == XpmSuccess; 3788 return rc == XpmSuccess;
3786} 3789}
3787 3790
@@ -6580,6 +6583,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6580 colors generated, and mgr->cinfo.colormap is a two-dimensional array 6583 colors generated, and mgr->cinfo.colormap is a two-dimensional array
6581 of color indices in the range 0..mgr->cinfo.actual_number_of_colors. 6584 of color indices in the range 0..mgr->cinfo.actual_number_of_colors.
6582 No more than 255 colors will be generated. */ 6585 No more than 255 colors will be generated. */
6586 USE_SAFE_ALLOCA;
6583 { 6587 {
6584 int i, ir, ig, ib; 6588 int i, ir, ig, ib;
6585 6589
@@ -6595,7 +6599,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6595 a default color, and we don't have to care about which colors 6599 a default color, and we don't have to care about which colors
6596 can be freed safely, and which can't. */ 6600 can be freed safely, and which can't. */
6597 init_color_table (); 6601 init_color_table ();
6598 colors = alloca (mgr->cinfo.actual_number_of_colors * sizeof *colors); 6602 SAFE_NALLOCA (colors, 1, mgr->cinfo.actual_number_of_colors);
6599 6603
6600 for (i = 0; i < mgr->cinfo.actual_number_of_colors; ++i) 6604 for (i = 0; i < mgr->cinfo.actual_number_of_colors; ++i)
6601 { 6605 {
@@ -6638,6 +6642,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6638 6642
6639 /* Put ximg into the image. */ 6643 /* Put ximg into the image. */
6640 image_put_x_image (f, img, ximg, 0); 6644 image_put_x_image (f, img, ximg, 0);
6645 SAFE_FREE ();
6641 return 1; 6646 return 1;
6642} 6647}
6643 6648
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
diff --git a/src/keymap.c b/src/keymap.c
index f4dd644aebd..f7256bfde2a 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -2883,13 +2883,14 @@ You type Translation\n\
2883 if (!SYMBOLP (modes[i])) 2883 if (!SYMBOLP (modes[i]))
2884 emacs_abort (); 2884 emacs_abort ();
2885 2885
2886 p = title = alloca (42 + SCHARS (SYMBOL_NAME (modes[i]))); 2886 USE_SAFE_ALLOCA;
2887 p = title = SAFE_ALLOCA (42 + SBYTES (SYMBOL_NAME (modes[i])));
2887 *p++ = '\f'; 2888 *p++ = '\f';
2888 *p++ = '\n'; 2889 *p++ = '\n';
2889 *p++ = '`'; 2890 *p++ = '`';
2890 memcpy (p, SDATA (SYMBOL_NAME (modes[i])), 2891 memcpy (p, SDATA (SYMBOL_NAME (modes[i])),
2891 SCHARS (SYMBOL_NAME (modes[i]))); 2892 SBYTES (SYMBOL_NAME (modes[i])));
2892 p += SCHARS (SYMBOL_NAME (modes[i])); 2893 p += SBYTES (SYMBOL_NAME (modes[i]));
2893 *p++ = '\''; 2894 *p++ = '\'';
2894 memcpy (p, " Minor Mode Bindings", strlen (" Minor Mode Bindings")); 2895 memcpy (p, " Minor Mode Bindings", strlen (" Minor Mode Bindings"));
2895 p += strlen (" Minor Mode Bindings"); 2896 p += strlen (" Minor Mode Bindings");
@@ -2898,6 +2899,7 @@ You type Translation\n\
2898 describe_map_tree (maps[i], 1, shadow, prefix, 2899 describe_map_tree (maps[i], 1, shadow, prefix,
2899 title, nomenu, 0, 0, 0); 2900 title, nomenu, 0, 0, 0);
2900 shadow = Fcons (maps[i], shadow); 2901 shadow = Fcons (maps[i], shadow);
2902 SAFE_FREE ();
2901 } 2903 }
2902 2904
2903 start1 = get_local_map (BUF_PT (XBUFFER (buffer)), 2905 start1 = get_local_map (BUF_PT (XBUFFER (buffer)),
@@ -3184,10 +3186,10 @@ describe_map (Lisp_Object map, Lisp_Object prefix,
3184 3186
3185 /* These accumulate the values from sparse keymap bindings, 3187 /* These accumulate the values from sparse keymap bindings,
3186 so we can sort them and handle them in order. */ 3188 so we can sort them and handle them in order. */
3187 int length_needed = 0; 3189 ptrdiff_t length_needed = 0;
3188 struct describe_map_elt *vect; 3190 struct describe_map_elt *vect;
3189 int slots_used = 0; 3191 ptrdiff_t slots_used = 0;
3190 int i; 3192 ptrdiff_t i;
3191 3193
3192 suppress = Qnil; 3194 suppress = Qnil;
3193 3195
@@ -3207,7 +3209,8 @@ describe_map (Lisp_Object map, Lisp_Object prefix,
3207 for (tail = map; CONSP (tail); tail = XCDR (tail)) 3209 for (tail = map; CONSP (tail); tail = XCDR (tail))
3208 length_needed++; 3210 length_needed++;
3209 3211
3210 vect = alloca (length_needed * sizeof *vect); 3212 USE_SAFE_ALLOCA;
3213 SAFE_NALLOCA (vect, 1, length_needed);
3211 3214
3212 for (tail = map; CONSP (tail); tail = XCDR (tail)) 3215 for (tail = map; CONSP (tail); tail = XCDR (tail))
3213 { 3216 {
@@ -3350,6 +3353,7 @@ describe_map (Lisp_Object map, Lisp_Object prefix,
3350 } 3353 }
3351 } 3354 }
3352 3355
3356 SAFE_FREE ();
3353 UNGCPRO; 3357 UNGCPRO;
3354} 3358}
3355 3359
diff --git a/src/lisp.h b/src/lisp.h
index 53bfd7c4daf..15c459c9fdb 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4451,12 +4451,6 @@ egetenv (const char *var)
4451 return egetenv_internal (var, strlen (var)); 4451 return egetenv_internal (var, strlen (var));
4452} 4452}
4453 4453
4454/* Copy Lisp string to temporary (allocated on stack) C string. */
4455
4456#define xlispstrdupa(string) \
4457 memcpy (alloca (SBYTES (string) + 1), \
4458 SSDATA (string), SBYTES (string) + 1)
4459
4460/* Set up the name of the machine we're running on. */ 4454/* Set up the name of the machine we're running on. */
4461extern void init_system_name (void); 4455extern void init_system_name (void);
4462 4456
@@ -4484,7 +4478,7 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
4484 4478
4485/* SAFE_ALLOCA allocates a simple buffer. */ 4479/* SAFE_ALLOCA allocates a simple buffer. */
4486 4480
4487#define SAFE_ALLOCA(size) ((size) < MAX_ALLOCA \ 4481#define SAFE_ALLOCA(size) ((size) <= MAX_ALLOCA \
4488 ? alloca (size) \ 4482 ? alloca (size) \
4489 : (sa_must_free = true, record_xmalloc (size))) 4483 : (sa_must_free = true, record_xmalloc (size)))
4490 4484
@@ -4504,6 +4498,14 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
4504 } \ 4498 } \
4505 } while (false) 4499 } while (false)
4506 4500
4501/* SAFE_ALLOCA_STRING allocates a C copy of a Lisp string. */
4502
4503#define SAFE_ALLOCA_STRING(ptr, string) \
4504 do { \
4505 (ptr) = SAFE_ALLOCA (SBYTES (string) + 1); \
4506 memcpy (ptr, SDATA (string), SBYTES (string) + 1); \
4507 } while (false)
4508
4507/* SAFE_FREE frees xmalloced memory and enables GC as needed. */ 4509/* SAFE_FREE frees xmalloced memory and enables GC as needed. */
4508 4510
4509#define SAFE_FREE() \ 4511#define SAFE_FREE() \
@@ -4519,9 +4521,9 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
4519 4521
4520#define SAFE_ALLOCA_LISP(buf, nelt) \ 4522#define SAFE_ALLOCA_LISP(buf, nelt) \
4521 do { \ 4523 do { \
4522 if ((nelt) < MAX_ALLOCA / word_size) \ 4524 if ((nelt) <= MAX_ALLOCA / word_size) \
4523 (buf) = alloca ((nelt) * word_size); \ 4525 (buf) = alloca ((nelt) * word_size); \
4524 else if ((nelt) < min (PTRDIFF_MAX, SIZE_MAX) / word_size) \ 4526 else if ((nelt) <= min (PTRDIFF_MAX, SIZE_MAX) / word_size) \
4525 { \ 4527 { \
4526 Lisp_Object arg_; \ 4528 Lisp_Object arg_; \
4527 (buf) = xmalloc ((nelt) * word_size); \ 4529 (buf) = xmalloc ((nelt) * word_size); \
diff --git a/src/lread.c b/src/lread.c
index 7626e16e818..21046774cb8 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1473,6 +1473,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
1473 ptrdiff_t max_suffix_len = 0; 1473 ptrdiff_t max_suffix_len = 0;
1474 int last_errno = ENOENT; 1474 int last_errno = ENOENT;
1475 int save_fd = -1; 1475 int save_fd = -1;
1476 USE_SAFE_ALLOCA;
1476 1477
1477 /* The last-modified time of the newest matching file found. 1478 /* The last-modified time of the newest matching file found.
1478 Initialize it to something less than all valid timestamps. */ 1479 Initialize it to something less than all valid timestamps. */
@@ -1513,7 +1514,10 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
1513 this path element/specified file name and any possible suffix. */ 1514 this path element/specified file name and any possible suffix. */
1514 want_length = max_suffix_len + SBYTES (filename); 1515 want_length = max_suffix_len + SBYTES (filename);
1515 if (fn_size <= want_length) 1516 if (fn_size <= want_length)
1516 fn = alloca (fn_size = 100 + want_length); 1517 {
1518 fn_size = 100 + want_length;
1519 fn = SAFE_ALLOCA (fn_size);
1520 }
1517 1521
1518 /* Loop over suffixes. */ 1522 /* Loop over suffixes. */
1519 for (tail = NILP (suffixes) ? list1 (empty_unibyte_string) : suffixes; 1523 for (tail = NILP (suffixes) ? list1 (empty_unibyte_string) : suffixes;
@@ -1579,6 +1583,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
1579 /* We succeeded; return this descriptor and filename. */ 1583 /* We succeeded; return this descriptor and filename. */
1580 if (storeptr) 1584 if (storeptr)
1581 *storeptr = string; 1585 *storeptr = string;
1586 SAFE_FREE ();
1582 UNGCPRO; 1587 UNGCPRO;
1583 return -2; 1588 return -2;
1584 } 1589 }
@@ -1651,6 +1656,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
1651 /* We succeeded; return this descriptor and filename. */ 1656 /* We succeeded; return this descriptor and filename. */
1652 if (storeptr) 1657 if (storeptr)
1653 *storeptr = string; 1658 *storeptr = string;
1659 SAFE_FREE ();
1654 UNGCPRO; 1660 UNGCPRO;
1655 return fd; 1661 return fd;
1656 } 1662 }
@@ -1661,6 +1667,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
1661 { 1667 {
1662 if (storeptr) 1668 if (storeptr)
1663 *storeptr = save_string; 1669 *storeptr = save_string;
1670 SAFE_FREE ();
1664 UNGCPRO; 1671 UNGCPRO;
1665 return save_fd; 1672 return save_fd;
1666 } 1673 }
@@ -1670,6 +1677,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
1670 break; 1677 break;
1671 } 1678 }
1672 1679
1680 SAFE_FREE ();
1673 UNGCPRO; 1681 UNGCPRO;
1674 errno = last_errno; 1682 errno = last_errno;
1675 return -1; 1683 return -1;
diff --git a/src/menu.c b/src/menu.c
index 66247c713a2..8c624f758a9 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -632,8 +632,9 @@ digest_single_submenu (int start, int end, bool top_level_items)
632 widget_value **submenu_stack; 632 widget_value **submenu_stack;
633 bool panes_seen = 0; 633 bool panes_seen = 0;
634 struct frame *f = XFRAME (Vmenu_updating_frame); 634 struct frame *f = XFRAME (Vmenu_updating_frame);
635 USE_SAFE_ALLOCA;
635 636
636 submenu_stack = alloca (menu_items_used * sizeof *submenu_stack); 637 SAFE_NALLOCA (submenu_stack, 1, menu_items_used);
637 wv = make_widget_value ("menu", NULL, true, Qnil); 638 wv = make_widget_value ("menu", NULL, true, Qnil);
638 wv->button_type = BUTTON_TYPE_NONE; 639 wv->button_type = BUTTON_TYPE_NONE;
639 first_wv = wv; 640 first_wv = wv;
@@ -835,11 +836,12 @@ digest_single_submenu (int start, int end, bool top_level_items)
835 that was originally a button, return it by itself. */ 836 that was originally a button, return it by itself. */
836 if (top_level_items && first_wv->contents && first_wv->contents->next == 0) 837 if (top_level_items && first_wv->contents && first_wv->contents->next == 0)
837 { 838 {
838 wv = first_wv->contents; 839 wv = first_wv;
839 xfree (first_wv); 840 first_wv = first_wv->contents;
840 return wv; 841 xfree (wv);
841 } 842 }
842 843
844 SAFE_FREE ();
843 return first_wv; 845 return first_wv;
844} 846}
845 847
@@ -890,9 +892,10 @@ find_and_call_menu_selection (struct frame *f, int menu_bar_items_used,
890 Lisp_Object *subprefix_stack; 892 Lisp_Object *subprefix_stack;
891 int submenu_depth = 0; 893 int submenu_depth = 0;
892 int i; 894 int i;
895 USE_SAFE_ALLOCA;
893 896
894 entry = Qnil; 897 entry = Qnil;
895 subprefix_stack = alloca (menu_bar_items_used * sizeof *subprefix_stack); 898 SAFE_NALLOCA (subprefix_stack, 1, menu_bar_items_used);
896 prefix = Qnil; 899 prefix = Qnil;
897 i = 0; 900 i = 0;
898 901
@@ -954,11 +957,13 @@ find_and_call_menu_selection (struct frame *f, int menu_bar_items_used,
954 buf.arg = entry; 957 buf.arg = entry;
955 kbd_buffer_store_event (&buf); 958 kbd_buffer_store_event (&buf);
956 959
957 return; 960 break;
958 } 961 }
959 i += MENU_ITEMS_ITEM_LENGTH; 962 i += MENU_ITEMS_ITEM_LENGTH;
960 } 963 }
961 } 964 }
965
966 SAFE_FREE ();
962} 967}
963 968
964#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */ 969#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */
@@ -973,10 +978,11 @@ find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data
973 int i; 978 int i;
974 Lisp_Object *subprefix_stack; 979 Lisp_Object *subprefix_stack;
975 int submenu_depth = 0; 980 int submenu_depth = 0;
981 USE_SAFE_ALLOCA;
976 982
977 prefix = entry = Qnil; 983 prefix = entry = Qnil;
978 i = 0; 984 i = 0;
979 subprefix_stack = alloca (menu_items_used * word_size); 985 SAFE_ALLOCA_LISP (subprefix_stack, menu_items_used);
980 986
981 while (i < menu_items_used) 987 while (i < menu_items_used)
982 { 988 {
@@ -1018,11 +1024,13 @@ find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data
1018 if (!NILP (subprefix_stack[j])) 1024 if (!NILP (subprefix_stack[j]))
1019 entry = Fcons (subprefix_stack[j], entry); 1025 entry = Fcons (subprefix_stack[j], entry);
1020 } 1026 }
1027 SAFE_FREE ();
1021 return entry; 1028 return entry;
1022 } 1029 }
1023 i += MENU_ITEMS_ITEM_LENGTH; 1030 i += MENU_ITEMS_ITEM_LENGTH;
1024 } 1031 }
1025 } 1032 }
1033 SAFE_FREE ();
1026 return Qnil; 1034 return Qnil;
1027} 1035}
1028#endif /* HAVE_NS */ 1036#endif /* HAVE_NS */
diff --git a/src/print.c b/src/print.c
index 57fac7af378..d6ed3e41284 100644
--- a/src/print.c
+++ b/src/print.c
@@ -169,11 +169,13 @@ bool print_output_debug_flag EXTERNALLY_VISIBLE = 1;
169 if (print_buffer_pos != print_buffer_pos_byte \ 169 if (print_buffer_pos != print_buffer_pos_byte \
170 && NILP (BVAR (current_buffer, enable_multibyte_characters)))\ 170 && NILP (BVAR (current_buffer, enable_multibyte_characters)))\
171 { \ 171 { \
172 unsigned char *temp = alloca (print_buffer_pos + 1); \ 172 USE_SAFE_ALLOCA; \
173 unsigned char *temp = SAFE_ALLOCA (print_buffer_pos + 1); \
173 copy_text ((unsigned char *) print_buffer, temp, \ 174 copy_text ((unsigned char *) print_buffer, temp, \
174 print_buffer_pos_byte, 1, 0); \ 175 print_buffer_pos_byte, 1, 0); \
175 insert_1_both ((char *) temp, print_buffer_pos, \ 176 insert_1_both ((char *) temp, print_buffer_pos, \
176 print_buffer_pos, 0, 1, 0); \ 177 print_buffer_pos, 0, 1, 0); \
178 SAFE_FREE (); \
177 } \ 179 } \
178 else \ 180 else \
179 insert_1_both (print_buffer, print_buffer_pos, \ 181 insert_1_both (print_buffer, print_buffer_pos, \
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
4975static int 4979static int
4976read_process_output (Lisp_Object proc, register int channel) 4980read_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;
diff --git a/src/regex.c b/src/regex.c
index 1c1164da57d..9e9018bff88 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -457,11 +457,17 @@ init_syntax_once (void)
457 457
458# endif /* not alloca */ 458# endif /* not alloca */
459 459
460# define REGEX_ALLOCATE alloca 460# ifdef emacs
461# define REGEX_USE_SAFE_ALLOCA USE_SAFE_ALLOCA
462# define REGEX_SAFE_FREE() SAFE_FREE ()
463# define REGEX_ALLOCATE SAFE_ALLOCA
464# else
465# define REGEX_ALLOCATE alloca
466# endif
461 467
462/* Assumes a `char *destination' variable. */ 468/* Assumes a `char *destination' variable. */
463# define REGEX_REALLOCATE(source, osize, nsize) \ 469# define REGEX_REALLOCATE(source, osize, nsize) \
464 (destination = alloca (nsize), \ 470 (destination = REGEX_ALLOCATE (nsize), \
465 memcpy (destination, source, osize)) 471 memcpy (destination, source, osize))
466 472
467/* No need to do anything to free, after alloca. */ 473/* No need to do anything to free, after alloca. */
@@ -469,6 +475,11 @@ init_syntax_once (void)
469 475
470#endif /* not REGEX_MALLOC */ 476#endif /* not REGEX_MALLOC */
471 477
478#ifndef REGEX_USE_SAFE_ALLOCA
479# define REGEX_USE_SAFE_ALLOCA ((void) 0)
480# define REGEX_SAFE_FREE() ((void) 0)
481#endif
482
472/* Define how to allocate the failure stack. */ 483/* Define how to allocate the failure stack. */
473 484
474#if defined REL_ALLOC && defined REGEX_MALLOC 485#if defined REL_ALLOC && defined REGEX_MALLOC
@@ -482,22 +493,10 @@ init_syntax_once (void)
482 493
483#else /* not using relocating allocator */ 494#else /* not using relocating allocator */
484 495
485# ifdef REGEX_MALLOC 496# define REGEX_ALLOCATE_STACK(size) REGEX_ALLOCATE (size)
497# define REGEX_REALLOCATE_STACK(source, o, n) REGEX_REALLOCATE (source, o, n)
498# define REGEX_FREE_STACK(ptr) REGEX_FREE (ptr)
486 499
487# define REGEX_ALLOCATE_STACK malloc
488# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
489# define REGEX_FREE_STACK free
490
491# else /* not REGEX_MALLOC */
492
493# define REGEX_ALLOCATE_STACK alloca
494
495# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
496 REGEX_REALLOCATE (source, osize, nsize)
497/* No need to explicitly free anything. */
498# define REGEX_FREE_STACK(arg) ((void)0)
499
500# endif /* not REGEX_MALLOC */
501#endif /* not using relocating allocator */ 500#endif /* not using relocating allocator */
502 501
503 502
@@ -4579,6 +4578,7 @@ static int bcmp_translate (re_char *s1, re_char *s2,
4579 FREE_VAR (regend); \ 4578 FREE_VAR (regend); \
4580 FREE_VAR (best_regstart); \ 4579 FREE_VAR (best_regstart); \
4581 FREE_VAR (best_regend); \ 4580 FREE_VAR (best_regend); \
4581 REGEX_SAFE_FREE (); \
4582 } while (0) 4582 } while (0)
4583#else 4583#else
4584# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ 4584# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */
@@ -5018,6 +5018,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1,
5018 5018
5019 DEBUG_PRINT ("\n\nEntering re_match_2.\n"); 5019 DEBUG_PRINT ("\n\nEntering re_match_2.\n");
5020 5020
5021 REGEX_USE_SAFE_ALLOCA;
5022
5021 INIT_FAIL_STACK (); 5023 INIT_FAIL_STACK ();
5022 5024
5023#ifdef MATCH_MAY_ALLOCATE 5025#ifdef MATCH_MAY_ALLOCATE
diff --git a/src/scroll.c b/src/scroll.c
index 6c559663f80..7cb683c4577 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -245,18 +245,20 @@ do_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
245{ 245{
246 struct matrix_elt *p; 246 struct matrix_elt *p;
247 int i, j, k; 247 int i, j, k;
248 USE_SAFE_ALLOCA;
248 249
249 /* True if we have set a terminal window with set_terminal_window. */ 250 /* True if we have set a terminal window with set_terminal_window. */
250 bool terminal_window_p = 0; 251 bool terminal_window_p = 0;
251 252
252 /* A queue for line insertions to be done. */ 253 /* A queue for line insertions to be done. */
253 struct queue { int count, pos; }; 254 struct queue { int count, pos; };
254 struct queue *queue_start 255 struct queue *queue_start;
255 = alloca (current_matrix->nrows * sizeof *queue_start); 256 SAFE_NALLOCA (queue_start, 1, current_matrix->nrows);
256 struct queue *queue = queue_start; 257 struct queue *queue = queue_start;
257 258
258 char *retained_p = alloca (window_size * sizeof *retained_p); 259 char *retained_p = SAFE_ALLOCA (window_size);
259 int *copy_from = alloca (window_size * sizeof *copy_from); 260 int *copy_from;
261 SAFE_NALLOCA (copy_from, 1, window_size);
260 262
261 /* Zero means line is empty. */ 263 /* Zero means line is empty. */
262 memset (retained_p, 0, window_size * sizeof (char)); 264 memset (retained_p, 0, window_size * sizeof (char));
@@ -378,6 +380,7 @@ do_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
378 380
379 if (terminal_window_p) 381 if (terminal_window_p)
380 set_terminal_window (frame, 0); 382 set_terminal_window (frame, 0);
383 SAFE_FREE ();
381} 384}
382 385
383 386
@@ -649,10 +652,12 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
649{ 652{
650 struct matrix_elt *p; 653 struct matrix_elt *p;
651 int i, j; 654 int i, j;
655 USE_SAFE_ALLOCA;
652 656
653 /* A queue of deletions and insertions to be performed. */ 657 /* A queue of deletions and insertions to be performed. */
654 struct alt_queue { int count, pos, window; }; 658 struct alt_queue { int count, pos, window; };
655 struct alt_queue *queue_start = alloca (window_size * sizeof *queue_start); 659 struct alt_queue *queue_start;
660 SAFE_NALLOCA (queue_start, 1, window_size);
656 struct alt_queue *queue = queue_start; 661 struct alt_queue *queue = queue_start;
657 662
658 /* True if a terminal window has been set with set_terminal_window. */ 663 /* True if a terminal window has been set with set_terminal_window. */
@@ -667,11 +672,12 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
667 bool write_follows_p = 1; 672 bool write_follows_p = 1;
668 673
669 /* For each row in the new matrix what row of the old matrix it is. */ 674 /* For each row in the new matrix what row of the old matrix it is. */
670 int *copy_from = alloca (window_size * sizeof *copy_from); 675 int *copy_from;
676 SAFE_NALLOCA (copy_from, 1, window_size);
671 677
672 /* Non-zero for each row in the new matrix that is retained from the 678 /* Non-zero for each row in the new matrix that is retained from the
673 old matrix. Lines not retained are empty. */ 679 old matrix. Lines not retained are empty. */
674 char *retained_p = alloca (window_size * sizeof *retained_p); 680 char *retained_p = SAFE_ALLOCA (window_size);
675 681
676 memset (retained_p, 0, window_size * sizeof (char)); 682 memset (retained_p, 0, window_size * sizeof (char));
677 683
@@ -787,6 +793,7 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix,
787 793
788 if (terminal_window_p) 794 if (terminal_window_p)
789 set_terminal_window (frame, 0); 795 set_terminal_window (frame, 0);
796 SAFE_FREE ();
790} 797}
791 798
792 799
@@ -796,8 +803,9 @@ scrolling_1 (struct frame *frame, int window_size, int unchanged_at_top,
796 int unchanged_at_bottom, int *draw_cost, int *old_draw_cost, 803 int unchanged_at_bottom, int *draw_cost, int *old_draw_cost,
797 unsigned *old_hash, unsigned *new_hash, int free_at_end) 804 unsigned *old_hash, unsigned *new_hash, int free_at_end)
798{ 805{
799 struct matrix_elt *matrix 806 USE_SAFE_ALLOCA;
800 = alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix); 807 struct matrix_elt *matrix;
808 SAFE_NALLOCA (matrix, window_size + 1, window_size + 1);
801 809
802 if (FRAME_SCROLL_REGION_OK (frame)) 810 if (FRAME_SCROLL_REGION_OK (frame))
803 { 811 {
@@ -817,6 +825,8 @@ scrolling_1 (struct frame *frame, int window_size, int unchanged_at_top,
817 frame->current_matrix, matrix, window_size, 825 frame->current_matrix, matrix, window_size,
818 unchanged_at_top); 826 unchanged_at_top);
819 } 827 }
828
829 SAFE_FREE ();
820} 830}
821 831
822 832
diff --git a/src/search.c b/src/search.c
index ecfb2352144..9eed390244f 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1318,6 +1318,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1318 translation. Otherwise set to zero later. */ 1318 translation. Otherwise set to zero later. */
1319 int char_base = -1; 1319 int char_base = -1;
1320 bool boyer_moore_ok = 1; 1320 bool boyer_moore_ok = 1;
1321 USE_SAFE_ALLOCA;
1321 1322
1322 /* MULTIBYTE says whether the text to be searched is multibyte. 1323 /* MULTIBYTE says whether the text to be searched is multibyte.
1323 We must convert PATTERN to match that, or we will not really 1324 We must convert PATTERN to match that, or we will not really
@@ -1335,7 +1336,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1335 raw_pattern_size_byte 1336 raw_pattern_size_byte
1336 = count_size_as_multibyte (SDATA (string), 1337 = count_size_as_multibyte (SDATA (string),
1337 raw_pattern_size); 1338 raw_pattern_size);
1338 raw_pattern = alloca (raw_pattern_size_byte + 1); 1339 raw_pattern = SAFE_ALLOCA (raw_pattern_size_byte + 1);
1339 copy_text (SDATA (string), raw_pattern, 1340 copy_text (SDATA (string), raw_pattern,
1340 SCHARS (string), 0, 1); 1341 SCHARS (string), 0, 1);
1341 } 1342 }
@@ -1349,7 +1350,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1349 the chosen single-byte character set can possibly match. */ 1350 the chosen single-byte character set can possibly match. */
1350 raw_pattern_size = SCHARS (string); 1351 raw_pattern_size = SCHARS (string);
1351 raw_pattern_size_byte = SCHARS (string); 1352 raw_pattern_size_byte = SCHARS (string);
1352 raw_pattern = alloca (raw_pattern_size + 1); 1353 raw_pattern = SAFE_ALLOCA (raw_pattern_size + 1);
1353 copy_text (SDATA (string), raw_pattern, 1354 copy_text (SDATA (string), raw_pattern,
1354 SBYTES (string), 1, 0); 1355 SBYTES (string), 1, 0);
1355 } 1356 }
@@ -1357,7 +1358,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1357 /* Copy and optionally translate the pattern. */ 1358 /* Copy and optionally translate the pattern. */
1358 len = raw_pattern_size; 1359 len = raw_pattern_size;
1359 len_byte = raw_pattern_size_byte; 1360 len_byte = raw_pattern_size_byte;
1360 patbuf = alloca (len * MAX_MULTIBYTE_LENGTH); 1361 SAFE_NALLOCA (patbuf, MAX_MULTIBYTE_LENGTH, len);
1361 pat = patbuf; 1362 pat = patbuf;
1362 base_pat = raw_pattern; 1363 base_pat = raw_pattern;
1363 if (multibyte) 1364 if (multibyte)
@@ -1497,13 +1498,15 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1497 len_byte = pat - patbuf; 1498 len_byte = pat - patbuf;
1498 pat = base_pat = patbuf; 1499 pat = base_pat = patbuf;
1499 1500
1500 if (boyer_moore_ok) 1501 EMACS_INT result
1501 return boyer_moore (n, pat, len_byte, trt, inverse_trt, 1502 = (boyer_moore_ok
1502 pos_byte, lim_byte, 1503 ? boyer_moore (n, pat, len_byte, trt, inverse_trt,
1503 char_base); 1504 pos_byte, lim_byte,
1504 else 1505 char_base)
1505 return simple_search (n, pat, raw_pattern_size, len_byte, trt, 1506 : simple_search (n, pat, raw_pattern_size, len_byte, trt,
1506 pos, pos_byte, lim, lim_byte); 1507 pos, pos_byte, lim, lim_byte));
1508 SAFE_FREE ();
1509 return result;
1507 } 1510 }
1508} 1511}
1509 1512
@@ -2809,7 +2812,8 @@ Return value is undefined if the last search failed. */)
2809 2812
2810 prev = Qnil; 2813 prev = Qnil;
2811 2814
2812 data = alloca ((2 * search_regs.num_regs + 1) * sizeof *data); 2815 USE_SAFE_ALLOCA;
2816 SAFE_NALLOCA (data, 1, 2 * search_regs.num_regs + 1);
2813 2817
2814 len = 0; 2818 len = 0;
2815 for (i = 0; i < search_regs.num_regs; i++) 2819 for (i = 0; i < search_regs.num_regs; i++)
@@ -2852,25 +2856,28 @@ Return value is undefined if the last search failed. */)
2852 2856
2853 /* If REUSE is not usable, cons up the values and return them. */ 2857 /* If REUSE is not usable, cons up the values and return them. */
2854 if (! CONSP (reuse)) 2858 if (! CONSP (reuse))
2855 return Flist (len, data); 2859 reuse = Flist (len, data);
2856 2860 else
2857 /* If REUSE is a list, store as many value elements as will fit
2858 into the elements of REUSE. */
2859 for (i = 0, tail = reuse; CONSP (tail);
2860 i++, tail = XCDR (tail))
2861 { 2861 {
2862 /* If REUSE is a list, store as many value elements as will fit
2863 into the elements of REUSE. */
2864 for (i = 0, tail = reuse; CONSP (tail);
2865 i++, tail = XCDR (tail))
2866 {
2867 if (i < len)
2868 XSETCAR (tail, data[i]);
2869 else
2870 XSETCAR (tail, Qnil);
2871 prev = tail;
2872 }
2873
2874 /* If we couldn't fit all value elements into REUSE,
2875 cons up the rest of them and add them to the end of REUSE. */
2862 if (i < len) 2876 if (i < len)
2863 XSETCAR (tail, data[i]); 2877 XSETCDR (prev, Flist (len - i, data + i));
2864 else
2865 XSETCAR (tail, Qnil);
2866 prev = tail;
2867 } 2878 }
2868 2879
2869 /* If we couldn't fit all value elements into REUSE, 2880 SAFE_FREE ();
2870 cons up the rest of them and add them to the end of REUSE. */
2871 if (i < len)
2872 XSETCDR (prev, Flist (len - i, data + i));
2873
2874 return reuse; 2881 return reuse;
2875} 2882}
2876 2883
@@ -3075,7 +3082,8 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
3075 3082
3076 CHECK_STRING (string); 3083 CHECK_STRING (string);
3077 3084
3078 temp = alloca (SBYTES (string) * 2); 3085 USE_SAFE_ALLOCA;
3086 SAFE_NALLOCA (temp, 2, SBYTES (string));
3079 3087
3080 /* Now copy the data into the new string, inserting escapes. */ 3088 /* Now copy the data into the new string, inserting escapes. */
3081 3089
@@ -3093,10 +3101,13 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
3093 *out++ = *in; 3101 *out++ = *in;
3094 } 3102 }
3095 3103
3096 return make_specified_string (temp, 3104 Lisp_Object result
3097 SCHARS (string) + backslashes_added, 3105 = make_specified_string (temp,
3098 out - temp, 3106 SCHARS (string) + backslashes_added,
3099 STRING_MULTIBYTE (string)); 3107 out - temp,
3108 STRING_MULTIBYTE (string));
3109 SAFE_FREE ();
3110 return result;
3100} 3111}
3101 3112
3102/* Like find_newline, but doesn't use the cache, and only searches forward. */ 3113/* Like find_newline, but doesn't use the cache, and only searches forward. */
diff --git a/src/sound.c b/src/sound.c
index 7046f4e8e32..9351097138d 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -564,12 +564,11 @@ wav_play (struct sound *s, struct sound_device *sd)
564 SBYTES (s->data) - sizeof *header); 564 SBYTES (s->data) - sizeof *header);
565 else 565 else
566 { 566 {
567 char *buffer;
568 ptrdiff_t nbytes = 0; 567 ptrdiff_t nbytes = 0;
569 ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048; 568 ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048;
570 ptrdiff_t data_left = header->data_length; 569 ptrdiff_t data_left = header->data_length;
571 570 USE_SAFE_ALLOCA;
572 buffer = alloca (blksize); 571 char *buffer = SAFE_ALLOCA (blksize);
573 lseek (s->fd, sizeof *header, SEEK_SET); 572 lseek (s->fd, sizeof *header, SEEK_SET);
574 while (data_left > 0 573 while (data_left > 0
575 && (nbytes = emacs_read (s->fd, buffer, blksize)) > 0) 574 && (nbytes = emacs_read (s->fd, buffer, blksize)) > 0)
@@ -582,6 +581,7 @@ wav_play (struct sound *s, struct sound_device *sd)
582 581
583 if (nbytes < 0) 582 if (nbytes < 0)
584 sound_perror ("Error reading sound file"); 583 sound_perror ("Error reading sound file");
584 SAFE_FREE ();
585 } 585 }
586} 586}
587 587
@@ -656,19 +656,20 @@ au_play (struct sound *s, struct sound_device *sd)
656 else 656 else
657 { 657 {
658 ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048; 658 ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048;
659 char *buffer;
660 ptrdiff_t nbytes; 659 ptrdiff_t nbytes;
661 660
662 /* Seek */ 661 /* Seek */
663 lseek (s->fd, header->data_offset, SEEK_SET); 662 lseek (s->fd, header->data_offset, SEEK_SET);
664 663
665 /* Copy sound data to the device. */ 664 /* Copy sound data to the device. */
666 buffer = alloca (blksize); 665 USE_SAFE_ALLOCA;
666 char *buffer = SAFE_ALLOCA (blksize);
667 while ((nbytes = emacs_read (s->fd, buffer, blksize)) > 0) 667 while ((nbytes = emacs_read (s->fd, buffer, blksize)) > 0)
668 sd->write (sd, buffer, nbytes); 668 sd->write (sd, buffer, nbytes);
669 669
670 if (nbytes < 0) 670 if (nbytes < 0)
671 sound_perror ("Error reading sound file"); 671 sound_perror ("Error reading sound file");
672 SAFE_FREE ();
672 } 673 }
673} 674}
674 675
@@ -1309,7 +1310,6 @@ Internal use only, use `play-sound' instead. */)
1309 struct gcpro gcpro1, gcpro2; 1310 struct gcpro gcpro1, gcpro2;
1310 Lisp_Object args[2]; 1311 Lisp_Object args[2];
1311#else /* WINDOWSNT */ 1312#else /* WINDOWSNT */
1312 int len = 0;
1313 Lisp_Object lo_file = {0}; 1313 Lisp_Object lo_file = {0};
1314 char * psz_file = NULL; 1314 char * psz_file = NULL;
1315 unsigned long ui_volume_tmp = UINT_MAX; 1315 unsigned long ui_volume_tmp = UINT_MAX;
@@ -1326,7 +1326,8 @@ Internal use only, use `play-sound' instead. */)
1326 current_sound_device = xzalloc (sizeof *current_sound_device); 1326 current_sound_device = xzalloc (sizeof *current_sound_device);
1327 current_sound = xzalloc (sizeof *current_sound); 1327 current_sound = xzalloc (sizeof *current_sound);
1328 record_unwind_protect_void (sound_cleanup); 1328 record_unwind_protect_void (sound_cleanup);
1329 current_sound->header = alloca (MAX_SOUND_HEADER_BYTES); 1329 char headerbuf[MAX_SOUND_HEADER_BYTES];
1330 current_sound->header = headerbuf;
1330 1331
1331 if (STRINGP (attrs[SOUND_FILE])) 1332 if (STRINGP (attrs[SOUND_FILE]))
1332 { 1333 {
diff --git a/src/syntax.c b/src/syntax.c
index 69391bac9ed..9f5ef754e2a 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1567,6 +1567,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim,
1567 const unsigned char *str; 1567 const unsigned char *str;
1568 int len; 1568 int len;
1569 Lisp_Object iso_classes; 1569 Lisp_Object iso_classes;
1570 USE_SAFE_ALLOCA;
1570 1571
1571 CHECK_STRING (string); 1572 CHECK_STRING (string);
1572 iso_classes = Qnil; 1573 iso_classes = Qnil;
@@ -1699,7 +1700,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim,
1699 memcpy (himap, fastmap + 0200, 0200); 1700 memcpy (himap, fastmap + 0200, 0200);
1700 himap[0200] = 0; 1701 himap[0200] = 0;
1701 memset (fastmap + 0200, 0, 0200); 1702 memset (fastmap + 0200, 0, 0200);
1702 char_ranges = alloca (sizeof *char_ranges * 128 * 2); 1703 SAFE_NALLOCA (char_ranges, 2, 128);
1703 i = 0; 1704 i = 0;
1704 1705
1705 while ((p1 = memchr (himap + i, 1, 0200 - i))) 1706 while ((p1 = memchr (himap + i, 1, 0200 - i)))
@@ -1723,7 +1724,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim,
1723 } 1724 }
1724 else /* STRING is multibyte */ 1725 else /* STRING is multibyte */
1725 { 1726 {
1726 char_ranges = alloca (sizeof *char_ranges * SCHARS (string) * 2); 1727 SAFE_NALLOCA (char_ranges, 2, SCHARS (string));
1727 1728
1728 while (i_byte < size_byte) 1729 while (i_byte < size_byte)
1729 { 1730 {
@@ -2032,6 +2033,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim,
2032 SET_PT_BOTH (pos, pos_byte); 2033 SET_PT_BOTH (pos, pos_byte);
2033 immediate_quit = 0; 2034 immediate_quit = 0;
2034 2035
2036 SAFE_FREE ();
2035 return make_number (PT - start_point); 2037 return make_number (PT - start_point);
2036 } 2038 }
2037} 2039}
diff --git a/src/term.c b/src/term.c
index af1b62ccaaf..0a1b3dd13e2 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3191,6 +3191,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3191 Lisp_Object selectface; 3191 Lisp_Object selectface;
3192 int first_item = 0; 3192 int first_item = 0;
3193 int col, row; 3193 int col, row;
3194 USE_SAFE_ALLOCA;
3194 3195
3195 /* Don't allow non-positive x0 and y0, lest the menu will wrap 3196 /* Don't allow non-positive x0 and y0, lest the menu will wrap
3196 around the display. */ 3197 around the display. */
@@ -3199,7 +3200,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3199 if (y0 <= 0) 3200 if (y0 <= 0)
3200 y0 = 1; 3201 y0 = 1;
3201 3202
3202 state = alloca (menu->panecount * sizeof (struct tty_menu_state)); 3203 SAFE_NALLOCA (state, 1, menu->panecount);
3203 memset (state, 0, sizeof (*state)); 3204 memset (state, 0, sizeof (*state));
3204 faces[0] 3205 faces[0]
3205 = lookup_derived_face (sf, intern ("tty-menu-disabled-face"), 3206 = lookup_derived_face (sf, intern ("tty-menu-disabled-face"),
@@ -3421,6 +3422,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3421 discard_mouse_events (); 3422 discard_mouse_events ();
3422 if (!kbd_buffer_events_waiting ()) 3423 if (!kbd_buffer_events_waiting ())
3423 clear_input_pending (); 3424 clear_input_pending ();
3425 SAFE_FREE ();
3424 return result; 3426 return result;
3425} 3427}
3426 3428
@@ -3606,6 +3608,7 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags,
3606 item_y = y += f->top_pos; 3608 item_y = y += f->top_pos;
3607 3609
3608 /* Create all the necessary panes and their items. */ 3610 /* Create all the necessary panes and their items. */
3611 USE_SAFE_ALLOCA;
3609 maxwidth = maxlines = lines = i = 0; 3612 maxwidth = maxlines = lines = i = 0;
3610 lpane = TTYM_FAILURE; 3613 lpane = TTYM_FAILURE;
3611 while (i < menu_items_used) 3614 while (i < menu_items_used)
@@ -3674,9 +3677,7 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags,
3674 3677
3675 if (!NILP (descrip)) 3678 if (!NILP (descrip))
3676 { 3679 {
3677 /* If alloca is fast, use that to make the space, 3680 item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1);
3678 to reduce gc needs. */
3679 item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1);
3680 memcpy (item_data, SSDATA (item_name), SBYTES (item_name)); 3681 memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
3681 for (j = SCHARS (item_name); j < maxwidth; j++) 3682 for (j = SCHARS (item_name); j < maxwidth; j++)
3682 item_data[j] = ' '; 3683 item_data[j] = ' ';
@@ -3829,6 +3830,7 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags,
3829 3830
3830 tty_menu_end: 3831 tty_menu_end:
3831 3832
3833 SAFE_FREE ();
3832 unbind_to (specpdl_count, Qnil); 3834 unbind_to (specpdl_count, Qnil);
3833 return entry; 3835 return entry;
3834} 3836}
diff --git a/src/textprop.c b/src/textprop.c
index bd09304ba3b..2eea2d20839 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -660,6 +660,7 @@ get_char_property_and_overlay (Lisp_Object position, register Lisp_Object prop,
660 660
661 set_buffer_temp (XBUFFER (object)); 661 set_buffer_temp (XBUFFER (object));
662 662
663 USE_SAFE_ALLOCA;
663 GET_OVERLAYS_AT (XINT (position), overlay_vec, noverlays, NULL, 0); 664 GET_OVERLAYS_AT (XINT (position), overlay_vec, noverlays, NULL, 0);
664 noverlays = sort_overlays (overlay_vec, noverlays, w); 665 noverlays = sort_overlays (overlay_vec, noverlays, w);
665 666
@@ -674,9 +675,11 @@ get_char_property_and_overlay (Lisp_Object position, register Lisp_Object prop,
674 if (overlay) 675 if (overlay)
675 /* Return the overlay we got the property from. */ 676 /* Return the overlay we got the property from. */
676 *overlay = overlay_vec[noverlays]; 677 *overlay = overlay_vec[noverlays];
678 SAFE_FREE ();
677 return tem; 679 return tem;
678 } 680 }
679 } 681 }
682 SAFE_FREE ();
680 } 683 }
681 684
682 if (overlay) 685 if (overlay)
diff --git a/src/window.c b/src/window.c
index ac685f6867f..341e3e3dcd2 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6124,6 +6124,7 @@ the return value is nil. Otherwise the value is t. */)
6124 Lisp_Object frame; 6124 Lisp_Object frame;
6125 struct frame *f; 6125 struct frame *f;
6126 ptrdiff_t old_point = -1; 6126 ptrdiff_t old_point = -1;
6127 USE_SAFE_ALLOCA;
6127 6128
6128 CHECK_WINDOW_CONFIGURATION (configuration); 6129 CHECK_WINDOW_CONFIGURATION (configuration);
6129 6130
@@ -6231,8 +6232,8 @@ the return value is nil. Otherwise the value is t. */)
6231 really like to do is to free only those matrices not reused 6232 really like to do is to free only those matrices not reused
6232 below. */ 6233 below. */
6233 root_window = XWINDOW (FRAME_ROOT_WINDOW (f)); 6234 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6234 leaf_windows = alloca (count_windows (root_window) 6235 int nwindows = count_windows (root_window);
6235 * sizeof *leaf_windows); 6236 SAFE_NALLOCA (leaf_windows, 1, nwindows);
6236 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0); 6237 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6237 6238
6238 /* Kludge Alert! 6239 /* Kludge Alert!
@@ -6456,6 +6457,7 @@ the return value is nil. Otherwise the value is t. */)
6456 Vminibuf_scroll_window = data->minibuf_scroll_window; 6457 Vminibuf_scroll_window = data->minibuf_scroll_window;
6457 minibuf_selected_window = data->minibuf_selected_window; 6458 minibuf_selected_window = data->minibuf_selected_window;
6458 6459
6460 SAFE_FREE ();
6459 return (FRAME_LIVE_P (f) ? Qt : Qnil); 6461 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6460} 6462}
6461 6463
diff --git a/src/xdisp.c b/src/xdisp.c
index a22519abe40..d02caba5c19 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2626,15 +2626,14 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
2626 { 2626 {
2627 ptrdiff_t i; 2627 ptrdiff_t i;
2628 ptrdiff_t count = SPECPDL_INDEX (); 2628 ptrdiff_t count = SPECPDL_INDEX ();
2629 struct gcpro gcpro1; 2629 Lisp_Object *args;
2630 Lisp_Object *args = alloca (nargs * word_size); 2630 USE_SAFE_ALLOCA;
2631 SAFE_ALLOCA_LISP (args, nargs);
2631 2632
2632 args[0] = func; 2633 args[0] = func;
2633 for (i = 1; i < nargs; i++) 2634 for (i = 1; i < nargs; i++)
2634 args[i] = va_arg (ap, Lisp_Object); 2635 args[i] = va_arg (ap, Lisp_Object);
2635 2636
2636 GCPRO1 (args[0]);
2637 gcpro1.nvars = nargs;
2638 specbind (Qinhibit_redisplay, Qt); 2637 specbind (Qinhibit_redisplay, Qt);
2639 if (inhibit_quit) 2638 if (inhibit_quit)
2640 specbind (Qinhibit_quit, Qt); 2639 specbind (Qinhibit_quit, Qt);
@@ -2642,7 +2641,7 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
2642 so there is no possibility of wanting to redisplay. */ 2641 so there is no possibility of wanting to redisplay. */
2643 val = internal_condition_case_n (Ffuncall, nargs, args, Qt, 2642 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
2644 safe_eval_handler); 2643 safe_eval_handler);
2645 UNGCPRO; 2644 SAFE_FREE ();
2646 val = unbind_to (count, val); 2645 val = unbind_to (count, val);
2647 } 2646 }
2648 2647
@@ -3659,6 +3658,7 @@ next_overlay_change (ptrdiff_t pos)
3659 ptrdiff_t i, noverlays; 3658 ptrdiff_t i, noverlays;
3660 ptrdiff_t endpos; 3659 ptrdiff_t endpos;
3661 Lisp_Object *overlays; 3660 Lisp_Object *overlays;
3661 USE_SAFE_ALLOCA;
3662 3662
3663 /* Get all overlays at the given position. */ 3663 /* Get all overlays at the given position. */
3664 GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1); 3664 GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1);
@@ -3675,6 +3675,7 @@ next_overlay_change (ptrdiff_t pos)
3675 endpos = min (endpos, oendpos); 3675 endpos = min (endpos, oendpos);
3676 } 3676 }
3677 3677
3678 SAFE_FREE ();
3678 return endpos; 3679 return endpos;
3679} 3680}
3680 3681
@@ -5735,10 +5736,11 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
5735 Lisp_Object overlay, window, str, invisible; 5736 Lisp_Object overlay, window, str, invisible;
5736 struct Lisp_Overlay *ov; 5737 struct Lisp_Overlay *ov;
5737 ptrdiff_t start, end; 5738 ptrdiff_t start, end;
5738 ptrdiff_t size = 20;
5739 ptrdiff_t n = 0, i, j; 5739 ptrdiff_t n = 0, i, j;
5740 int invis_p; 5740 int invis_p;
5741 struct overlay_entry *entries = alloca (size * sizeof *entries); 5741 struct overlay_entry entriesbuf[20];
5742 ptrdiff_t size = ARRAYELTS (entriesbuf);
5743 struct overlay_entry *entries = entriesbuf;
5742 USE_SAFE_ALLOCA; 5744 USE_SAFE_ALLOCA;
5743 5745
5744 if (charpos <= 0) 5746 if (charpos <= 0)
@@ -10191,9 +10193,9 @@ message3 (Lisp_Object m)
10191 { 10193 {
10192 ptrdiff_t nbytes = SBYTES (m); 10194 ptrdiff_t nbytes = SBYTES (m);
10193 bool multibyte = STRING_MULTIBYTE (m); 10195 bool multibyte = STRING_MULTIBYTE (m);
10196 char *buffer;
10194 USE_SAFE_ALLOCA; 10197 USE_SAFE_ALLOCA;
10195 char *buffer = SAFE_ALLOCA (nbytes); 10198 SAFE_ALLOCA_STRING (buffer, m);
10196 memcpy (buffer, SDATA (m), nbytes);
10197 message_dolog (buffer, nbytes, 1, multibyte); 10199 message_dolog (buffer, nbytes, 1, multibyte);
10198 SAFE_FREE (); 10200 SAFE_FREE ();
10199 } 10201 }
@@ -10395,11 +10397,13 @@ vmessage (const char *m, va_list ap)
10395 { 10397 {
10396 ptrdiff_t len; 10398 ptrdiff_t len;
10397 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f); 10399 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
10398 char *message_buf = alloca (maxsize + 1); 10400 USE_SAFE_ALLOCA;
10401 char *message_buf = SAFE_ALLOCA (maxsize + 1);
10399 10402
10400 len = doprnt (message_buf, maxsize, m, 0, ap); 10403 len = doprnt (message_buf, maxsize, m, 0, ap);
10401 10404
10402 message3 (make_string (message_buf, len)); 10405 message3 (make_string (message_buf, len));
10406 SAFE_FREE ();
10403 } 10407 }
10404 else 10408 else
10405 message1 (0); 10409 message1 (0);
@@ -18695,10 +18699,10 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
18695 else if (glyphs == 1) 18699 else if (glyphs == 1)
18696 { 18700 {
18697 int area; 18701 int area;
18702 char s[SHRT_MAX + 4];
18698 18703
18699 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) 18704 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
18700 { 18705 {
18701 char *s = alloca (row->used[area] + 4);
18702 int i; 18706 int i;
18703 18707
18704 for (i = 0; i < row->used[area]; ++i) 18708 for (i = 0; i < row->used[area]; ++i)
@@ -22690,10 +22694,8 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_
22690 } 22694 }
22691 else if (CHARACTERP (eoltype)) 22695 else if (CHARACTERP (eoltype))
22692 { 22696 {
22693 unsigned char *tmp = alloca (MAX_MULTIBYTE_LENGTH);
22694 int c = XFASTINT (eoltype); 22697 int c = XFASTINT (eoltype);
22695 eol_str_len = CHAR_STRING (c, tmp); 22698 return buf + CHAR_STRING (c, (unsigned char *) buf);
22696 eol_str = tmp;
22697 } 22699 }
22698 else 22700 else
22699 { 22701 {
@@ -24609,7 +24611,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
24609 face_id = (row)->glyphs[area][START].face_id; \ 24611 face_id = (row)->glyphs[area][START].face_id; \
24610 \ 24612 \
24611 s = alloca (sizeof *s); \ 24613 s = alloca (sizeof *s); \
24612 char2b = alloca ((END - START) * sizeof *char2b); \ 24614 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
24613 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ 24615 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
24614 append_glyph_string (&HEAD, &TAIL, s); \ 24616 append_glyph_string (&HEAD, &TAIL, s); \
24615 s->x = (X); \ 24617 s->x = (X); \
@@ -24637,7 +24639,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
24637 struct glyph_string *first_s = NULL; \ 24639 struct glyph_string *first_s = NULL; \
24638 int n; \ 24640 int n; \
24639 \ 24641 \
24640 char2b = alloca (cmp->glyph_len * sizeof *char2b); \ 24642 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
24641 \ 24643 \
24642 /* Make glyph_strings for each glyph sequence that is drawable by \ 24644 /* Make glyph_strings for each glyph sequence that is drawable by \
24643 the same face, and append them to HEAD/TAIL. */ \ 24645 the same face, and append them to HEAD/TAIL. */ \
@@ -24672,7 +24674,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
24672 gstring = (composition_gstring_from_id \ 24674 gstring = (composition_gstring_from_id \
24673 ((row)->glyphs[area][START].u.cmp.id)); \ 24675 ((row)->glyphs[area][START].u.cmp.id)); \
24674 s = alloca (sizeof *s); \ 24676 s = alloca (sizeof *s); \
24675 char2b = alloca (LGSTRING_GLYPH_LEN (gstring) * sizeof *char2b); \ 24677 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
24676 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ 24678 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
24677 append_glyph_string (&(HEAD), &(TAIL), s); \ 24679 append_glyph_string (&(HEAD), &(TAIL), s); \
24678 s->x = (X); \ 24680 s->x = (X); \
@@ -24824,6 +24826,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
24824 BUILD_GLYPH_STRINGS will modify its start parameter. That's 24826 BUILD_GLYPH_STRINGS will modify its start parameter. That's
24825 the reason we use a separate variable `i'. */ 24827 the reason we use a separate variable `i'. */
24826 i = start; 24828 i = start;
24829 USE_SAFE_ALLOCA;
24827 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x); 24830 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
24828 if (tail) 24831 if (tail)
24829 x_reached = tail->x + tail->background_width; 24832 x_reached = tail->x + tail->background_width;
@@ -25023,6 +25026,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
25023 25026
25024 RELEASE_HDC (hdc, f); 25027 RELEASE_HDC (hdc, f);
25025 25028
25029 SAFE_FREE ();
25026 return x_reached; 25030 return x_reached;
25027} 25031}
25028 25032
@@ -29291,6 +29295,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
29291 /* Is this char mouse-active or does it have help-echo? */ 29295 /* Is this char mouse-active or does it have help-echo? */
29292 position = make_number (pos); 29296 position = make_number (pos);
29293 29297
29298 USE_SAFE_ALLOCA;
29299
29294 if (BUFFERP (object)) 29300 if (BUFFERP (object))
29295 { 29301 {
29296 /* Put all the overlays we want in a vector in overlay_vec. */ 29302 /* Put all the overlays we want in a vector in overlay_vec. */
@@ -29572,6 +29578,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
29572 BEGV = obegv; 29578 BEGV = obegv;
29573 ZV = ozv; 29579 ZV = ozv;
29574 current_buffer = obuf; 29580 current_buffer = obuf;
29581 SAFE_FREE ();
29575 } 29582 }
29576 29583
29577 set_cursor: 29584 set_cursor:
diff --git a/src/xfaces.c b/src/xfaces.c
index 047f75ffb19..a0998d7cbbc 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -5980,6 +5980,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5980 endpos = XINT (end); 5980 endpos = XINT (end);
5981 5981
5982 /* Look at properties from overlays. */ 5982 /* Look at properties from overlays. */
5983 USE_SAFE_ALLOCA;
5983 { 5984 {
5984 ptrdiff_t next_overlay; 5985 ptrdiff_t next_overlay;
5985 5986
@@ -6006,7 +6007,10 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6006 /* Optimize common cases where we can use the default face. */ 6007 /* Optimize common cases where we can use the default face. */
6007 if (noverlays == 0 6008 if (noverlays == 0
6008 && NILP (prop)) 6009 && NILP (prop))
6009 return default_face->id; 6010 {
6011 SAFE_FREE ();
6012 return default_face->id;
6013 }
6010 6014
6011 /* Begin with attributes from the default face. */ 6015 /* Begin with attributes from the default face. */
6012 memcpy (attrs, default_face->lface, sizeof attrs); 6016 memcpy (attrs, default_face->lface, sizeof attrs);
@@ -6034,6 +6038,8 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6034 6038
6035 *endptr = endpos; 6039 *endptr = endpos;
6036 6040
6041 SAFE_FREE ();
6042
6037 /* Look up a realized face with the given face attributes, 6043 /* Look up a realized face with the given face attributes,
6038 or realize a new one for ASCII characters. */ 6044 or realize a new one for ASCII characters. */
6039 return lookup_face (f, attrs); 6045 return lookup_face (f, attrs);
diff --git a/src/xmenu.c b/src/xmenu.c
index a7d47188ef5..8bb8d17369c 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -2023,7 +2023,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
2023 Window root; 2023 Window root;
2024 XMenu *menu; 2024 XMenu *menu;
2025 int pane, selidx, lpane, status; 2025 int pane, selidx, lpane, status;
2026 Lisp_Object entry, pane_prefix; 2026 Lisp_Object entry = Qnil;
2027 Lisp_Object pane_prefix;
2027 char *datap; 2028 char *datap;
2028 int ulx, uly, width, height; 2029 int ulx, uly, width, height;
2029 int dispwidth, dispheight; 2030 int dispwidth, dispheight;
@@ -2045,6 +2046,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
2045 return Qnil; 2046 return Qnil;
2046 } 2047 }
2047 2048
2049 USE_SAFE_ALLOCA;
2048 block_input (); 2050 block_input ();
2049 2051
2050 /* Figure out which root window F is on. */ 2052 /* Figure out which root window F is on. */
@@ -2057,8 +2059,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
2057 if (menu == NULL) 2059 if (menu == NULL)
2058 { 2060 {
2059 *error_name = "Can't create menu"; 2061 *error_name = "Can't create menu";
2060 unblock_input (); 2062 goto return_entry;
2061 return Qnil;
2062 } 2063 }
2063 2064
2064 /* Don't GC while we prepare and show the menu, 2065 /* Don't GC while we prepare and show the menu,
@@ -2101,8 +2102,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
2101 { 2102 {
2102 XMenuDestroy (FRAME_X_DISPLAY (f), menu); 2103 XMenuDestroy (FRAME_X_DISPLAY (f), menu);
2103 *error_name = "Can't create pane"; 2104 *error_name = "Can't create pane";
2104 unblock_input (); 2105 goto return_entry;
2105 return Qnil;
2106 } 2106 }
2107 i += MENU_ITEMS_PANE_LENGTH; 2107 i += MENU_ITEMS_PANE_LENGTH;
2108 2108
@@ -2146,9 +2146,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
2146 2146
2147 if (!NILP (descrip)) 2147 if (!NILP (descrip))
2148 { 2148 {
2149 /* if alloca is fast, use that to make the space, 2149 item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1);
2150 to reduce gc needs. */
2151 item_data = alloca (maxwidth + SBYTES (descrip) + 1);
2152 memcpy (item_data, SSDATA (item_name), SBYTES (item_name)); 2150 memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
2153 for (j = SCHARS (item_name); j < maxwidth; j++) 2151 for (j = SCHARS (item_name); j < maxwidth; j++)
2154 item_data[j] = ' '; 2152 item_data[j] = ' ';
@@ -2166,8 +2164,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
2166 { 2164 {
2167 XMenuDestroy (FRAME_X_DISPLAY (f), menu); 2165 XMenuDestroy (FRAME_X_DISPLAY (f), menu);
2168 *error_name = "Can't add selection to menu"; 2166 *error_name = "Can't add selection to menu";
2169 unblock_input (); 2167 goto return_entry;
2170 return Qnil;
2171 } 2168 }
2172 i += MENU_ITEMS_ITEM_LENGTH; 2169 i += MENU_ITEMS_ITEM_LENGTH;
2173 lines++; 2170 lines++;
@@ -2241,7 +2238,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
2241 status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx, 2238 status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
2242 x, y, ButtonReleaseMask, &datap, 2239 x, y, ButtonReleaseMask, &datap,
2243 menu_help_callback); 2240 menu_help_callback);
2244 entry = pane_prefix = Qnil; 2241 pane_prefix = Qnil;
2245 2242
2246 switch (status) 2243 switch (status)
2247 { 2244 {
@@ -2300,10 +2297,10 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
2300 break; 2297 break;
2301 } 2298 }
2302 2299
2300 return_entry:
2303 unblock_input (); 2301 unblock_input ();
2304 unbind_to (specpdl_count, Qnil); 2302 SAFE_FREE ();
2305 2303 return unbind_to (specpdl_count, entry);
2306 return entry;
2307} 2304}
2308 2305
2309#endif /* not USE_X_TOOLKIT */ 2306#endif /* not USE_X_TOOLKIT */