emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r117829: Use SAFE_ALLOCA etc. to avoid unbounded sta


From: Paul Eggert
Subject: [Emacs-diffs] trunk r117829: Use SAFE_ALLOCA etc. to avoid unbounded stack allocation.
Date: Sun, 07 Sep 2014 07:04:22 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 117829
revision-id: address@hidden
parent: address@hidden
fixes bug: http://debbugs.gnu.org/18410
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Sun 2014-09-07 00:04:01 -0700
message:
  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.
modified:
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/alloc.c                    alloc.c-20091113204419-o5vbwnq5f7feedwu-252
  src/buffer.c                   buffer.c-20091113204419-o5vbwnq5f7feedwu-264
  src/buffer.h                   buffer.h-20091113204419-o5vbwnq5f7feedwu-196
  src/callint.c                  callint.c-20091113204419-o5vbwnq5f7feedwu-279
  src/callproc.c                 callproc.c-20091113204419-o5vbwnq5f7feedwu-248
  src/coding.c                   coding.c-20091113204419-o5vbwnq5f7feedwu-1077
  src/doc.c                      doc.c-20091113204419-o5vbwnq5f7feedwu-250
  src/editfns.c                  editfns.c-20091113204419-o5vbwnq5f7feedwu-255
  src/eval.c                     eval.c-20091113204419-o5vbwnq5f7feedwu-237
  src/fileio.c                   fileio.c-20091113204419-o5vbwnq5f7feedwu-210
  src/fns.c                      fns.c-20091113204419-o5vbwnq5f7feedwu-203
  src/font.c                     font.c-20091113204419-o5vbwnq5f7feedwu-8540
  src/fontset.c                  fontset.c-20091113204419-o5vbwnq5f7feedwu-1079
  src/frame.c                    frame.c-20091113204419-o5vbwnq5f7feedwu-243
  src/ftfont.c                   ftfont.c-20091113204419-o5vbwnq5f7feedwu-8542
  src/ftxfont.c                  ftxfont.c-20091113204419-o5vbwnq5f7feedwu-8544
  src/image.c                    image.c-20091113204419-o5vbwnq5f7feedwu-2969
  src/keyboard.c                 keyboard.c-20091113204419-o5vbwnq5f7feedwu-449
  src/keymap.c                   keymap.c-20091113204419-o5vbwnq5f7feedwu-219
  src/lisp.h                     lisp.h-20091113204419-o5vbwnq5f7feedwu-253
  src/lread.c                    lread.c-20091113204419-o5vbwnq5f7feedwu-266
  src/menu.c                     menu.c-20091113204419-o5vbwnq5f7feedwu-8676
  src/print.c                    print.c-20091113204419-o5vbwnq5f7feedwu-262
  src/process.c                  process.c-20091113204419-o5vbwnq5f7feedwu-462
  src/regex.c                    regex.c-20091113204419-o5vbwnq5f7feedwu-518
  src/scroll.c                   scroll.c-20091113204419-o5vbwnq5f7feedwu-173
  src/search.c                   search.c-20091113204419-o5vbwnq5f7feedwu-473
  src/sound.c                    sound.c-20091113204419-o5vbwnq5f7feedwu-1323
  src/syntax.c                   syntax.c-20091113204419-o5vbwnq5f7feedwu-180
  src/term.c                     term.c-20091113204419-o5vbwnq5f7feedwu-220
  src/textprop.c                 textprop.c-20091113204419-o5vbwnq5f7feedwu-512
  src/window.c                   window.c-20091113204419-o5vbwnq5f7feedwu-231
  src/xdisp.c                    xdisp.c-20091113204419-o5vbwnq5f7feedwu-240
  src/xfaces.c                   xfaces.c-20091113204419-o5vbwnq5f7feedwu-560
  src/xmenu.c                    xmenu.c-20091113204419-o5vbwnq5f7feedwu-161
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2014-09-06 07:40:43 +0000
+++ b/src/ChangeLog     2014-09-07 07:04:01 +0000
@@ -1,3 +1,101 @@
+2014-09-07  Paul Eggert  <address@hidden>
+
+       Use SAFE_ALLOCA etc. to avoid unbounded stack allocation (Bug#18410).
+       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.
+
 2014-09-06  Eli Zaretskii  <address@hidden>
 
        * Makefile.in (EMACS_HEAPSIZE): Remove, no longer used.  (Bug#18416)

=== modified file 'src/alloc.c'
--- a/src/alloc.c       2014-08-29 07:29:47 +0000
+++ b/src/alloc.c       2014-09-07 07:04:01 +0000
@@ -2618,29 +2618,28 @@
 Lisp_Object
 listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...)
 {
+  Lisp_Object (*cons) (Lisp_Object, Lisp_Object);
+  switch (type)
+    {
+    case CONSTYPE_PURE: cons = pure_cons; break;
+    case CONSTYPE_HEAP: cons = Fcons; break;
+    default: emacs_abort ();
+    }
+
+  eassume (0 < count);
+  Lisp_Object val = cons (arg, Qnil);
+  Lisp_Object tail = val;
+
   va_list ap;
-  ptrdiff_t i;
-  Lisp_Object val, *objp;
-
-  /* Change to SAFE_ALLOCA if you hit this eassert.  */
-  eassert (count <= MAX_ALLOCA / word_size);
-
-  objp = alloca (count * word_size);
-  objp[0] = arg;
   va_start (ap, arg);
-  for (i = 1; i < count; i++)
-    objp[i] = va_arg (ap, Lisp_Object);
-  va_end (ap);
-
-  for (val = Qnil, i = count - 1; i >= 0; i--)
+  for (ptrdiff_t i = 1; i < count; i++)
     {
-      if (type == CONSTYPE_PURE)
-       val = pure_cons (objp[i], val);
-      else if (type == CONSTYPE_HEAP)
-       val = Fcons (objp[i], val);
-      else
-       emacs_abort ();
+      Lisp_Object elem = cons (va_arg (ap, Lisp_Object), Qnil);
+      XSETCDR (tail, elem);
+      tail = elem;
     }
+  va_end (ap);
+
   return val;
 }
 
@@ -3620,7 +3619,7 @@
   p->data[1].object = b;
   return val;
 }
-  
+
 #if ! (defined USE_X_TOOLKIT || defined USE_GTK)
 Lisp_Object
 make_save_ptr_ptr (void *a, void *b)

=== modified file 'src/buffer.c'
--- a/src/buffer.c      2014-09-03 15:10:29 +0000
+++ b/src/buffer.c      2014-09-07 07:04:01 +0000
@@ -3053,13 +3053,15 @@
   ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay));
   ptrdiff_t n, i, size;
   Lisp_Object *v, tem;
+  Lisp_Object vbuf[10];
+  USE_SAFE_ALLOCA;
 
-  size = 10;
-  v = alloca (size * sizeof *v);
+  size = ARRAYELTS (vbuf);
+  v = vbuf;
   n = overlays_in (start, end, 0, &v, &size, NULL, NULL);
   if (n > size)
     {
-      v = alloca (n * sizeof *v);
+      SAFE_NALLOCA (v, 1, n);
       overlays_in (start, end, 0, &v, &n, NULL, NULL);
     }
 
@@ -3069,6 +3071,7 @@
            !NILP (tem)))
       break;
 
+  SAFE_FREE ();
   return i < n;
 }
 
@@ -4517,13 +4520,13 @@
        First copy the vector contents, in case some of these hooks
        do subsequent modification of the buffer.  */
     ptrdiff_t size = last_overlay_modification_hooks_used;
-    Lisp_Object *copy = alloca (size * sizeof *copy);
+    Lisp_Object *copy;
     ptrdiff_t i;
 
+    USE_SAFE_ALLOCA;
+    SAFE_ALLOCA_LISP (copy, size);
     memcpy (copy, XVECTOR (last_overlay_modification_hooks)->contents,
            size * word_size);
-    gcpro1.var = copy;
-    gcpro1.nvars = size;
 
     for (i = 0; i < size;)
       {
@@ -4532,6 +4535,8 @@
        overlay_i = copy[i++];
        call_overlay_mod_hooks (prop_i, overlay_i, after, arg1, arg2, arg3);
       }
+
+    SAFE_FREE ();
   }
   UNGCPRO;
 }

=== modified file 'src/buffer.h'
--- a/src/buffer.h      2014-09-02 11:41:22 +0000
+++ b/src/buffer.h      2014-09-07 07:04:01 +0000
@@ -1127,15 +1127,15 @@
 #define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq)                
\
   do {                                                                 \
     ptrdiff_t maxlen = 40;                                             \
-    overlays = alloca (maxlen * sizeof *overlays);                     \
-    noverlays = overlays_at (posn, false, &overlays, &maxlen,          \
-                            nextp, NULL, chrq);                        \
-    if (noverlays > maxlen)                                            \
+    SAFE_NALLOCA (overlays, 1, maxlen);                                        
\
+    (noverlays) = overlays_at (posn, false, &(overlays), &maxlen,      \
+                              nextp, NULL, chrq);                      \
+    if ((noverlays) > maxlen)                                          \
       {                                                                        
\
        maxlen = noverlays;                                             \
-       overlays = alloca (maxlen * sizeof *overlays);                  \
-       noverlays = overlays_at (posn, false, &overlays, &maxlen,       \
-                                nextp, NULL, chrq);                    \
+       SAFE_NALLOCA (overlays, 1, maxlen);                             \
+       (noverlays) = overlays_at (posn, false, &(overlays), &maxlen,   \
+                                  nextp, NULL, chrq);                  \
       }                                                                        
\
   } while (false)
 

=== modified file 'src/callint.c'
--- a/src/callint.c     2014-06-17 13:50:22 +0000
+++ b/src/callint.c     2014-09-07 07:04:01 +0000
@@ -297,6 +297,7 @@
   Lisp_Object teml;
   Lisp_Object up_event;
   Lisp_Object enable;
+  USE_SAFE_ALLOCA;
   ptrdiff_t speccount = SPECPDL_INDEX ();
 
   /* The index of the next element of this_command_keys to examine for
@@ -366,12 +367,8 @@
       wrong_type_argument (Qcommandp, function);
   }
 
-  /* If SPECS is set to a string, use it as an interactive prompt.  */
-  if (STRINGP (specs))
-    /* Make a copy of string so that if a GC relocates specs,
-       `string' will still be valid.  */
-    string = xlispstrdupa (specs);
-  else
+  /* If SPECS is not a string, invent one.  */
+  if (! STRINGP (specs))
     {
       Lisp_Object input;
       Lisp_Object funval = Findirect_function (function, Qt);
@@ -416,10 +413,16 @@
        args[0] = Qfuncall_interactively;
        args[1] = function;
        args[2] = specs;
-       return unbind_to (speccount, Fapply (3, args));
+       Lisp_Object result = unbind_to (speccount, Fapply (3, args));
+       SAFE_FREE ();
+       return result;
       }
     }
 
+  /* SPECS is set to a string; use it as an interactive prompt.
+     Copy it so that STRING will be valid even if a GC relocates SPECS.  */
+  SAFE_ALLOCA_STRING (string, specs);
+
   /* Here if function specifies a string to control parsing the defaults.  */
 
   /* Set next_event to point to the first event with parameters.  */
@@ -507,14 +510,15 @@
        break;
     }
 
-  if (min (MOST_POSITIVE_FIXNUM,
-          min (PTRDIFF_MAX, SIZE_MAX) / word_size)
-      < nargs)
+  if (MOST_POSITIVE_FIXNUM < min (PTRDIFF_MAX, SIZE_MAX) / word_size
+      && MOST_POSITIVE_FIXNUM < nargs)
     memory_full (SIZE_MAX);
 
-  args = alloca (nargs * sizeof *args);
-  visargs = alloca (nargs * sizeof *visargs);
-  varies = alloca (nargs * sizeof *varies);
+  /* Allocate them all at one go.  This wastes a bit of memory, but
+     it's OK to trade space for speed.  */
+  SAFE_NALLOCA (args, 3, nargs);
+  visargs = args + nargs;
+  varies = (signed char *) (visargs + nargs);
 
   for (i = 0; i < nargs; i++)
     {
@@ -871,7 +875,9 @@
   {
     Lisp_Object val = Ffuncall (nargs, args);
     UNGCPRO;
-    return unbind_to (speccount, val);
+    val = unbind_to (speccount, val);
+    SAFE_FREE ();
+    return val;
   }
 }
 

=== modified file 'src/callproc.c'
--- a/src/callproc.c    2014-09-02 06:49:40 +0000
+++ b/src/callproc.c    2014-09-07 07:04:01 +0000
@@ -466,7 +466,7 @@
       && SREF (path, 1) == ':')
     path = Fsubstring (path, make_number (2), Qnil);
 
-  new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv);
+  SAFE_NALLOCA (new_argv, 1, nargs < 4 ? 2 : nargs - 2);
 
   {
     struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -1151,6 +1151,25 @@
   return new_env;
 }
 
