aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorPaul Eggert2015-11-16 23:08:54 -0800
committerPaul Eggert2015-11-16 23:09:28 -0800
commit54beeef1180e5ff2adb6797b6b4572e71c882e95 (patch)
treebe939c06ccdeac25775f22790a2c83d7fd0eeaf0 /src/eval.c
parent1721600d2463bacd13faa2c7613b7897a84d1099 (diff)
downloademacs-54beeef1180e5ff2adb6797b6b4572e71c882e95.tar.gz
emacs-54beeef1180e5ff2adb6797b6b4572e71c882e95.zip
eval_sub followed dangling pointer when debugging
Problem reported by Pip Cet (Bug#21245). This bug could occur in eval_sub if the C compiler reused storage associated with the ‘argvals’ local after ‘argvals’ went out of scope, and if the Elisp debugger stopped on Elisp function exit and accessed ‘argvals’. It could also occur if a variadic function was called with so many arguments (over 2048 args on x86-64) that SAFE_ALLOCA_LISP called malloc, then SAFE_FREE freed the arguments, then the memory manager used the storage for other purposes, then the debugger accessed the arguments. * src/eval.c (eval_sub): Declare ‘argvals’ at top level of function body. Simplify local decls. When allocating args via SAFE_ALLOCA, call debugger before invoking SAFE_FREE, as the debugger needs access to the args. (eval_sub, apply_lambda): Rework to avoid need for set_backtrace_debug_on_exit hack. This is cleaner, and should work better with buggy custom debuggers.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/src/eval.c b/src/eval.c
index d460048e04b..3ee07a71c69 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2014,6 +2014,10 @@ eval_sub (Lisp_Object form)
2014 Lisp_Object funcar; 2014 Lisp_Object funcar;
2015 ptrdiff_t count; 2015 ptrdiff_t count;
2016 2016
2017 /* Declare here, as this array may be accessed by call_debugger near
2018 the end of this function. See Bug#21245. */
2019 Lisp_Object argvals[8];
2020
2017 if (SYMBOLP (form)) 2021 if (SYMBOLP (form))
2018 { 2022 {
2019 /* Look up its binding in the lexical environment. 2023 /* Look up its binding in the lexical environment.
@@ -2066,13 +2070,8 @@ eval_sub (Lisp_Object form)
2066 2070
2067 if (SUBRP (fun)) 2071 if (SUBRP (fun))
2068 { 2072 {
2069 Lisp_Object numargs; 2073 Lisp_Object args_left = original_args;
2070 Lisp_Object argvals[8]; 2074 Lisp_Object numargs = Flength (args_left);
2071 Lisp_Object args_left;
2072 register int i, maxargs;
2073
2074 args_left = original_args;
2075 numargs = Flength (args_left);
2076 2075
2077 check_cons_list (); 2076 check_cons_list ();
2078 2077
@@ -2101,11 +2100,20 @@ eval_sub (Lisp_Object form)
2101 set_backtrace_args (specpdl + count, vals, XINT (numargs)); 2100 set_backtrace_args (specpdl + count, vals, XINT (numargs));
2102 2101
2103 val = (XSUBR (fun)->function.aMANY) (XINT (numargs), vals); 2102 val = (XSUBR (fun)->function.aMANY) (XINT (numargs), vals);
2103
2104 check_cons_list ();
2105 lisp_eval_depth--;
2106 /* Do the debug-on-exit now, while VALS still exists. */
2107 if (backtrace_debug_on_exit (specpdl + count))
2108 val = call_debugger (list2 (Qexit, val));
2104 SAFE_FREE (); 2109 SAFE_FREE ();
2110 specpdl_ptr--;
2111 return val;
2105 } 2112 }
2106 else 2113 else
2107 { 2114 {
2108 maxargs = XSUBR (fun)->max_args; 2115 int i, maxargs = XSUBR (fun)->max_args;
2116
2109 for (i = 0; i < maxargs; i++) 2117 for (i = 0; i < maxargs; i++)
2110 { 2118 {
2111 argvals[i] = eval_sub (Fcar (args_left)); 2119 argvals[i] = eval_sub (Fcar (args_left));
@@ -2165,7 +2173,7 @@ eval_sub (Lisp_Object form)
2165 } 2173 }
2166 } 2174 }
2167 else if (COMPILEDP (fun)) 2175 else if (COMPILEDP (fun))
2168 val = apply_lambda (fun, original_args, count); 2176 return apply_lambda (fun, original_args, count);
2169 else 2177 else
2170 { 2178 {
2171 if (NILP (fun)) 2179 if (NILP (fun))
@@ -2195,7 +2203,7 @@ eval_sub (Lisp_Object form)
2195 } 2203 }
2196 else if (EQ (funcar, Qlambda) 2204 else if (EQ (funcar, Qlambda)
2197 || EQ (funcar, Qclosure)) 2205 || EQ (funcar, Qclosure))
2198 val = apply_lambda (fun, original_args, count); 2206 return apply_lambda (fun, original_args, count);
2199 else 2207 else
2200 xsignal1 (Qinvalid_function, original_fun); 2208 xsignal1 (Qinvalid_function, original_fun);
2201 } 2209 }
@@ -2750,14 +2758,13 @@ apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count)
2750 set_backtrace_args (specpdl + count, arg_vector, i); 2758 set_backtrace_args (specpdl + count, arg_vector, i);
2751 tem = funcall_lambda (fun, numargs, arg_vector); 2759 tem = funcall_lambda (fun, numargs, arg_vector);
2752 2760
2761 check_cons_list ();
2762 lisp_eval_depth--;
2753 /* Do the debug-on-exit now, while arg_vector still exists. */ 2763 /* Do the debug-on-exit now, while arg_vector still exists. */
2754 if (backtrace_debug_on_exit (specpdl + count)) 2764 if (backtrace_debug_on_exit (specpdl + count))
2755 { 2765 tem = call_debugger (list2 (Qexit, tem));
2756 /* Don't do it again when we return to eval. */
2757 set_backtrace_debug_on_exit (specpdl + count, false);
2758 tem = call_debugger (list2 (Qexit, tem));
2759 }
2760 SAFE_FREE (); 2766 SAFE_FREE ();
2767 specpdl_ptr--;
2761 return tem; 2768 return tem;
2762} 2769}
2763 2770