aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoam Postavsky2020-03-20 04:07:39 -0400
committerNoam Postavsky2020-03-22 23:06:31 -0400
commit8944310d7c9e259c9611ff2f0004c3176eb0ddab (patch)
tree13a0f17f063ecb83481f94166ba7f68b19beeba2
parent8709aaddd8707c9eafb359f9ec824e4bc109bbc6 (diff)
downloademacs-8944310d7c9e259c9611ff2f0004c3176eb0ddab.tar.gz
emacs-8944310d7c9e259c9611ff2f0004c3176eb0ddab.zip
Don't signal during backtrace unrewind (Bug#40088)
backtrace_eval_unrewind is used to temporarily reverse let-bindings (it's called with a positive argument to reverse bindings, and then a negative argument to re-apply them) by backtrace--locals and backtrace-eval. For the SPECPDL_LET_DEFAULT and SPECPDL_LET_LOCAL cases (which occur for let-bindings on buffer-local variables), the code calls Fdefault_value and Fbuffer_local_value on the symbol. For symbols which are unbound at top-level, the first (with positive argument) call to backtrace_eval_unrewind will set the symbol's value to unbound (putting the current value in the specpdl's "old value" slot). On the second (with negative argument) call, backtrace_eval_unrewind attempts to retrieve the symbol's value with Fdefault_value or Fbuffer_local_value, but that raises a void-variable signal. This interrupts the restoration of the let-bindings, so any other variables more recent on the stack will now have the wrong value. * src/data.c (default_value): Make non-static. * src/lisp.h: Declare it. * src/eval.c (backtrace_eval_unrewind): Replace the calls to Fdefault_value and Fbuffer_local_value with default_value and buffer_local_value, respectively. The latter do exactly the same as the former, except if the symbol's value is Qunbound they just return it instead of signaling void-variable.
-rw-r--r--src/data.c2
-rw-r--r--src/eval.c4
-rw-r--r--src/lisp.h1
3 files changed, 4 insertions, 3 deletions
diff --git a/src/data.c b/src/data.c
index b1530688468..5ce5e360ab4 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1573,7 +1573,7 @@ notify_variable_watchers (Lisp_Object symbol,
1573/* Return the default value of SYMBOL, but don't check for voidness. 1573/* Return the default value of SYMBOL, but don't check for voidness.
1574 Return Qunbound if it is void. */ 1574 Return Qunbound if it is void. */
1575 1575
1576static Lisp_Object 1576Lisp_Object
1577default_value (Lisp_Object symbol) 1577default_value (Lisp_Object symbol)
1578{ 1578{
1579 struct Lisp_Symbol *sym; 1579 struct Lisp_Symbol *sym;
diff --git a/src/eval.c b/src/eval.c
index 4559a0e1f66..78a787c4ffd 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3816,7 +3816,7 @@ backtrace_eval_unrewind (int distance)
3816 { 3816 {
3817 Lisp_Object sym = specpdl_symbol (tmp); 3817 Lisp_Object sym = specpdl_symbol (tmp);
3818 Lisp_Object old_value = specpdl_old_value (tmp); 3818 Lisp_Object old_value = specpdl_old_value (tmp);
3819 set_specpdl_old_value (tmp, Fdefault_value (sym)); 3819 set_specpdl_old_value (tmp, default_value (sym));
3820 Fset_default (sym, old_value); 3820 Fset_default (sym, old_value);
3821 } 3821 }
3822 break; 3822 break;
@@ -3832,7 +3832,7 @@ backtrace_eval_unrewind (int distance)
3832 if (!NILP (Flocal_variable_p (symbol, where))) 3832 if (!NILP (Flocal_variable_p (symbol, where)))
3833 { 3833 {
3834 set_specpdl_old_value 3834 set_specpdl_old_value
3835 (tmp, Fbuffer_local_value (symbol, where)); 3835 (tmp, buffer_local_value (symbol, where));
3836 set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND); 3836 set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND);
3837 } 3837 }
3838 } 3838 }
diff --git a/src/lisp.h b/src/lisp.h
index 8674fe11a64..92294ac1d33 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -594,6 +594,7 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object);
594 594
595/* Defined in data.c. */ 595/* Defined in data.c. */
596extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); 596extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object);
597extern Lisp_Object default_value (Lisp_Object symbol);
597 598
598 599
599/* Defined in emacs.c. */ 600/* Defined in emacs.c. */