+#ifndef DOS_NT
+
+/* 'exec' failed inside a child running NAME, with error number ERR.
+   Report the error and exit the child.  */
+
+static _Noreturn void
+exec_failed (char const *name, int err)
+{
+  /* Avoid deadlock if the child's perror writes to a full pipe; the
+     pipe's reader is the parent, but with vfork the parent can't
+     run until the child exits.  Truncate the diagnostic instead.  */
+  fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
+
+  errno = err;
+  emacs_perror (name);
+  _exit (err == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+}
+#endif
+
 /* This is the last thing run in a newly forked inferior
    either synchronous or asynchronous.
    Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
@@ -1174,8 +1193,6 @@
   int cpid;
   HANDLE handles[3];
 #else
-  int exec_errno;
-
   pid_t pid = getpid ();
 #endif /* WINDOWSNT */
 
@@ -1196,6 +1213,8 @@
        on that.  */
     pwd_var = xmalloc (i + 5);
 #else
+    if (MAX_ALLOCA - 5 < i)
+      exec_failed (new_argv[0], ENOMEM);
     pwd_var = alloca (i + 5);
 #endif
     temp = pwd_var + 4;
@@ -1262,6 +1281,8 @@
       }
 
     /* new_length + 2 to include PWD and terminating 0.  */
+    if (MAX_ALLOCA / sizeof *env - 2 < new_length)
+      exec_failed (new_argv[0], ENOMEM);
     env = new_env = alloca ((new_length + 2) * sizeof *env);
     /* If we have a PWD envvar, pass one down,
        but with corrected value.  */
@@ -1270,6 +1291,8 @@
 
     if (STRINGP (display))
       {
+       if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display))
+         exec_failed (new_argv[0], ENOMEM);
        char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
        strcpy (vdata, "DISPLAY=");
        strcat (vdata, SSDATA (display));
@@ -1345,16 +1368,7 @@
   tcsetpgrp (0, pid);
 
   execve (new_argv[0], new_argv, env);
-  exec_errno = errno;
-
-  /* Avoid deadlock if the child's perror writes to a full pipe; the
-     pipe's reader is the parent, but with vfork the parent can't
-     run until the child exits.  Truncate the diagnostic instead.  */
-  fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
-
-  errno = exec_errno;
-  emacs_perror (new_argv[0]);
-  _exit (exec_errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+  exec_failed (new_argv[0], errno);
 
 #else /* MSDOS */
   pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);
@@ -1543,20 +1557,13 @@
 void
 init_callproc (void)
 {
-  char *data_dir = egetenv ("EMACSDATA");
+  bool data_dir = egetenv ("EMACSDATA") != 0;
 
-  register char * sh;
+  char *sh;
   Lisp_Object tempdir;
 #ifdef HAVE_NS
   if (data_dir == 0)
-    {
-      const char *etc_dir = ns_etc_directory ();
-      if (etc_dir)
-        {
-          data_dir = alloca (strlen (etc_dir) + 1);
-          strcpy (data_dir, etc_dir);
-        }
-    }
+    data_dir == ns_etc_directory () != 0;
 #endif
 
   if (!NILP (Vinstallation_directory))

=== modified file 'src/coding.c'
--- a/src/coding.c      2014-08-11 00:59:34 +0000
+++ b/src/coding.c      2014-09-07 07:04:01 +0000
@@ -6867,6 +6867,11 @@
 }
 
 
+/* MAX_LOOKUP's maximum value.  MAX_LOOKUP is an int and so cannot
+   exceed INT_MAX.  Also, MAX_LOOKUP is multiplied by sizeof (int) for
+   alloca, so it cannot exceed MAX_ALLOCA / sizeof (int).  */
+enum { MAX_LOOKUP_MAX = min (INT_MAX, MAX_ALLOCA / sizeof (int)) };
+
 /* Return a translation table (or list of them) from coding system
    attribute vector ATTRS for encoding (if ENCODEP) or decoding (if
    not ENCODEP). */
@@ -6919,7 +6924,7 @@
        {
          val = XCHAR_TABLE (translation_table)->extras[1];
          if (NATNUMP (val) && *max_lookup < XFASTINT (val))
-           *max_lookup = XFASTINT (val);
+           *max_lookup = min (XFASTINT (val), MAX_LOOKUP_MAX);
        }
       else if (CONSP (translation_table))
        {
@@ -6931,7 +6936,7 @@
              {
                Lisp_Object tailval = XCHAR_TABLE (XCAR (tail))->extras[1];
                if (NATNUMP (tailval) && *max_lookup < XFASTINT (tailval))
-                 *max_lookup = XFASTINT (tailval);
+                 *max_lookup = min (XFASTINT (tailval), MAX_LOOKUP_MAX);
              }
        }
     }
@@ -10011,7 +10016,8 @@
 {
   Lisp_Object subsidiaries;
   ptrdiff_t base_name_len = SBYTES (SYMBOL_NAME (base));
-  char *buf = alloca (base_name_len + 6);
+  USE_SAFE_ALLOCA;
+  char *buf = SAFE_ALLOCA (base_name_len + 6);
   int i;
 
   memcpy (buf, SDATA (SYMBOL_NAME (base)), base_name_len);
@@ -10021,6 +10027,7 @@
       strcpy (buf + base_name_len, suffixes[i]);
       ASET (subsidiaries, i, intern (buf));
     }
+  SAFE_FREE ();
   return subsidiaries;
 }
 

=== modified file 'src/doc.c'
--- a/src/doc.c 2014-04-05 19:30:36 +0000
+++ b/src/doc.c 2014-09-07 07:04:01 +0000
@@ -561,6 +561,8 @@
   char *p, *name;
   bool skip_file = 0;
   ptrdiff_t count;
+  char const *dirname;
+  ptrdiff_t dirlen;
   /* Preloaded defcustoms using custom-initialize-delay are added to
      this list, but kept unbound.  See http://debbugs.gnu.org/11565  */
   Lisp_Object delayed_init =
@@ -577,15 +579,21 @@
       (0)
 #endif /* CANNOT_DUMP */
     {
-      name = alloca (SCHARS (filename) + 14);
-      strcpy (name, "../etc/");
+      static char const sibling_etc[] = "../etc/";
+      dirname = sibling_etc;
+      dirlen = sizeof sibling_etc - 1;
     }
   else
     {
       CHECK_STRING (Vdoc_directory);
-      name = alloca (SCHARS (filename) + SCHARS (Vdoc_directory) + 1);
-      strcpy (name, SSDATA (Vdoc_directory));
+      dirname = SSDATA (Vdoc_directory);
+      dirlen = SBYTES (Vdoc_directory);
     }
+
+  count = SPECPDL_INDEX ();
+  USE_SAFE_ALLOCA;
+  name = SAFE_ALLOCA (dirlen + SBYTES (filename) + 1);
+  strcpy (name, dirname);
   strcat (name, SSDATA (filename));    /*** Add this line ***/
 
   /* Vbuild_files is nil when temacs is run, and non-nil after that.  */
@@ -608,7 +616,6 @@
       report_file_errno ("Opening doc string file", build_string (name),
                         open_errno);
     }
-  count = SPECPDL_INDEX ();
   record_unwind_protect_int (close_file_unwind, fd);
   Vdoc_file_name = filename;
   filled = 0;
@@ -637,7 +644,7 @@
                   && (end[-1] == 'o' || end[-1] == 'c'))
                 {
                   ptrdiff_t len = end - p - 2;
-                  char *fromfile = alloca (len + 1);
+                  char *fromfile = SAFE_ALLOCA (len + 1);
                   memcpy (fromfile, &p[2], len);
                   fromfile[len] = 0;
                   if (fromfile[len-1] == 'c')
@@ -688,6 +695,8 @@
       filled -= end - buf;
       memmove (buf, end, filled);
     }
+
+  SAFE_FREE ();
   return unbind_to (count, Qnil);
 }
 

=== modified file 'src/editfns.c'
--- a/src/editfns.c     2014-08-07 10:15:52 +0000
+++ b/src/editfns.c     2014-09-07 07:04:01 +0000
@@ -376,13 +376,14 @@
       set_buffer_temp (XBUFFER (object));
 
       /* First try with room for 40 overlays.  */
-      noverlays = 40;
-      overlay_vec = alloca (noverlays * sizeof *overlay_vec);
+      Lisp_Object overlay_vecbuf[40];
+      noverlays = ARRAYELTS (overlay_vecbuf);
+      overlay_vec = overlay_vecbuf;
       noverlays = overlays_around (posn, overlay_vec, noverlays);
 
       /* If there are more than 40,
         make enough space for all, and try again.  */
-      if (noverlays > 40)
+      if (ARRAYELTS (overlay_vecbuf) < noverlays)
        {
          SAFE_ALLOCA_LISP (overlay_vec, noverlays);
          noverlays = overlays_around (posn, overlay_vec, noverlays);
@@ -1325,17 +1326,16 @@
   /* Substitute the login name for the &, upcasing the first character.  */
   if (q)
     {
-      register char *r;
-      Lisp_Object login;
-
-      login = Fuser_login_name (make_number (pw->pw_uid));
-      r = alloca (strlen (p) + SCHARS (login) + 1);
+      Lisp_Object login = Fuser_login_name (make_number (pw->pw_uid));
+      USE_SAFE_ALLOCA;
+      char *r = SAFE_ALLOCA (strlen (p) + SBYTES (login) + 1);
       memcpy (r, p, q - p);
       r[q - p] = 0;
       strcat (r, SSDATA (login));
       r[q - p] = upcase ((unsigned char) r[q - p]);
       strcat (r, q + 1);
       full = build_string (r);
+      SAFE_FREE ();
     }
 #endif /* AMPERSAND_FULL_NAME */
 
@@ -3012,8 +3012,12 @@
 check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end,
                   Lisp_Object val)
 {
-  int buf_size = 16, buf_used = 0;
-  int *buf = alloca (sizeof (int) * buf_size);
+  int initial_buf[16];
+  int *buf = initial_buf;
+  ptrdiff_t buf_size = ARRAYELTS (initial_buf);
+  int *bufalloc = 0;
+  ptrdiff_t buf_used = 0;
+  Lisp_Object result = Qnil;
 
   for (; CONSP (val); val = XCDR (val))
     {
@@ -3038,12 +3042,11 @@
 
                  if (buf_used == buf_size)
                    {
-                     int *newbuf;
-
-                     buf_size += 16;
-                     newbuf = alloca (sizeof (int) * buf_size);
-                     memcpy (newbuf, buf, sizeof (int) * buf_used);
-                     buf = newbuf;
+                     bufalloc = xpalloc (bufalloc, &buf_size, 1, -1,
+                                         sizeof *bufalloc);
+                     if (buf == initial_buf)
+                       memcpy (bufalloc, buf, sizeof initial_buf);
+                     buf = bufalloc;
                    }
                  buf[buf_used++] = STRING_CHAR_AND_LENGTH (p, len1);
                  pos_byte += len1;
@@ -3052,10 +3055,15 @@
                break;
            }
          if (i == len)
-           return XCAR (val);
+           {
+             result = XCAR (val);
+             break;
+           }
        }
     }
-  return Qnil;
+
+  xfree (bufalloc);
+  return result;
 }
 
 
@@ -4617,11 +4625,11 @@
       if (tmp_interval3)
        set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
 
