=== modified file 'src/ChangeLog' --- src/ChangeLog 2014-09-04 05:38:37 +0000 +++ src/ChangeLog 2014-09-05 06:03:28 +0000 @@ -1,3 +1,101 @@ +2014-09-05 Paul Eggert + + 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 . + (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-04 Jan D * xterm.c (x_term_init): Don't call x_session_initialize if running === modified file 'src/alloc.c' --- src/alloc.c 2014-08-29 07:29:47 +0000 +++ src/alloc.c 2014-09-05 06:03:28 +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' --- src/buffer.c 2014-09-03 15:10:29 +0000 +++ src/buffer.c 2014-09-05 06:03:28 +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' --- src/buffer.h 2014-09-02 11:41:22 +0000 +++ src/buffer.h 2014-09-05 06:03:28 +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' --- src/callint.c 2014-06-17 13:50:22 +0000 +++ src/callint.c 2014-09-05 06:03:28 +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' --- src/callproc.c 2014-09-02 06:49:40 +0000 +++ src/callproc.c 2014-09-05 06:03:28 +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' --- src/coding.c 2014-08-11 00:59:34 +0000 +++ src/coding.c 2014-09-05 06:03:28 +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' --- src/doc.c 2014-04-05 19:30:36 +0000 +++ src/doc.c 2014-09-05 06:03:28 +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' --- src/editfns.c 2014-08-07 10:15:52 +0000 +++ src/editfns.c 2014-09-05 06:03:28 +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' --- src/eval.c 2014-09-03 04:21:40 +0000 +++ src/eval.c 2014-09-05 06:03:28 +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' --- src/fileio.c 2014-09-02 18:05:00 +0000 +++ src/fileio.c 2014-09-05 06:03:28 +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' --- src/fns.c 2014-08-30 23:29:23 +0000 +++ src/fns.c 2014-09-05 06:03:28 +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' --- src/font.c 2014-07-26 13:17:25 +0000 +++ src/font.c 2014-09-05 06:03:28 +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' --- src/fontset.c 2014-08-11 00:59:34 +0000 +++ src/fontset.c 2014-09-05 06:03:28 +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' --- src/frame.c 2014-09-03 15:10:29 +0000 +++ src/frame.c 2014-09-05 06:03:28 +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' --- src/ftfont.c 2014-08-25 07:00:42 +0000 +++ src/ftfont.c 2014-09-05 06:03:28 +0000 @@ -24,6 +24,8 @@ #include #include +#include + #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' --- src/ftxfont.c 2014-07-03 12:20:00 +0000 +++ src/ftxfont.c 2014-09-05 06:03:28 +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' --- src/image.c 2014-07-07 23:25:13 +0000 +++ src/image.c 2014-09-05 06:03:28 +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' --- src/keyboard.c 2014-08-27 10:51:21 +0000 +++ src/keyboard.c 2014-09-05 06:03:28 +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' --- src/keymap.c 2014-07-14 04:44:01 +0000 +++ src/keymap.c 2014-09-05 06:03:28 +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' --- src/lisp.h 2014-09-02 18:05:00 +0000 +++ src/lisp.h 2014-09-05 06:03:28 +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' --- src/lread.c 2014-09-01 16:05:43 +0000 +++ src/lread.c 2014-09-05 06:03:28 +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' --- src/menu.c 2014-08-10 08:26:28 +0000 +++ src/menu.c 2014-09-05 06:03:28 +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' --- src/print.c 2014-07-17 09:12:51 +0000 +++ src/print.c 2014-09-05 06:03:28 +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' --- src/process.c 2014-08-09 16:20:29 +0000 +++ src/process.c 2014-09-05 06:03:28 +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' --- src/regex.c 2014-07-15 14:04:06 +0000 +++ src/regex.c 2014-09-05 06:03:28 +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' --- src/scroll.c 2014-08-03 12:34:44 +0000 +++ src/scroll.c 2014-09-05 06:03:28 +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' --- src/search.c 2014-06-23 04:11:29 +0000 +++ src/search.c 2014-09-05 06:03:28 +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); + Lisp_Object 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' --- src/sound.c 2014-03-25 14:43:26 +0000 +++ src/sound.c 2014-09-05 06:03:28 +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' --- src/syntax.c 2014-09-04 16:14:05 +0000 +++ src/syntax.c 2014-09-05 06:03:28 +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' --- src/term.c 2014-08-10 16:28:36 +0000 +++ src/term.c 2014-09-05 06:03:28 +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' --- src/textprop.c 2014-01-14 17:59:19 +0000 +++ src/textprop.c 2014-09-05 06:03:28 +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' --- src/window.c 2014-08-11 00:59:34 +0000 +++ src/window.c 2014-09-05 06:03:28 +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' --- src/xdisp.c 2014-09-04 16:14:05 +0000 +++ src/xdisp.c 2014-09-05 06:03:28 +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' --- src/xfaces.c 2014-08-07 10:15:52 +0000 +++ src/xfaces.c 2014-09-05 06:03:28 +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' --- src/xmenu.c 2014-07-27 13:21:30 +0000 +++ src/xmenu.c 2014-09-05 06:03:28 +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 */