+      USE_SAFE_ALLOCA;
+
       /* First region smaller than second.  */
       if (len1_byte < len2_byte)
         {
-         USE_SAFE_ALLOCA;
-
          temp = SAFE_ALLOCA (len2_byte);
 
          /* Don't precompute these addresses.  We have to compute them
@@ -4633,21 +4641,19 @@
           memcpy (temp, start2_addr, len2_byte);
           memcpy (start1_addr + len2_byte, start1_addr, len1_byte);
           memcpy (start1_addr, temp, len2_byte);
-         SAFE_FREE ();
         }
       else
        /* First region not smaller than second.  */
         {
-         USE_SAFE_ALLOCA;
-
          temp = SAFE_ALLOCA (len1_byte);
          start1_addr = BYTE_POS_ADDR (start1_byte);
          start2_addr = BYTE_POS_ADDR (start2_byte);
           memcpy (temp, start1_addr, len1_byte);
           memcpy (start1_addr, start2_addr, len2_byte);
           memcpy (start1_addr + len2_byte, temp, len1_byte);
-         SAFE_FREE ();
         }
+
+      SAFE_FREE ();
       graft_intervals_into_buffer (tmp_interval1, start1 + len2,
                                    len1, current_buffer, 0);
       graft_intervals_into_buffer (tmp_interval2, start1,

=== modified file 'src/eval.c'
--- a/src/eval.c        2014-09-03 04:21:40 +0000
+++ b/src/eval.c        2014-09-07 07:04:01 +0000
@@ -1272,7 +1272,10 @@
 
   { /* The first clause is the one that should be checked first, so it should
        be added to handlerlist last.  So we build in `clauses' a table that
-       contains `handlers' but in reverse order.  */
+       contains `handlers' but in reverse order.  SAFE_ALLOCA won't work
+       here due to the setjmp, so impose a MAX_ALLOCA limit.  */
+    if (MAX_ALLOCA / word_size < clausenb)
+      memory_full (SIZE_MAX);
     Lisp_Object *clauses = alloca (clausenb * sizeof *clauses);
     Lisp_Object *volatile clauses_volatile = clauses;
     int i = clausenb;
@@ -1311,7 +1314,7 @@
            return val;
          }
       }
-    }
+  }
 
   val = eval_sub (bodyform);
   handlerlist = oldhandlerlist;
@@ -2789,10 +2792,11 @@
        val = (XSUBR (fun)->function.aMANY) (numargs, args + 1);
       else
        {
+         Lisp_Object internal_argbuf[8];
          if (XSUBR (fun)->max_args > numargs)
            {
-             internal_args = alloca (XSUBR (fun)->max_args
-                                     * sizeof *internal_args);
+             eassert (XSUBR (fun)->max_args <= ARRAYELTS (internal_argbuf));
+             internal_args = internal_argbuf;
              memcpy (internal_args, args + 1, numargs * word_size);
              for (i = numargs; i < XSUBR (fun)->max_args; i++)
                internal_args[i] = Qnil;

=== modified file 'src/fileio.c'
--- a/src/fileio.c      2014-09-02 18:05:00 +0000
+++ b/src/fileio.c      2014-09-07 07:04:01 +0000
@@ -396,13 +396,6 @@
 Given a Unix syntax file name, returns a string ending in slash.  */)
   (Lisp_Object filename)
 {
-#ifndef DOS_NT
-  register const char *beg;
-#else
-  register char *beg;
-  Lisp_Object tem_fn;
-#endif
-  register const char *p;
   Lisp_Object handler;
 
   CHECK_STRING (filename);
@@ -417,12 +410,8 @@
       return STRINGP (handled_name) ? handled_name : Qnil;
     }
 
-#ifdef DOS_NT
-  beg = xlispstrdupa (filename);
-#else
-  beg = SSDATA (filename);
-#endif
-  p = beg + SBYTES (filename);
+  char *beg = SSDATA (filename);
+  char const *p = beg + SBYTES (filename);
 
   while (p != beg && !IS_DIRECTORY_SEP (p[-1])
 #ifdef DOS_NT
@@ -438,6 +427,11 @@
     return Qnil;
 #ifdef DOS_NT
   /* Expansion of "c:" to drive and default directory.  */
+  Lisp_Object tem_fn;
+  USE_SAFE_ALLOCA;
+  SAFE_ALLOCA_STRING (beg, filename);
+  p = beg + (p - SSDATA (filename));
+
   if (p[-1] == ':')
     {
       /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir.  */
@@ -481,6 +475,7 @@
       dostounix_filename (beg);
       tem_fn = make_specified_string (beg, -1, p - beg, 0);
     }
+  SAFE_FREE ();
   return tem_fn;
 #else  /* DOS_NT */
   return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename));
@@ -1019,7 +1014,7 @@
 #endif
 
   /* Make a local copy of NAME to protect it from GC in DECODE_FILE below.  */
-  nm = xlispstrdupa (name);
+  SAFE_ALLOCA_STRING (nm, name);
   nmlim = nm + SBYTES (name);
 
 #ifdef DOS_NT
@@ -1122,12 +1117,12 @@
          if (!NILP (Vw32_downcase_file_names))
            name = Fdowncase (name);
 #endif
+#else /* not DOS_NT */
+         if (strcmp (nm, SSDATA (name)) != 0)
+           name = make_specified_string (nm, -1, nmlim - nm, multibyte);
+#endif /* not DOS_NT */
+         SAFE_FREE ();
          return name;
-#else /* not DOS_NT */
-         if (strcmp (nm, SSDATA (name)) == 0)
-           return name;
-         return make_specified_string (nm, -1, nmlim - nm, multibyte);
-#endif /* not DOS_NT */
        }
     }
 
@@ -1729,7 +1724,8 @@
          for (s = p; *s && !IS_DIRECTORY_SEP (*s); s++);
          if (p[0] == '~' && s > p + 1) /* We've got "/~something/".  */
            {
-             char *o = alloca (s - p + 1);
+             USE_SAFE_ALLOCA;
+             char *o = SAFE_ALLOCA (s - p + 1);
              struct passwd *pw;
              memcpy (o, p, s - p);
              o [s - p] = 0;
@@ -1740,6 +1736,7 @@
              block_input ();
              pw = getpwnam (o + 1);
              unblock_input ();
+             SAFE_FREE ();
              if (pw)
                return p;
            }
@@ -1788,7 +1785,8 @@
   /* Always work on a copy of the string, in case GC happens during
      decode of environment variables, causing the original Lisp_String
      data to be relocated.  */
-  nm = xlispstrdupa (filename);
+  USE_SAFE_ALLOCA;
+  SAFE_ALLOCA_STRING (nm, filename);
 
 #ifdef DOS_NT
   dostounix_filename (nm);
@@ -1802,8 +1800,13 @@
     /* Start over with the new string, so we check the file-name-handler
        again.  Important with filenames like "/home/foo//:/hello///there"
        which would substitute to "/:/hello///there" rather than "/there".  */
-    return Fsubstitute_in_file_name
-      (make_specified_string (p, -1, endp - p, multibyte));
+    {
+      Lisp_Object result
+       = (Fsubstitute_in_file_name
+          (make_specified_string (p, -1, endp - p, multibyte)));
+      SAFE_FREE ();
+      return result;
+    }
 
   /* See if any variables are substituted into the string.  */
 
@@ -1825,6 +1828,7 @@
       if (!NILP (Vw32_downcase_file_names))
        filename = Fdowncase (filename);
 #endif
+      SAFE_FREE ();
       return filename;
     }
 
@@ -1843,14 +1847,14 @@
     {
       Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte);
 
-      xname = Fdowncase (xname);
-      return xname;
+      filename = Fdowncase (xname);
     }
   else
 #endif
-  return (xnm == SSDATA (filename)
-         ? filename
-         : make_specified_string (xnm, -1, x - xnm, multibyte));
+  if (xnm != SSDATA (filename))
+    filename = make_specified_string (xnm, -1, x - xnm, multibyte);
+  SAFE_FREE ();
+  return filename;
 }
 
 /* A slightly faster and more convenient way to get

=== modified file 'src/fns.c'
--- a/src/fns.c 2014-08-30 23:29:23 +0000
+++ b/src/fns.c 2014-09-07 07:04:01 +0000
@@ -1992,17 +1992,14 @@
     return;
   ptrdiff_t halflen = len >> 1;
   Lisp_Object *tmp;
-  Lisp_Object tmpvec = Qnil;
-  struct gcpro gcpro1, gcpro2, gcpro3;
-  GCPRO3 (vector, predicate, tmpvec);
-  if (halflen < MAX_ALLOCA / word_size)
-    tmp = alloca (halflen * word_size);
-  else
-    {
-      tmpvec = Fmake_vector (make_number (halflen), make_number (0));
-      tmp = XVECTOR (tmpvec)->contents;
-    }
+  struct gcpro gcpro1, gcpro2;
+  GCPRO2 (vector, predicate);
+  USE_SAFE_ALLOCA;
+  SAFE_ALLOCA_LISP (tmp, halflen);
+  for (ptrdiff_t i = 0; i < halflen; i++)
+    tmp[i] = make_number (0);
   sort_vector_inplace (predicate, len, XVECTOR (vector)->contents, tmp);
+  SAFE_FREE ();
   UNGCPRO;
 }
 
@@ -3289,7 +3286,6 @@
   if (encoded_length < 0)
     {
       /* The encoding wasn't possible. */
-      SAFE_FREE ();
       error ("Multibyte character in data for base64 encoding");
     }
 
@@ -3434,7 +3430,6 @@
   if (decoded_length < 0)
     {
       /* The decoding wasn't possible. */
-      SAFE_FREE ();
       error ("Invalid base64 data");
     }
 
@@ -4581,12 +4576,12 @@
 {
   Lisp_Object test, size, rehash_size, rehash_threshold, weak;
   struct hash_table_test testdesc;
-  char *used;
   ptrdiff_t i;
+  USE_SAFE_ALLOCA;
 
   /* The vector `used' is used to keep track of arguments that
      have been consumed.  */
-  used = alloca (nargs * sizeof *used);
+  char *used = SAFE_ALLOCA (nargs * sizeof *used);
   memset (used, 0, nargs * sizeof *used);
 
   /* See if there's a `:test TEST' among the arguments.  */
@@ -4653,6 +4648,7 @@
     if (!used[i])
       signal_error ("Invalid argument list", args[i]);
 
+  SAFE_FREE ();
   return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak);
 }
 

=== modified file 'src/font.c'
--- a/src/font.c        2014-07-26 13:17:25 +0000
+++ b/src/font.c        2014-09-07 07:04:01 +0000
@@ -1299,6 +1299,9 @@
 
   val = AREF (font, FONT_SIZE_INDEX);
   eassert (NUMBERP (val) || NILP (val));
+  char font_size_index_buf[sizeof "-*"
+                          + MAX (INT_STRLEN_BOUND (EMACS_INT),
+                                 1 + DBL_MAX_10_EXP + 1)];
   if (INTEGERP (val))
     {
       EMACS_INT v = XINT (val);
@@ -1306,8 +1309,7 @@
        v = pixel_size;
       if (v > 0)
        {
-         f[XLFD_PIXEL_INDEX] = p =
-           alloca (sizeof "-*" + INT_STRLEN_BOUND (EMACS_INT));
+         f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
          sprintf (p, "%"pI"d-*", v);
        }
       else
@@ -1316,21 +1318,22 @@
   else if (FLOATP (val))
     {
       double v = XFLOAT_DATA (val) * 10;
-      f[XLFD_PIXEL_INDEX] = p = alloca (sizeof "*-" + 1 + DBL_MAX_10_EXP + 1);
+      f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
       sprintf (p, "*-%.0f", v);
     }
   else
     f[XLFD_PIXEL_INDEX] = "*-*";
 
+  char dpi_index_buf[sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)];
   if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
     {
       EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX));
-      f[XLFD_RESX_INDEX] = p =
-       alloca (sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT));
+      f[XLFD_RESX_INDEX] = p = dpi_index_buf;
       sprintf (p, "%"pI"d-%"pI"d", v, v);
     }
   else
     f[XLFD_RESX_INDEX] = "*-*";
+
   if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
     {
       EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX));
@@ -1342,13 +1345,16 @@
     }
   else
     f[XLFD_SPACING_INDEX] = "*";
+
+  char avgwidth_index_buf[INT_BUFSIZE_BOUND (EMACS_INT)];
   if (INTEGERP (AREF (font,  FONT_AVGWIDTH_INDEX)))
     {
-      f[XLFD_AVGWIDTH_INDEX] = p = alloca (INT_BUFSIZE_BOUND (EMACS_INT));
+      f[XLFD_AVGWIDTH_INDEX] = p = avgwidth_index_buf;
       sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX)));
     }
   else
     f[XLFD_AVGWIDTH_INDEX] = "*";
+
   len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
                  f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
                  f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
@@ -2185,13 +2191,17 @@
 static Lisp_Object
 font_vconcat_entity_vectors (Lisp_Object list)
 {
-  int nargs = XINT (Flength (list));
-  Lisp_Object *args = alloca (word_size * nargs);
-  int i;
+  EMACS_INT nargs = XFASTINT (Flength (list));
+  Lisp_Object *args;
+  USE_SAFE_ALLOCA;
+  SAFE_ALLOCA_LISP (args, nargs);
+  ptrdiff_t i;
 
   for (i = 0; i < nargs; i++, list = XCDR (list))
     args[i] = XCAR (list);
-  return Fvconcat (nargs, args);
+  Lisp_Object result = Fvconcat (nargs, args);
+  SAFE_FREE ();
+  return result;
 }
 
 
@@ -3219,9 +3229,10 @@
       val = attrs[LFACE_FAMILY_INDEX];
       val = font_intern_prop (SSDATA (val), SBYTES (val), 1);
     }
+  Lisp_Object familybuf[3];
   if (NILP (val))
     {
-      family = alloca ((sizeof family[0]) * 2);
+      family = familybuf;
       family[0] = Qnil;
       family[1] = zero_vector; /* terminator.  */
     }
@@ -3242,7 +3253,7 @@
        }
       else
        {
-         family = alloca ((sizeof family[0]) * 3);
+         family = familybuf;
          i = 0;
          family[i++] = val;
          if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
@@ -3529,8 +3540,9 @@
       struct font_driver_list **list_table, **next;
       Lisp_Object tail;
       int i;
+      USE_SAFE_ALLOCA;
 
-      list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1));
+      SAFE_NALLOCA (list_table, 1, num_font_drivers + 1);
       for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
        {
          for (list = f->font_driver_list; list; list = list->next)
@@ -3551,6 +3563,7 @@
          next = &(*next)->next;
        }
       *next = NULL;
+      SAFE_FREE ();
 
       if (! f->font_driver_list->on)
        { /* None of the drivers is enabled: enable them all.

=== modified file 'src/fontset.c'
--- a/src/fontset.c     2014-08-11 00:59:34 +0000
+++ b/src/fontset.c     2014-09-07 07:04:01 +0000
@@ -1079,10 +1079,11 @@
       /* If PATTERN is not full XLFD we convert "*" to ".*".  Otherwise
         we convert "*" to "[^-]*" which is much faster in regular
         expression matching.  */
-      if (ndashes < 14)
-       p1 = regex = alloca (SBYTES (pattern) + 2 * nstars + 2 * nescs + 1);
-      else
-       p1 = regex = alloca (SBYTES (pattern) + 5 * nstars + 2 * nescs + 1);
+      ptrdiff_t regexsize = (SBYTES (pattern)
+                            + (ndashes < 14 ? 2 : 5) * nstars
+                            + 2 * nescs + 1);
+      USE_SAFE_ALLOCA;
+      p1 = regex = SAFE_ALLOCA (regexsize);
 
       *p1++ = '^';
       for (p0 = SDATA (pattern); *p0; p0++)
@@ -1110,6 +1111,7 @@
 
       Vcached_fontset_data = Fcons (build_string (SSDATA (pattern)),
                                    build_string ((char *) regex));
+      SAFE_FREE ();
     }
 
   return CACHED_FONTSET_REGEX;
@@ -1892,7 +1894,9 @@
 
   /* Recode fontsets realized on FRAME from the base fontset FONTSET
      in the table `realized'.  */
-  realized[0] = alloca (word_size * ASIZE (Vfontset_table));
+  USE_SAFE_ALLOCA;
+  SAFE_ALLOCA_LISP (realized[0], 2 * ASIZE (Vfontset_table));
+  realized[1] = realized[0] + ASIZE (Vfontset_table);
   for (i = j = 0; i < ASIZE (Vfontset_table); i++)
     {
       elt = FONTSET_FROM_ID (i);
@@ -1903,7 +1907,6 @@
     }
   realized[0][j] = Qnil;
 
-  realized[1] = alloca (word_size * ASIZE (Vfontset_table));
   for (i = j = 0; ! NILP (realized[0][i]); i++)
     {
       elt = FONTSET_DEFAULT (realized[0][i]);
@@ -1995,6 +1998,7 @@
        break;
     }
 
+  SAFE_FREE ();
   return tables[0];
 }
 

=== modified file 'src/frame.c'
--- a/src/frame.c       2014-09-03 15:10:29 +0000
+++ b/src/frame.c       2014-09-07 07:04:01 +0000
@@ -994,22 +994,24 @@
     {
       char *name = 0, *type = 0;
       Lisp_Object tty, tty_type;
+      USE_SAFE_ALLOCA;
 
       tty = get_future_frame_param
         (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
                        ? FRAME_TTY (XFRAME (selected_frame))->name
                        : NULL));
       if (!NILP (tty))
-       name = xlispstrdupa (tty);
+       SAFE_ALLOCA_STRING (name, tty);
 
       tty_type = get_future_frame_param
         (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
                             ? FRAME_TTY (XFRAME (selected_frame))->type
                             : NULL));
       if (!NILP (tty_type))
-       type = xlispstrdupa (tty_type);
+       SAFE_ALLOCA_STRING (type, tty_type);
 
       t = init_tty (name, type, 0); /* Errors are not fatal.  */
+      SAFE_FREE ();
     }
 
   f = make_terminal_frame (t);
@@ -3017,14 +3019,14 @@
 #ifdef HAVE_X_WINDOWS
   bool icon_left_no_change = 0, icon_top_no_change = 0;
 #endif
-  struct gcpro gcpro1, gcpro2;
 
   i = 0;
   for (tail = alist; CONSP (tail); tail = XCDR (tail))
     i++;
 
-  parms = alloca (i * sizeof *parms);
-  values = alloca (i * sizeof *values);
+  USE_SAFE_ALLOCA;
+  SAFE_ALLOCA_LISP (parms, 2 * i);
+  values = parms + i;
 
   /* Extract parm names and values into those vectors.  */
 
@@ -3041,10 +3043,6 @@
   /* TAIL and ALIST are not used again below here.  */
   alist = tail = Qnil;
 
-  GCPRO2 (*parms, *values);
-  gcpro1.nvars = i;
-  gcpro2.nvars = i;
-
   /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
      because their values appear in VALUES and strings are not valid.  */
   top = left = Qunbound;
@@ -3273,7 +3271,7 @@
 #endif /* HAVE_X_WINDOWS */
   }
 
-  UNGCPRO;
+  SAFE_FREE ();
 }
 
 
@@ -4010,10 +4008,6 @@
 static Lisp_Object
 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, 
Lisp_Object component, Lisp_Object subclass)
 {
-  register char *value;
-  char *name_key;
-  char *class_key;
-
   CHECK_STRING (attribute);
   CHECK_STRING (class);
 
@@ -4028,17 +4022,20 @@
 
   /* Allocate space for the components, the dots which separate them,
      and the final '\0'.  Make them big enough for the worst case.  */
-  name_key = alloca (SBYTES (Vx_resource_name)
-                    + (STRINGP (component)
-                       ? SBYTES (component) : 0)
-                    + SBYTES (attribute)
-                    + 3);
+  ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
+                           + (STRINGP (component)
+                              ? SBYTES (component) : 0)
+                           + SBYTES (attribute)
+                           + 3);
 
-  class_key = alloca (SBYTES (Vx_resource_class)
-                     + SBYTES (class)
-                     + (STRINGP (subclass)
-                        ? SBYTES (subclass) : 0)
-                     + 3);
+  ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
+                            + SBYTES (class)
+                            + (STRINGP (subclass)
+                               ? SBYTES (subclass) : 0)
+                            + 3);
+  USE_SAFE_ALLOCA;
+  char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
+  char *class_key = name_key + name_keysize;
 
   /* Start with emacs.FRAMENAME for the name (the specific one)
      and with `Emacs' for the class key (the general one).  */
@@ -4060,7 +4057,8 @@
   strcat (name_key, ".");
   strcat (name_key, SSDATA (attribute));
 
-  value = x_get_string_resource (rdb, name_key, class_key);
+  char *value = x_get_string_resource (rdb, name_key, class_key);
+  SAFE_FREE();
 
   if (value && *value)
     return build_string (value);
@@ -4112,8 +4110,10 @@
 
   /* Allocate space for the components, the dots which separate them,
      and the final '\0'.  */
-  char *name_key = SAFE_ALLOCA (invocation_namelen + strlen (attribute) + 2);
-  char *class_key = alloca ((sizeof (EMACS_CLASS) - 1) + strlen (class) + 2);
+  ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
+  ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
+  char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
+  char *class_key = name_key + name_keysize;
 
   esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
   sprintf (class_key, "%s.%s", EMACS_CLASS, class);

=== modified file 'src/ftfont.c'
--- a/src/ftfont.c      2014-08-25 07:00:42 +0000
+++ b/src/ftfont.c      2014-09-07 07:04:01 +0000
@@ -24,6 +24,8 @@
 #include <fontconfig/fontconfig.h>
 #include <fontconfig/fcfreetype.h>
 
+#include <c-strcase.h>
+
 #include "lisp.h"
 #include "dispextern.h"
 #include "frame.h"
@@ -140,6 +142,12 @@
     { NULL }
   };
 
+static bool
+matching_prefix (char const *str, ptrdiff_t len, char const *pat)
+{
+  return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0;
+}
+
 /* Dirty hack for handing ADSTYLE property.
 
    Fontconfig (actually the underlying FreeType) gives such ADSTYLE
@@ -171,18 +179,10 @@
     return Qnil;
   str = (char *) fcstr;
   for (end = str; *end && *end != ' '; end++);
-  if (*end)
-    {
-      char *newstr = alloca (end - str + 1);
-      memcpy (newstr, str, end - str);
-      newstr[end - str] = '\0';
-      end = newstr + (end - str);
-      str = newstr;
-    }
-  if (xstrcasecmp (str, "Regular") == 0
-      || xstrcasecmp (str, "Bold") == 0
-      || xstrcasecmp (str, "Oblique") == 0
-      || xstrcasecmp (str, "Italic") == 0)
+  if (matching_prefix (str, end - str, "Regular")
+      || matching_prefix (str, end - str, "Bold")
+      || matching_prefix (str, end - str, "Oblique")
+      || matching_prefix (str, end - str, "Italic"))
     return Qnil;
   adstyle = font_intern_prop (str, end - str, 1);
   if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
@@ -573,7 +573,8 @@
 ftfont_get_charset (Lisp_Object registry)
 {
   char *str = SSDATA (SYMBOL_NAME (registry));
-  char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
+  USE_SAFE_ALLOCA;
+  char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
   Lisp_Object regexp;
   int i, j;
 
@@ -589,6 +590,7 @@
     }
   re[j] = '\0';
   regexp = make_unibyte_string (re, j);
+  SAFE_FREE ();
   for (i = 0; fc_charset_table[i].name; i++)
     if (fast_c_string_match_ignore_case
        (regexp, fc_charset_table[i].name,
@@ -1688,7 +1690,8 @@
        else if (! otf)
          return 0;
        for (n = 1; spec->features[i][n]; n++);
-       tags = alloca (sizeof (OTF_Tag) * n);
+       USE_SAFE_ALLOCA;
+       SAFE_NALLOCA (tags, 1, n);
        for (n = 0, negative = 0; spec->features[i][n]; n++)
          {
            if (spec->features[i][n] == 0xFFFFFFFF)
@@ -1698,16 +1701,17 @@
            else
              tags[n] = spec->features[i][n];
          }
-#ifdef M17N_FLT_USE_NEW_FEATURE
-       if (OTF_check_features (otf, i == 0, spec->script, spec->langsys,
-                               tags, n - negative) != 1)
-         return 0;
-#else  /* not M17N_FLT_USE_NEW_FEATURE */
-       if (n - negative > 0
-           && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
-                                  tags, n - negative) != 1)
-         return 0;
-#endif /* not M17N_FLT_USE_NEW_FEATURE */
+       bool passed = true;
+#ifndef M17N_FLT_USE_NEW_FEATURE
+       passed = n - negative > 0;
+#endif
+       if (passed)
+         passed = (OTF_check_features (otf, i == 0, spec->script,
+                                       spec->langsys, tags, n - negative)
+                   != 1);
+       SAFE_FREE ();
+       if (passed)
+         return 0;
       }
   return 1;
 #undef FEATURE_NONE
@@ -1799,11 +1803,15 @@
   if (len == 0)
     return from;
   OTF_tag_name (spec->script, script);
+
+  char langsysbuf[5];
   if (spec->langsys)
     {
-      langsys = alloca (5);
+      langsys = langsysbuf;
       OTF_tag_name (spec->langsys, langsys);
     }
+
+  USE_SAFE_ALLOCA;
   for (i = 0; i < 2; i++)
     {
       char *p;
@@ -1811,10 +1819,11 @@
       if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
        {
          for (j = 0; spec->features[i][j]; j++);
+         SAFE_NALLOCA (p, 6, j);
          if (i == 0)
-           p = gsub_features = alloca (6 * j);
+           gsub_features = p;
          else
-           p = gpos_features = alloca (6 * j);
+           gpos_features = p;
          for (j = 0; spec->features[i][j]; j++)
            {
              if (spec->features[i][j] == 0xFFFFFFFF)
@@ -1846,7 +1855,10 @@
                                   gsub_features) < 0)
        goto simple_copy;
       if (out->allocated < out->used + otf_gstring.used)
-       return -2;
+       {
+         SAFE_FREE ();
+         return -2;
+       }
       features = otf->gsub->FeatureList.Feature;
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
        {
@@ -1935,7 +1947,10 @@
   else if (out)
     {
       if (out->allocated < out->used + len)
-       return -2;
+       {
+         SAFE_FREE ();
+         return -2;
+       }
       for (i = 0; i < len; i++)
        out->glyphs[out->used++] = in->glyphs[from + i];
     }
@@ -1947,7 +1962,10 @@
 
       if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
                                   gpos_features) < 0)
-       return to;
+       {
+         SAFE_FREE ();
+         return to;
+       }
       features = otf->gpos->FeatureList.Feature;
       x_ppem = ft_face->size->metrics.x_ppem;
       y_ppem = ft_face->size->metrics.y_ppem;
@@ -2069,7 +2087,10 @@
     {
       if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
                                   gpos_features) < 0)
-       return to;
+       {
+         SAFE_FREE ();
+         return to;
+       }
       features = otf->gpos->FeatureList.Feature;
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
           i++, otfg++)
@@ -2089,9 +2110,11 @@
              }
          }
     }
+  SAFE_FREE ();
   return to;
 
  simple_copy:
+  SAFE_FREE ();
   if (! out)
     return to;
   if (out->allocated < out->used + len)
@@ -2129,11 +2152,15 @@
   if (len == 0)
     return from;
   OTF_tag_name (spec->script, script);
+
+  char langsysbuf[5];
   if (spec->langsys)
     {
-      langsys = alloca (5);
+      langsys = langsysbuf;
       OTF_tag_name (spec->langsys, langsys);
     }
+
+  USE_SAFE_ALLOCA;
   for (i = 0; i < 2; i++)
     {
       char *p;
@@ -2141,10 +2168,11 @@
       if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
        {
          for (j = 0; spec->features[i][j]; j++);
+         SAFE_NALLOCA (p, 6, j);
          if (i == 0)
-           p = gsub_features = alloca (6 * j);
+           gsub_features = p;
          else
-           p = gpos_features = alloca (6 * j);
+           gpos_features = p;
          for (j = 0; spec->features[i][j]; j++)
            {
              if (spec->features[i][j] == 0xFFFFFFFF)
@@ -2176,7 +2204,10 @@
          < 0)
        goto simple_copy;
       if (out->allocated < out->used + otf_gstring.used)
-       return -2;
+       {
+         SAFE_FREE ();
+         return -2;
+       }
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
        {
          MFLTGlyph *g;
@@ -2227,7 +2258,10 @@
   else
     {
       if (out->allocated < out->used + len)
-       return -2;
+       {
+         SAFE_FREE ();
+         return -2;
+       }
       for (i = 0; i < len; i++)
        out->glyphs[out->used++] = in->glyphs[from + i];
     }
@@ -2239,7 +2273,10 @@
 
       if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
          < 0)
-       return to;
+       {
+         SAFE_FREE ();
+         return to;
+       }
 
       x_ppem = ft_face->size->metrics.x_ppem;
       y_ppem = ft_face->size->metrics.y_ppem;
@@ -2349,9 +2386,11 @@
            base = g;
        }
     }
+  SAFE_FREE ();
   return to;
 
  simple_copy:
+  SAFE_FREE ();
   if (out->allocated < out->used + len)
     return -2;
   font->get_metrics (font, in, from, to);

=== modified file 'src/ftxfont.c'
--- a/src/ftxfont.c     2014-07-03 12:20:00 +0000
+++ b/src/ftxfont.c     2014-09-07 07:04:01 +0000
@@ -271,10 +271,11 @@
 
   n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0;
 
+  USE_SAFE_ALLOCA;
+  SAFE_NALLOCA (code, 1, len);
   block_input ();
   if (with_background)
     ftxfont_draw_background (f, font, s->gc, x, y, s->width);
-  code = alloca (sizeof (unsigned) * len);
   for (i = 0; i < len; i++)
     code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
               | XCHAR2B_BYTE2 (s->char2b + from + i));
@@ -322,6 +323,7 @@
     }
 
   unblock_input ();
+  SAFE_FREE ();
 
   return len;
 }

=== modified file 'src/image.c'
--- a/src/image.c       2014-07-07 23:25:13 +0000
+++ b/src/image.c       2014-09-07 07:04:01 +0000
@@ -3037,13 +3037,16 @@
                                     + SBYTES (data)));
       else
        {
+         USE_SAFE_ALLOCA;
+
          if (VECTORP (data))
            {
              int i;
              char *p;
              int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
 
-             p = bits = alloca (nbytes * img->height);
+             SAFE_NALLOCA (bits, nbytes, img->height);
+             p = bits;
              for (i = 0; i < img->height; ++i, p += nbytes)
                {
                  Lisp_Object line = AREF (data, i);
@@ -3064,9 +3067,8 @@
             int nbytes, i;
             /* Windows mono bitmaps are reversed compared with X.  */
             invertedBits = bits;
-            nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
-              * img->height;
-            bits = alloca (nbytes);
+            nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+            SAFE_NALLOCA (bits, nbytes, img->height);
             for (i = 0; i < nbytes; i++)
               bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
           }
@@ -3088,6 +3090,8 @@
                           img->spec, Qnil);
              x_clear_image (f, img);
            }
+
+         SAFE_FREE ();
        }
     }
 
@@ -3494,6 +3498,8 @@
   int rc;
   XpmAttributes attrs;
   Lisp_Object specified_file, color_symbols;
+  USE_SAFE_ALLOCA;
+
 #ifdef HAVE_NTGUI
   HDC hdc;
   xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
@@ -3536,7 +3542,7 @@
     {
       Lisp_Object tail;
       XpmColorSymbol *xpm_syms;
-      int i, size;
+      ptrdiff_t i, size;
 
       attrs.valuemask |= XpmColorSymbols;
 
@@ -3546,8 +3552,8 @@
        ++attrs.numsymbols;
 
       /* Allocate an XpmColorSymbol array.  */
+      SAFE_NALLOCA (xpm_syms, 1, attrs.numsymbols);
       size = attrs.numsymbols * sizeof *xpm_syms;
-      xpm_syms = alloca (size);
       memset (xpm_syms, 0, size);
       attrs.colorsymbols = xpm_syms;
 
@@ -3569,17 +3575,11 @@
          name = XCAR (XCAR (tail));
          color = XCDR (XCAR (tail));
          if (STRINGP (name))
-           {
-             xpm_syms[i].name = alloca (SCHARS (name) + 1);
-             strcpy (xpm_syms[i].name, SSDATA (name));
-           }
+           SAFE_ALLOCA_STRING (xpm_syms[i].name, name);
          else
            xpm_syms[i].name = empty_string;
          if (STRINGP (color))
-           {
-             xpm_syms[i].value = alloca (SCHARS (color) + 1);
-             strcpy (xpm_syms[i].value, SSDATA (color));
-           }
+           SAFE_ALLOCA_STRING (xpm_syms[i].value, color);
          else
            xpm_syms[i].value = empty_string;
        }
@@ -3610,6 +3610,7 @@
 #ifdef ALLOC_XPM_COLORS
          xpm_free_color_cache ();
 #endif
+         SAFE_FREE ();
          return 0;
        }
 
@@ -3640,6 +3641,7 @@
 #ifdef ALLOC_XPM_COLORS
          xpm_free_color_cache ();
 #endif
+         SAFE_FREE ();
          return 0;
        }
 #ifdef HAVE_NTGUI
@@ -3782,6 +3784,7 @@
 #ifdef ALLOC_XPM_COLORS
   xpm_free_color_cache ();
 #endif
+  SAFE_FREE ();
   return rc == XpmSuccess;
 }
 
@@ -6580,6 +6583,7 @@
      colors generated, and mgr->cinfo.colormap is a two-dimensional array
      of color indices in the range 0..mgr->cinfo.actual_number_of_colors.
      No more than 255 colors will be generated.  */
+  USE_SAFE_ALLOCA;
   {
     int i, ir, ig, ib;
 
@@ -6595,7 +6599,7 @@
        a default color, and we don't have to care about which colors
        can be freed safely, and which can't.  */
     init_color_table ();
-    colors = alloca (mgr->cinfo.actual_number_of_colors * sizeof *colors);
+    SAFE_NALLOCA (colors, 1, mgr->cinfo.actual_number_of_colors);
 
     for (i = 0; i < mgr->cinfo.actual_number_of_colors; ++i)
       {
@@ -6638,6 +6642,7 @@
 
   /* Put ximg into the image.  */
   image_put_x_image (f, img, ximg, 0);
+  SAFE_FREE ();
   return 1;
 }
 

=== modified file 'src/keyboard.c'
--- a/src/keyboard.c    2014-08-27 10:51:21 +0000
+++ b/src/keyboard.c    2014-09-07 07:04:01 +0000
@@ -500,10 +500,12 @@
 static void
 echo_add_key (Lisp_Object c)
 {
-  int size = KEY_DESCRIPTION_SIZE + 100;
-  char *buffer = alloca (size);
+  char initbuf[KEY_DESCRIPTION_SIZE + 100];
+  ptrdiff_t size = sizeof initbuf;
+  char *buffer = initbuf;
   char *ptr = buffer;
   Lisp_Object echo_string;
+  USE_SAFE_ALLOCA;
 
   echo_string = KVAR (current_kboard, echo_string);
 
@@ -515,13 +517,13 @@
   else if (SYMBOLP (c))
     {
       Lisp_Object name = SYMBOL_NAME (c);
-      int nbytes = SBYTES (name);
+      ptrdiff_t nbytes = SBYTES (name);
 
       if (size - (ptr - buffer) < nbytes)
        {
-         int offset = ptr - buffer;
+         ptrdiff_t offset = ptr - buffer;
          size = max (2 * size, size + nbytes);
-         buffer = alloca (size);
+         buffer = SAFE_ALLOCA (size);
          ptr = buffer + offset;
        }
 
@@ -532,14 +534,14 @@
   if ((NILP (echo_string) || SCHARS (echo_string) == 0)
       && help_char_p (c))
     {
-      const char *text = " (Type ? for further options)";
-      int len = strlen (text);
+      static const char text[] = " (Type ? for further options)";
+      int len = sizeof text - 1;
 
       if (size - (ptr - buffer) < len)
        {
-         int offset = ptr - buffer;
+         ptrdiff_t offset = ptr - buffer;
          size += len;
-         buffer = alloca (size);
+         buffer = SAFE_ALLOCA (size);
          ptr = buffer + offset;
        }
 
@@ -572,6 +574,7 @@
   kset_echo_string
     (current_kboard,
      concat2 (echo_string, make_string (buffer, ptr - buffer)));
+  SAFE_FREE ();
 }
 
 /* Add C to the echo string, if echoing is going on.  C can be a
@@ -1147,7 +1150,7 @@
 Lisp_Object
 command_loop (void)
 {
-#ifdef HAVE_STACK_OVERFLOW_HANDLING  
+#ifdef HAVE_STACK_OVERFLOW_HANDLING
   /* At least on GNU/Linux, saving signal mask is important here.  */
   if (sigsetjmp (return_to_command_loop, 1) != 0)
     {
@@ -2351,14 +2354,15 @@
            { /* An encoded byte sequence, let's try to decode it.  */
              struct coding_system *coding
                = TERMINAL_KEYBOARD_CODING (terminal);
-             unsigned char *src = alloca (n);
+             unsigned char src[MAX_ENCODED_BYTES];
+             unsigned char dest[4 * sizeof src];
              int i;
              for (i = 0; i < n; i++)
                src[i] = XINT (events[i]);
              if (meta_key != 2)
                for (i = 0; i < n; i++)
                  src[i] &= ~0x80;
-             coding->destination = alloca (n * 4);
+             coding->destination = dest;
              coding->dst_bytes = n * 4;
              decode_coding_c_string (coding, src, n, Qnil);
              eassert (coding->produced_char <= n);
@@ -7434,11 +7438,14 @@
      in the current keymaps, or nil where it is not a prefix.  */
   Lisp_Object *maps;
 
+  Lisp_Object mapsbuf[3];
   Lisp_Object def, tail;
 
   ptrdiff_t mapno;
   Lisp_Object oquit;
 
+  USE_SAFE_ALLOCA;
+
   /* In order to build the menus, we need to call the keymap
      accessors.  They all call QUIT.  But this function is called
      during redisplay, during which a quit is fatal.  So inhibit
@@ -7467,7 +7474,7 @@
        && !NILP (Voverriding_local_map))
       {
        /* Yes, use them (if non-nil) as well as the global map.  */
-       maps = alloca (3 * sizeof (maps[0]));
+       maps = mapsbuf;
        nmaps = 0;
        if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map)))
          maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map);
@@ -7484,7 +7491,7 @@
        Lisp_Object tem;
        ptrdiff_t nminor;
        nminor = current_minor_maps (NULL, &tmaps);
-       maps = alloca ((nminor + 4) * sizeof *maps);
+       SAFE_NALLOCA (maps, 1, nminor + 4);
        nmaps = 0;
        tem = KVAR (current_kboard, Voverriding_terminal_local_map);
        if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag))
@@ -7556,6 +7563,7 @@
   }
 
   Vinhibit_quit = oquit;
+  SAFE_FREE ();
   return menu_bar_items_vector;
 }
 
@@ -7992,9 +8000,11 @@
 tool_bar_items (Lisp_Object reuse, int *nitems)
 {
   Lisp_Object *maps;
+  Lisp_Object mapsbuf[3];
   ptrdiff_t nmaps, i;
   Lisp_Object oquit;
   Lisp_Object *tmaps;
+  USE_SAFE_ALLOCA;
 
   *nitems = 0;
 
@@ -8018,7 +8028,7 @@
       && !NILP (Voverriding_local_map))
     {
       /* Yes, use them (if non-nil) as well as the global map.  */
-      maps = alloca (3 * sizeof *maps);
+      maps = mapsbuf;
       nmaps = 0;
       if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map)))
        maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map);
@@ -8035,7 +8045,7 @@
       Lisp_Object tem;
       ptrdiff_t nminor;
       nminor = current_minor_maps (NULL, &tmaps);
-      maps = alloca ((nminor + 4) * sizeof *maps);
+      SAFE_NALLOCA (maps, 1, nminor + 4);
       nmaps = 0;
       tem = KVAR (current_kboard, Voverriding_terminal_local_map);
       if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag))
@@ -8064,6 +8074,7 @@
 
   Vinhibit_quit = oquit;
   *nitems = ntool_bar_items / TOOL_BAR_ITEM_NSLOTS;
+  SAFE_FREE ();
   return tool_bar_items_vector;
 }
 

=== modified file 'src/keymap.c'
--- a/src/keymap.c      2014-07-14 04:44:01 +0000
+++ b/src/keymap.c      2014-09-07 07:04:01 +0000
@@ -2883,13 +2883,14 @@
          if (!SYMBOLP (modes[i]))
            emacs_abort ();
 
-         p = title = alloca (42 + SCHARS (SYMBOL_NAME (modes[i])));
+         USE_SAFE_ALLOCA;
+         p = title = SAFE_ALLOCA (42 + SBYTES (SYMBOL_NAME (modes[i])));
          *p++ = '\f';
          *p++ = '\n';
          *p++ = '`';
          memcpy (p, SDATA (SYMBOL_NAME (modes[i])),
-                 SCHARS (SYMBOL_NAME (modes[i])));
-         p += SCHARS (SYMBOL_NAME (modes[i]));
+                 SBYTES (SYMBOL_NAME (modes[i])));
+         p += SBYTES (SYMBOL_NAME (modes[i]));
          *p++ = '\'';
          memcpy (p, " Minor Mode Bindings", strlen (" Minor Mode Bindings"));
          p += strlen (" Minor Mode Bindings");
@@ -2898,6 +2899,7 @@
          describe_map_tree (maps[i], 1, shadow, prefix,
                             title, nomenu, 0, 0, 0);
          shadow = Fcons (maps[i], shadow);
+         SAFE_FREE ();
        }
 
       start1 = get_local_map (BUF_PT (XBUFFER (buffer)),
@@ -3184,10 +3186,10 @@
 
   /* These accumulate the values from sparse keymap bindings,
      so we can sort them and handle them in order.  */
-  int length_needed = 0;
+  ptrdiff_t length_needed = 0;
   struct describe_map_elt *vect;
-  int slots_used = 0;
-  int i;
+  ptrdiff_t slots_used = 0;
+  ptrdiff_t i;
 
   suppress = Qnil;
 
@@ -3207,7 +3209,8 @@
   for (tail = map; CONSP (tail); tail = XCDR (tail))
     length_needed++;
 
-  vect = alloca (length_needed * sizeof *vect);
+  USE_SAFE_ALLOCA;
+  SAFE_NALLOCA (vect, 1, length_needed);
 
   for (tail = map; CONSP (tail); tail = XCDR (tail))
     {
@@ -3350,6 +3353,7 @@
        }
     }
 
+  SAFE_FREE ();
   UNGCPRO;
 }
 

=== modified file 'src/lisp.h'
--- a/src/lisp.h        2014-09-02 18:05:00 +0000
+++ b/src/lisp.h        2014-09-07 07:04:01 +0000
@@ -4451,12 +4451,6 @@
   return egetenv_internal (var, strlen (var));
 }
 
-/* Copy Lisp string to temporary (allocated on stack) C string.  */
-
-#define xlispstrdupa(string)                   \
-  memcpy (alloca (SBYTES (string) + 1),                \
-         SSDATA (string), SBYTES (string) + 1)
-
 /* Set up the name of the machine we're running on.  */
 extern void init_system_name (void);
 
@@ -4484,7 +4478,7 @@
 
 /* SAFE_ALLOCA allocates a simple buffer.  */
 
-#define SAFE_ALLOCA(size) ((size) < MAX_ALLOCA \
+#define SAFE_ALLOCA(size) ((size) <= MAX_ALLOCA        \
                           ? alloca (size)      \
                           : (sa_must_free = true, record_xmalloc (size)))
 
@@ -4504,6 +4498,14 @@
       }                                                                 \
   } while (false)
 
+/* SAFE_ALLOCA_STRING allocates a C copy of a Lisp string.  */
+
+#define SAFE_ALLOCA_STRING(ptr, string)                        \
+  do {                                                 \
+    (ptr) = SAFE_ALLOCA (SBYTES (string) + 1);         \
+    memcpy (ptr, SDATA (string), SBYTES (string) + 1); \
+  } while (false)
+
 /* SAFE_FREE frees xmalloced memory and enables GC as needed.  */
 
 #define SAFE_FREE()                    \
@@ -4519,9 +4521,9 @@
 
 #define SAFE_ALLOCA_LISP(buf, nelt)                           \
   do {                                                        \
-    if ((nelt) < MAX_ALLOCA / word_size)                      \
+    if ((nelt) <= MAX_ALLOCA / word_size)                     \
       (buf) = alloca ((nelt) * word_size);                    \
-    else if ((nelt) < min (PTRDIFF_MAX, SIZE_MAX) / word_size) \
+    else if ((nelt) <= min (PTRDIFF_MAX, SIZE_MAX) / word_size) \
       {                                                               \
        Lisp_Object arg_;                                      \
        (buf) = xmalloc ((nelt) * word_size);                  \

=== modified file 'src/lread.c'
--- a/src/lread.c       2014-09-01 16:05:43 +0000
+++ b/src/lread.c       2014-09-07 07:04:01 +0000
@@ -1473,6 +1473,7 @@
   ptrdiff_t max_suffix_len = 0;
   int last_errno = ENOENT;
   int save_fd = -1;
+  USE_SAFE_ALLOCA;
 
   /* The last-modified time of the newest matching file found.
      Initialize it to something less than all valid timestamps.  */
@@ -1513,7 +1514,10 @@
         this path element/specified file name and any possible suffix.  */
       want_length = max_suffix_len + SBYTES (filename);
       if (fn_size <= want_length)
-       fn = alloca (fn_size = 100 + want_length);
+       {
+         fn_size = 100 + want_length;
+         fn = SAFE_ALLOCA (fn_size);
+       }
 
       /* Loop over suffixes.  */
       for (tail = NILP (suffixes) ? list1 (empty_unibyte_string) : suffixes;
@@ -1579,6 +1583,7 @@
                   /* We succeeded; return this descriptor and filename.  */
                   if (storeptr)
                     *storeptr = string;
+                 SAFE_FREE ();
                   UNGCPRO;
                   return -2;
                }
@@ -1651,6 +1656,7 @@
                       /* We succeeded; return this descriptor and filename.  */
                       if (storeptr)
                         *storeptr = string;
+                     SAFE_FREE ();
                       UNGCPRO;
                       return fd;
                     }
@@ -1661,6 +1667,7 @@
                 {
                   if (storeptr)
                     *storeptr = save_string;
+                 SAFE_FREE ();
                   UNGCPRO;
                   return save_fd;
                 }
@@ -1670,6 +1677,7 @@
        break;
     }
 
+  SAFE_FREE ();
   UNGCPRO;
   errno = last_errno;
   return -1;

=== modified file 'src/menu.c'
--- a/src/menu.c        2014-08-10 08:26:28 +0000
+++ b/src/menu.c        2014-09-07 07:04:01 +0000
@@ -632,8 +632,9 @@
   widget_value **submenu_stack;
   bool panes_seen = 0;
   struct frame *f = XFRAME (Vmenu_updating_frame);
+  USE_SAFE_ALLOCA;
 
-  submenu_stack = alloca (menu_items_used * sizeof *submenu_stack);
+  SAFE_NALLOCA (submenu_stack, 1, menu_items_used);
   wv = make_widget_value ("menu", NULL, true, Qnil);
   wv->button_type = BUTTON_TYPE_NONE;
   first_wv = wv;
@@ -835,11 +836,12 @@
      that was originally a button, return it by itself.  */
   if (top_level_items && first_wv->contents && first_wv->contents->next == 0)
     {
-      wv = first_wv->contents;
-      xfree (first_wv);
-      return wv;
+      wv = first_wv;
+      first_wv = first_wv->contents;
+      xfree (wv);
     }
 
+  SAFE_FREE ();
   return first_wv;
 }
 
@@ -890,9 +892,10 @@
   Lisp_Object *subprefix_stack;
   int submenu_depth = 0;
   int i;
+  USE_SAFE_ALLOCA;
 
   entry = Qnil;
-  subprefix_stack = alloca (menu_bar_items_used * sizeof *subprefix_stack);
+  SAFE_NALLOCA (subprefix_stack, 1, menu_bar_items_used);
   prefix = Qnil;
   i = 0;
 
@@ -954,11 +957,13 @@
              buf.arg = entry;
              kbd_buffer_store_event (&buf);
 
-             return;
+             break;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
        }
     }
+
+  SAFE_FREE ();
 }
 
 #endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */
@@ -973,10 +978,11 @@
   int i;
   Lisp_Object *subprefix_stack;
   int submenu_depth = 0;
+  USE_SAFE_ALLOCA;
 
   prefix = entry = Qnil;
   i = 0;
-  subprefix_stack = alloca (menu_items_used * word_size);
+  SAFE_ALLOCA_LISP (subprefix_stack, menu_items_used);
 
   while (i < menu_items_used)
     {
@@ -1018,11 +1024,13 @@
                     if (!NILP (subprefix_stack[j]))
                       entry = Fcons (subprefix_stack[j], entry);
                 }
+             SAFE_FREE ();
               return entry;
             }
           i += MENU_ITEMS_ITEM_LENGTH;
         }
     }
+  SAFE_FREE ();
   return Qnil;
 }
 #endif  /* HAVE_NS */

=== modified file 'src/print.c'
--- a/src/print.c       2014-07-17 09:12:51 +0000
+++ b/src/print.c       2014-09-07 07:04:01 +0000
@@ -169,11 +169,13 @@
        if (print_buffer_pos != print_buffer_pos_byte                   \
           && NILP (BVAR (current_buffer, enable_multibyte_characters)))\
         {                                                              \
-          unsigned char *temp = alloca (print_buffer_pos + 1);         \
+          USE_SAFE_ALLOCA;                                             \
+          unsigned char *temp = SAFE_ALLOCA (print_buffer_pos + 1);    \
           copy_text ((unsigned char *) print_buffer, temp,             \
                      print_buffer_pos_byte, 1, 0);                     \
           insert_1_both ((char *) temp, print_buffer_pos,              \
                          print_buffer_pos, 0, 1, 0);                   \
+          SAFE_FREE ();                                                \
         }                                                              \
        else                                                            \
         insert_1_both (print_buffer, print_buffer_pos,                 \

=== modified file 'src/process.c'
--- a/src/process.c     2014-08-09 16:20:29 +0000
+++ b/src/process.c     2014-09-07 07:04:01 +0000
@@ -1386,9 +1386,10 @@
   (ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object buffer, name, program, proc, current_dir, tem;
-  register unsigned char **new_argv;
+  unsigned char **new_argv;
   ptrdiff_t i;
   ptrdiff_t count = SPECPDL_INDEX ();
+  USE_SAFE_ALLOCA;
 
   buffer = args[1];
   if (!NILP (buffer))
@@ -1464,7 +1465,7 @@
     val = Vcoding_system_for_read;
     if (NILP (val))
       {
-       args2 = alloca ((nargs + 1) * sizeof *args2);
+       SAFE_ALLOCA_LISP (args2, nargs + 1);
        args2[0] = Qstart_process;
        for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
        GCPRO2 (proc, current_dir);
@@ -1483,7 +1484,7 @@
       {
        if (EQ (coding_systems, Qt))
          {
-           args2 = alloca ((nargs + 1) * sizeof *args2);
+           SAFE_ALLOCA_LISP (args2, nargs + 1);
            args2[0] = Qstart_process;
            for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
            GCPRO2 (proc, current_dir);
@@ -1578,7 +1579,7 @@
 
       /* Now that everything is encoded we can collect the strings into
         NEW_ARGV.  */
-      new_argv = alloca ((nargs - 1) * sizeof *new_argv);
+      SAFE_NALLOCA (new_argv, 1, nargs - 1);
       new_argv[nargs - 2] = 0;
 
       for (i = nargs - 2; i-- != 0; )
@@ -1592,6 +1593,7 @@
   else
     create_pty (proc);
 
+  SAFE_FREE ();
   return unbind_to (count, proc);
 }
 
@@ -2071,8 +2073,10 @@
           && VECTORP (XCDR (address)))
     {
       struct sockaddr *sa;
+      p = XVECTOR (XCDR (address));
+      if (MAX_ALLOCA - sizeof sa->sa_family < p->header.size)
+       return 0;
       *familyp = XINT (XCAR (address));
-      p = XVECTOR (XCDR (address));
       return p->header.size + sizeof (sa->sa_family);
     }
   return 0;
@@ -4973,18 +4977,17 @@
    for decoding.  */
 
 static int
-read_process_output (Lisp_Object proc, register int channel)
+read_process_output (Lisp_Object proc, int channel)
 {
-  register ssize_t nbytes;
-  char *chars;
-  register struct Lisp_Process *p = XPROCESS (proc);
+  ssize_t nbytes;
+  struct Lisp_Process *p = XPROCESS (proc);
   struct coding_system *coding = proc_decode_coding_system[channel];
   int carryover = p->decoding_carryover;
-  int readmax = 4096;
+  enum { readmax = 4096 };
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object odeactivate;
+  char chars[sizeof coding->carryover + readmax];
 
-  chars = alloca (carryover + readmax);
   if (carryover)
     /* See the comment above.  */
     memcpy (chars, SDATA (p->decoding_buf), carryover);
@@ -6837,7 +6840,7 @@
 {
   FD_SET (fd, &input_wait_mask);
   FD_SET (fd, &non_keyboard_wait_mask);
-  FD_SET (fd, &non_process_wait_mask);  
+  FD_SET (fd, &non_process_wait_mask);
   fd_callback_info[fd].func = timerfd_callback;
   fd_callback_info[fd].data = NULL;
   fd_callback_info[fd].condition |= FOR_READ;

=== modified file 'src/regex.c'
--- a/src/regex.c       2014-07-15 14:04:06 +0000
+++ b/src/regex.c       2014-09-07 07:04:01 +0000
@@ -457,11 +457,17 @@
 
 # endif /* not alloca */
 
-# define REGEX_ALLOCATE alloca
+# ifdef emacs
+#  define REGEX_USE_SAFE_ALLOCA USE_SAFE_ALLOCA
+#  define REGEX_SAFE_FREE() SAFE_FREE ()
+#  define REGEX_ALLOCATE SAFE_ALLOCA
+# else
+#  define REGEX_ALLOCATE alloca
+# endif
 
 /* Assumes a `char *destination' variable.  */
 # define REGEX_REALLOCATE(source, osize, nsize)                                
\
-  (destination = alloca (nsize),                                       \
+  (destination = REGEX_ALLOCATE (nsize),                               \
    memcpy (destination, source, osize))
 
 /* No need to do anything to free, after alloca.  */
@@ -469,6 +475,11 @@
 
 #endif /* not REGEX_MALLOC */
 
+#ifndef REGEX_USE_SAFE_ALLOCA
+# define REGEX_USE_SAFE_ALLOCA ((void) 0)
+# define REGEX_SAFE_FREE() ((void) 0)
+#endif
+
 /* Define how to allocate the failure stack.  */
 
 #if defined REL_ALLOC && defined REGEX_MALLOC
@@ -482,22 +493,10 @@
 
 #else /* not using relocating allocator */
 
-# ifdef REGEX_MALLOC
-
-#  define REGEX_ALLOCATE_STACK malloc
-#  define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
-#  define REGEX_FREE_STACK free
-
-# else /* not REGEX_MALLOC */
-
-#  define REGEX_ALLOCATE_STACK alloca
-
-#  define REGEX_REALLOCATE_STACK(source, osize, nsize)                 \
-   REGEX_REALLOCATE (source, osize, nsize)
-/* No need to explicitly free anything.  */
-#  define REGEX_FREE_STACK(arg) ((void)0)
-
-# endif /* not REGEX_MALLOC */
+# define REGEX_ALLOCATE_STACK(size) REGEX_ALLOCATE (size)
+# define REGEX_REALLOCATE_STACK(source, o, n) REGEX_REALLOCATE (source, o, n)
+# define REGEX_FREE_STACK(ptr) REGEX_FREE (ptr)
+
 #endif /* not using relocating allocator */
 
 
@@ -4579,6 +4578,7 @@
     FREE_VAR (regend);                                                 \
     FREE_VAR (best_regstart);                                          \
     FREE_VAR (best_regend);                                            \
+    REGEX_SAFE_FREE ();                                                        
\
   } while (0)
 #else
 # define FREE_VARIABLES() ((void)0) /* Do nothing!  But inhibit gcc warning.  
*/
@@ -5018,6 +5018,8 @@
 
   DEBUG_PRINT ("\n\nEntering re_match_2.\n");
 
+  REGEX_USE_SAFE_ALLOCA;
+
   INIT_FAIL_STACK ();
 
 #ifdef MATCH_MAY_ALLOCATE

=== modified file 'src/scroll.c'
--- a/src/scroll.c      2014-08-03 12:34:44 +0000
+++ b/src/scroll.c      2014-09-07 07:04:01 +0000
@@ -245,18 +245,20 @@
 {
   struct matrix_elt *p;
   int i, j, k;
+  USE_SAFE_ALLOCA;
 
   /* True if we have set a terminal window with set_terminal_window.  */
   bool terminal_window_p = 0;
 
   /* A queue for line insertions to be done.  */
   struct queue { int count, pos; };
-  struct queue *queue_start
-    = alloca (current_matrix->nrows * sizeof *queue_start);
+  struct queue *queue_start;
+  SAFE_NALLOCA (queue_start, 1, current_matrix->nrows);
   struct queue *queue = queue_start;
 
-  char *retained_p = alloca (window_size * sizeof *retained_p);
-  int *copy_from = alloca (window_size * sizeof *copy_from);
+  char *retained_p = SAFE_ALLOCA (window_size);
+  int *copy_from;
+  SAFE_NALLOCA (copy_from, 1, window_size);
 
   /* Zero means line is empty.  */
   memset (retained_p, 0, window_size * sizeof (char));
@@ -378,6 +380,7 @@
 
   if (terminal_window_p)
     set_terminal_window (frame, 0);
+  SAFE_FREE ();
 }
 
 
@@ -649,10 +652,12 @@
 {
   struct matrix_elt *p;
   int i, j;
+  USE_SAFE_ALLOCA;
 
   /* A queue of deletions and insertions to be performed.  */
   struct alt_queue { int count, pos, window; };
-  struct alt_queue *queue_start = alloca (window_size * sizeof *queue_start);
+  struct alt_queue *queue_start;
+  SAFE_NALLOCA (queue_start, 1, window_size);
   struct alt_queue *queue = queue_start;
 
   /* True if a terminal window has been set with set_terminal_window.  */
@@ -667,11 +672,12 @@
   bool write_follows_p = 1;
 
   /* For each row in the new matrix what row of the old matrix it is.  */
-  int *copy_from = alloca (window_size * sizeof *copy_from);
+  int *copy_from;
+  SAFE_NALLOCA (copy_from, 1, window_size);
 
   /* Non-zero for each row in the new matrix that is retained from the
      old matrix.  Lines not retained are empty.  */
-  char *retained_p = alloca (window_size * sizeof *retained_p);
+  char *retained_p = SAFE_ALLOCA (window_size);
 
   memset (retained_p, 0, window_size * sizeof (char));
 
@@ -787,6 +793,7 @@
 
   if (terminal_window_p)
     set_terminal_window (frame, 0);
+  SAFE_FREE ();
 }
 
 
@@ -796,8 +803,9 @@
             int unchanged_at_bottom, int *draw_cost, int *old_draw_cost,
             unsigned *old_hash, unsigned *new_hash, int free_at_end)
 {
-  struct matrix_elt *matrix
-    = alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix);
+  USE_SAFE_ALLOCA;
+  struct matrix_elt *matrix;
+  SAFE_NALLOCA (matrix, window_size + 1, window_size + 1);
 
   if (FRAME_SCROLL_REGION_OK (frame))
     {
@@ -817,6 +825,8 @@
                     frame->current_matrix, matrix, window_size,
                    unchanged_at_top);
     }
+
+  SAFE_FREE ();
 }
 
 

=== modified file 'src/search.c'
--- a/src/search.c      2014-06-23 04:11:29 +0000
+++ b/src/search.c      2014-09-07 07:04:01 +0000
@@ -1318,6 +1318,7 @@
         translation.  Otherwise set to zero later.  */
       int char_base = -1;
       bool boyer_moore_ok = 1;
+      USE_SAFE_ALLOCA;
 
       /* MULTIBYTE says whether the text to be searched is multibyte.
         We must convert PATTERN to match that, or we will not really
@@ -1335,7 +1336,7 @@
          raw_pattern_size_byte
            = count_size_as_multibyte (SDATA (string),
                                       raw_pattern_size);
-         raw_pattern = alloca (raw_pattern_size_byte + 1);
+         raw_pattern = SAFE_ALLOCA (raw_pattern_size_byte + 1);
          copy_text (SDATA (string), raw_pattern,
                     SCHARS (string), 0, 1);
        }
@@ -1349,7 +1350,7 @@
             the chosen single-byte character set can possibly match.  */
          raw_pattern_size = SCHARS (string);
          raw_pattern_size_byte = SCHARS (string);
-         raw_pattern = alloca (raw_pattern_size + 1);
+         raw_pattern = SAFE_ALLOCA (raw_pattern_size + 1);
          copy_text (SDATA (string), raw_pattern,
                     SBYTES (string), 1, 0);
        }
@@ -1357,7 +1358,7 @@
       /* Copy and optionally translate the pattern.  */
       len = raw_pattern_size;
       len_byte = raw_pattern_size_byte;
-      patbuf = alloca (len * MAX_MULTIBYTE_LENGTH);
+      SAFE_NALLOCA (patbuf, MAX_MULTIBYTE_LENGTH, len);
       pat = patbuf;
       base_pat = raw_pattern;
       if (multibyte)
@@ -1497,13 +1498,15 @@
       len_byte = pat - patbuf;
       pat = base_pat = patbuf;
 
-      if (boyer_moore_ok)
-       return boyer_moore (n, pat, len_byte, trt, inverse_trt,
-                           pos_byte, lim_byte,
-                           char_base);
-      else
-       return simple_search (n, pat, raw_pattern_size, len_byte, trt,
-                             pos, pos_byte, lim, lim_byte);
+      EMACS_INT result
+       = (boyer_moore_ok
+          ? boyer_moore (n, pat, len_byte, trt, inverse_trt,
+                         pos_byte, lim_byte,
+                         char_base)
+          : simple_search (n, pat, raw_pattern_size, len_byte, trt,
+                           pos, pos_byte, lim, lim_byte));
+      SAFE_FREE ();
+      return result;
     }
 }
 
@@ -2809,7 +2812,8 @@
 
   prev = Qnil;
 
-  data = alloca ((2 * search_regs.num_regs + 1) * sizeof *data);
+  USE_SAFE_ALLOCA;
+  SAFE_NALLOCA (data, 1, 2 * search_regs.num_regs + 1);
 
   len = 0;
   for (i = 0; i < search_regs.num_regs; i++)
@@ -2852,25 +2856,28 @@
 
   /* If REUSE is not usable, cons up the values and return them.  */
   if (! CONSP (reuse))
-    return Flist (len, data);
+    reuse = Flist (len, data);
+  else
+    {
+      /* If REUSE is a list, store as many value elements as will fit
+        into the elements of REUSE.  */
+      for (i = 0, tail = reuse; CONSP (tail);
+          i++, tail = XCDR (tail))
+       {
+         if (i < len)
+           XSETCAR (tail, data[i]);
+         else
+           XSETCAR (tail, Qnil);
+         prev = tail;
+       }
 
-  /* If REUSE is a list, store as many value elements as will fit
-     into the elements of REUSE.  */
-  for (i = 0, tail = reuse; CONSP (tail);
-       i++, tail = XCDR (tail))
-    {
+      /* If we couldn't fit all value elements into REUSE,
+        cons up the rest of them and add them to the end of REUSE.  */
       if (i < len)
-       XSETCAR (tail, data[i]);
-      else
-       XSETCAR (tail, Qnil);
-      prev = tail;
+       XSETCDR (prev, Flist (len - i, data + i));
     }
 
-  /* If we couldn't fit all value elements into REUSE,
-     cons up the rest of them and add them to the end of REUSE.  */
-  if (i < len)
-    XSETCDR (prev, Flist (len - i, data + i));
-
+  SAFE_FREE ();
   return reuse;
 }
 
@@ -3075,7 +3082,8 @@
 
   CHECK_STRING (string);
 
-  temp = alloca (SBYTES (string) * 2);
+  USE_SAFE_ALLOCA;
+  SAFE_NALLOCA (temp, 2, SBYTES (string));
 
   /* Now copy the data into the new string, inserting escapes. */
 
@@ -3093,10 +3101,13 @@
       *out++ = *in;
     }
 
-  return make_specified_string (temp,
-                               SCHARS (string) + backslashes_added,
-                               out - temp,
-                               STRING_MULTIBYTE (string));
+  Lisp_Object result
+    = make_specified_string (temp,
+                            SCHARS (string) + backslashes_added,
+                            out - temp,
+                            STRING_MULTIBYTE (string));
+  SAFE_FREE ();
+  return result;
 }
 
 /* Like find_newline, but doesn't use the cache, and only searches forward.  */

=== modified file 'src/sound.c'
--- a/src/sound.c       2014-03-25 14:43:26 +0000
+++ b/src/sound.c       2014-09-07 07:04:01 +0000
@@ -564,12 +564,11 @@
               SBYTES (s->data) - sizeof *header);
   else
     {
-      char *buffer;
       ptrdiff_t nbytes = 0;
       ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048;
       ptrdiff_t data_left = header->data_length;
-
-      buffer = alloca (blksize);
+      USE_SAFE_ALLOCA;
+      char *buffer = SAFE_ALLOCA (blksize);
       lseek (s->fd, sizeof *header, SEEK_SET);
       while (data_left > 0
              && (nbytes = emacs_read (s->fd, buffer, blksize)) > 0)
@@ -582,6 +581,7 @@
 
       if (nbytes < 0)
        sound_perror ("Error reading sound file");
+      SAFE_FREE ();
     }
 }
 
@@ -656,19 +656,20 @@
   else
     {
       ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048;
-      char *buffer;
       ptrdiff_t nbytes;
 
       /* Seek */
       lseek (s->fd, header->data_offset, SEEK_SET);
 
       /* Copy sound data to the device.  */
-      buffer = alloca (blksize);
+      USE_SAFE_ALLOCA;
+      char *buffer = SAFE_ALLOCA (blksize);
       while ((nbytes = emacs_read (s->fd, buffer, blksize)) > 0)
        sd->write (sd, buffer, nbytes);
 
       if (nbytes < 0)
        sound_perror ("Error reading sound file");
+      SAFE_FREE ();
     }
 }
 
@@ -1309,7 +1310,6 @@
   struct gcpro gcpro1, gcpro2;
   Lisp_Object args[2];
 #else /* WINDOWSNT */
-  int len = 0;
   Lisp_Object lo_file = {0};
   char * psz_file = NULL;
   unsigned long ui_volume_tmp = UINT_MAX;
@@ -1326,7 +1326,8 @@
   current_sound_device = xzalloc (sizeof *current_sound_device);
   current_sound = xzalloc (sizeof *current_sound);
   record_unwind_protect_void (sound_cleanup);
-  current_sound->header = alloca (MAX_SOUND_HEADER_BYTES);
+  char headerbuf[MAX_SOUND_HEADER_BYTES];
+  current_sound->header = headerbuf;
 
   if (STRINGP (attrs[SOUND_FILE]))
     {

=== modified file 'src/syntax.c'
--- a/src/syntax.c      2014-09-04 16:14:05 +0000
+++ b/src/syntax.c      2014-09-07 07:04:01 +0000
@@ -1567,6 +1567,7 @@
   const unsigned char *str;
   int len;
   Lisp_Object iso_classes;
+  USE_SAFE_ALLOCA;
 
   CHECK_STRING (string);
   iso_classes = Qnil;
@@ -1699,7 +1700,7 @@
          memcpy (himap, fastmap + 0200, 0200);
          himap[0200] = 0;
          memset (fastmap + 0200, 0, 0200);
-         char_ranges = alloca (sizeof *char_ranges * 128 * 2);
+         SAFE_NALLOCA (char_ranges, 2, 128);
          i = 0;
 
          while ((p1 = memchr (himap + i, 1, 0200 - i)))
@@ -1723,7 +1724,7 @@
     }
   else                         /* STRING is multibyte */
     {
-      char_ranges = alloca (sizeof *char_ranges * SCHARS (string) * 2);
+      SAFE_NALLOCA (char_ranges, 2, SCHARS (string));
 
       while (i_byte < size_byte)
        {
@@ -2032,6 +2033,7 @@
     SET_PT_BOTH (pos, pos_byte);
     immediate_quit = 0;
 
+    SAFE_FREE ();
     return make_number (PT - start_point);
   }
 }

=== modified file 'src/term.c'
--- a/src/term.c        2014-08-10 16:28:36 +0000
+++ b/src/term.c        2014-09-07 07:04:01 +0000
@@ -3191,6 +3191,7 @@
   Lisp_Object selectface;
   int first_item = 0;
   int col, row;
+  USE_SAFE_ALLOCA;
 
   /* Don't allow non-positive x0 and y0, lest the menu will wrap
      around the display.  */
@@ -3199,7 +3200,7 @@
   if (y0 <= 0)
     y0 = 1;
 
-  state = alloca (menu->panecount * sizeof (struct tty_menu_state));
+  SAFE_NALLOCA (state, 1, menu->panecount);
   memset (state, 0, sizeof (*state));
   faces[0]
     = lookup_derived_face (sf, intern ("tty-menu-disabled-face"),
@@ -3421,6 +3422,7 @@
   discard_mouse_events ();
   if (!kbd_buffer_events_waiting ())
     clear_input_pending ();
+  SAFE_FREE ();
   return result;
 }
 
@@ -3606,6 +3608,7 @@
   item_y = y += f->top_pos;
 
   /* Create all the necessary panes and their items.  */
+  USE_SAFE_ALLOCA;
   maxwidth = maxlines = lines = i = 0;
   lpane = TTYM_FAILURE;
   while (i < menu_items_used)
@@ -3674,9 +3677,7 @@
 
          if (!NILP (descrip))
            {
-             /* If alloca is fast, use that to make the space,
-                to reduce gc needs.  */
-             item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1);
+             item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1);
              memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
              for (j = SCHARS (item_name); j < maxwidth; j++)
                item_data[j] = ' ';
@@ -3829,6 +3830,7 @@
 
  tty_menu_end:
 
+  SAFE_FREE ();
   unbind_to (specpdl_count, Qnil);
   return entry;
 }

=== modified file 'src/textprop.c'
--- a/src/textprop.c    2014-01-14 17:59:19 +0000
+++ b/src/textprop.c    2014-09-07 07:04:01 +0000
@@ -660,6 +660,7 @@
 
       set_buffer_temp (XBUFFER (object));
 
+      USE_SAFE_ALLOCA;
       GET_OVERLAYS_AT (XINT (position), overlay_vec, noverlays, NULL, 0);
       noverlays = sort_overlays (overlay_vec, noverlays, w);
 
@@ -674,9 +675,11 @@
              if (overlay)
                /* Return the overlay we got the property from.  */
                *overlay = overlay_vec[noverlays];
+             SAFE_FREE ();
              return tem;
            }
        }
+      SAFE_FREE ();
     }
 
   if (overlay)

=== modified file 'src/window.c'
--- a/src/window.c      2014-08-11 00:59:34 +0000
+++ b/src/window.c      2014-09-07 07:04:01 +0000
@@ -6124,6 +6124,7 @@
   Lisp_Object frame;
   struct frame *f;
   ptrdiff_t old_point = -1;
+  USE_SAFE_ALLOCA;
 
   CHECK_WINDOW_CONFIGURATION (configuration);
 
@@ -6231,8 +6232,8 @@
         really like to do is to free only those matrices not reused
         below.  */
       root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
-      leaf_windows = alloca (count_windows (root_window)
-                            * sizeof *leaf_windows);
+      int nwindows = count_windows (root_window);
+      SAFE_NALLOCA (leaf_windows, 1, nwindows);
       n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
 
       /* Kludge Alert!
@@ -6456,6 +6457,7 @@
   Vminibuf_scroll_window = data->minibuf_scroll_window;
   minibuf_selected_window = data->minibuf_selected_window;
 
+  SAFE_FREE ();
   return (FRAME_LIVE_P (f) ? Qt : Qnil);
 }
 

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c       2014-09-04 16:14:05 +0000
+++ b/src/xdisp.c       2014-09-07 07:04:01 +0000
@@ -2626,15 +2626,14 @@
     {
       ptrdiff_t i;
       ptrdiff_t count = SPECPDL_INDEX ();
-      struct gcpro gcpro1;
-      Lisp_Object *args = alloca (nargs * word_size);
+      Lisp_Object *args;
+      USE_SAFE_ALLOCA;
+      SAFE_ALLOCA_LISP (args, nargs);
 
       args[0] = func;
       for (i = 1; i < nargs; i++)
        args[i] = va_arg (ap, Lisp_Object);
 
-      GCPRO1 (args[0]);
-      gcpro1.nvars = nargs;
       specbind (Qinhibit_redisplay, Qt);
       if (inhibit_quit)
        specbind (Qinhibit_quit, Qt);
@@ -2642,7 +2641,7 @@
         so there is no possibility of wanting to redisplay.  */
       val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
                                       safe_eval_handler);
-      UNGCPRO;
+      SAFE_FREE ();
       val = unbind_to (count, val);
     }
 
@@ -3659,6 +3658,7 @@
   ptrdiff_t i, noverlays;
   ptrdiff_t endpos;
   Lisp_Object *overlays;
+  USE_SAFE_ALLOCA;
 
   /* Get all overlays at the given position.  */
   GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1);
@@ -3675,6 +3675,7 @@
       endpos = min (endpos, oendpos);
     }
 
+  SAFE_FREE ();
   return endpos;
 }
 
@@ -5735,10 +5736,11 @@
   Lisp_Object overlay, window, str, invisible;
   struct Lisp_Overlay *ov;
   ptrdiff_t start, end;
-  ptrdiff_t size = 20;
   ptrdiff_t n = 0, i, j;
   int invis_p;
-  struct overlay_entry *entries = alloca (size * sizeof *entries);
+  struct overlay_entry entriesbuf[20];
+  ptrdiff_t size = ARRAYELTS (entriesbuf);
+  struct overlay_entry *entries = entriesbuf;
   USE_SAFE_ALLOCA;
 
   if (charpos <= 0)
@@ -10191,9 +10193,9 @@
     {
       ptrdiff_t nbytes = SBYTES (m);
       bool multibyte = STRING_MULTIBYTE (m);
+      char *buffer;
       USE_SAFE_ALLOCA;
-      char *buffer = SAFE_ALLOCA (nbytes);
-      memcpy (buffer, SDATA (m), nbytes);
+      SAFE_ALLOCA_STRING (buffer, m);
       message_dolog (buffer, nbytes, 1, multibyte);
       SAFE_FREE ();
     }
@@ -10395,11 +10397,13 @@
            {
              ptrdiff_t len;
              ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
-             char *message_buf = alloca (maxsize + 1);
+             USE_SAFE_ALLOCA;
+             char *message_buf = SAFE_ALLOCA (maxsize + 1);
 
              len = doprnt (message_buf, maxsize, m, 0, ap);
 
              message3 (make_string (message_buf, len));
+             SAFE_FREE ();
            }
          else
            message1 (0);
@@ -18695,10 +18699,10 @@
   else if (glyphs == 1)
     {
       int area;
+      char s[SHRT_MAX + 4];
 
       for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
        {
-         char *s = alloca (row->used[area] + 4);
          int i;
 
          for (i = 0; i < row->used[area]; ++i)
@@ -22690,10 +22694,8 @@
        }
       else if (CHARACTERP (eoltype))
        {
-         unsigned char *tmp = alloca (MAX_MULTIBYTE_LENGTH);
          int c = XFASTINT (eoltype);
-         eol_str_len = CHAR_STRING (c, tmp);
-         eol_str = tmp;
+         return buf + CHAR_STRING (c, (unsigned char *) buf);
        }
       else
        {
@@ -24609,7 +24611,7 @@
         face_id = (row)->glyphs[area][START].face_id;                     \
                                                                           \
         s = alloca (sizeof *s);                                           \
-        char2b = alloca ((END - START) * sizeof *char2b);                 \
+        SAFE_NALLOCA (char2b, 1, (END) - (START));                        \
         INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);           \
         append_glyph_string (&HEAD, &TAIL, s);                            \
         s->x = (X);                                                       \
@@ -24637,7 +24639,7 @@
     struct glyph_string *first_s = NULL;                                   \
     int n;                                                                 \
                                                                            \
-    char2b = alloca (cmp->glyph_len * sizeof *char2b);                     \
+    SAFE_NALLOCA (char2b, 1, cmp->glyph_len);                              \
                                                                            \
     /* Make glyph_strings for each glyph sequence that is drawable by      \
        the same face, and append them to HEAD/TAIL.  */                        
    \
@@ -24672,7 +24674,7 @@
     gstring = (composition_gstring_from_id                               \
               ((row)->glyphs[area][START].u.cmp.id));                    \
     s = alloca (sizeof *s);                                              \
-    char2b = alloca (LGSTRING_GLYPH_LEN (gstring) * sizeof *char2b);     \
+    SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring));              \
     INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);              \
     append_glyph_string (&(HEAD), &(TAIL), s);                           \
     s->x = (X);                                                                
  \
@@ -24824,6 +24826,7 @@
      BUILD_GLYPH_STRINGS will modify its start parameter.  That's
      the reason we use a separate variable `i'.  */
   i = start;
+  USE_SAFE_ALLOCA;
   BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
   if (tail)
     x_reached = tail->x + tail->background_width;
@@ -25023,6 +25026,7 @@
 
   RELEASE_HDC (hdc, f);
 
+  SAFE_FREE ();
   return x_reached;
 }
 
@@ -29291,6 +29295,8 @@
       /* Is this char mouse-active or does it have help-echo?  */
       position = make_number (pos);
 
+      USE_SAFE_ALLOCA;
+
       if (BUFFERP (object))
        {
          /* Put all the overlays we want in a vector in overlay_vec.  */
@@ -29572,6 +29578,7 @@
       BEGV = obegv;
       ZV = ozv;
       current_buffer = obuf;
+      SAFE_FREE ();
     }
 
  set_cursor:

=== modified file 'src/xfaces.c'
--- a/src/xfaces.c      2014-08-07 10:15:52 +0000
+++ b/src/xfaces.c      2014-09-07 07:04:01 +0000
@@ -5980,6 +5980,7 @@
     endpos = XINT (end);
 
   /* Look at properties from overlays.  */
+  USE_SAFE_ALLOCA;
   {
     ptrdiff_t next_overlay;
 
@@ -6006,7 +6007,10 @@
   /* Optimize common cases where we can use the default face.  */
   if (noverlays == 0
       && NILP (prop))
-    return default_face->id;
+    {
+      SAFE_FREE ();
+      return default_face->id;
+    }
 
   /* Begin with attributes from the default face.  */
   memcpy (attrs, default_face->lface, sizeof attrs);
@@ -6034,6 +6038,8 @@
 
   *endptr = endpos;
 
+  SAFE_FREE ();
+
   /* Look up a realized face with the given face attributes,
      or realize a new one for ASCII characters.  */
   return lookup_face (f, attrs);

=== modified file 'src/xmenu.c'
--- a/src/xmenu.c       2014-07-27 13:21:30 +0000
+++ b/src/xmenu.c       2014-09-07 07:04:01 +0000
@@ -2023,7 +2023,8 @@
   Window root;
   XMenu *menu;
   int pane, selidx, lpane, status;
-  Lisp_Object entry, pane_prefix;
+  Lisp_Object entry = Qnil;
+  Lisp_Object pane_prefix;
   char *datap;
   int ulx, uly, width, height;
   int dispwidth, dispheight;
@@ -2045,6 +2046,7 @@
       return Qnil;
     }
 
+  USE_SAFE_ALLOCA;
   block_input ();
 
   /* Figure out which root window F is on.  */
@@ -2057,8 +2059,7 @@
   if (menu == NULL)
     {
       *error_name = "Can't create menu";
-      unblock_input ();
-      return Qnil;
+      goto return_entry;
     }
 
   /* Don't GC while we prepare and show the menu,
@@ -2101,8 +2102,7 @@
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't create pane";
-             unblock_input ();
-             return Qnil;
+             goto return_entry;
            }
          i += MENU_ITEMS_PANE_LENGTH;
 
@@ -2146,9 +2146,7 @@
 
          if (!NILP (descrip))
            {
-             /* if alloca is fast, use that to make the space,
-                to reduce gc needs.  */
-             item_data = alloca (maxwidth + SBYTES (descrip) + 1);
+             item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1);
              memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
              for (j = SCHARS (item_name); j < maxwidth; j++)
                item_data[j] = ' ';
@@ -2166,8 +2164,7 @@
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't add selection to menu";
-             unblock_input ();
-             return Qnil;
+             goto return_entry;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
           lines++;
@@ -2241,7 +2238,7 @@
   status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
                           x, y, ButtonReleaseMask, &datap,
                           menu_help_callback);
-  entry = pane_prefix = Qnil;
+  pane_prefix = Qnil;
 
   switch (status)
     {
@@ -2300,10 +2297,10 @@
       break;
     }
 
+ return_entry:
   unblock_input ();
-  unbind_to (specpdl_count, Qnil);
-
-  return entry;
+  SAFE_FREE ();
+  return unbind_to (specpdl_count, entry);
 }
 
 #endif /* not USE_X_TOOLKIT */


reply via email to

[Prev in Thread] Current Thread [Next in Thread]