Subject: bug#40088: 27.0.90; Symbol’s value as variable is void: debugger-outer-match-data

From: Eli Zaretskii <[email-masked]>
Date: Sun, 22 Mar 2020 16:25:17 +0200

> From: Noam Postavsky <[email-masked]>
> Cc: [email-masked],  [email-masked],
>   [email-masked],  [email-masked]
> Date: Sat, 21 Mar 2020 19:47:07 -0400
> 
> The underlying cause is in backtrace_eval_unrewind, which 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.
> 
> ielm happens to have some buffer-local variables which are unbound at
> top-level, which is why it can trigger this problem.  But any situation
> with void variables with buffer-local let-bindings can also trigger it.
> 
> Now, all of the above is true also for Emacs 26 and earlier.

It sounds like a very basic error.  How come we never saw it before?
Is it just luck?

> So the effects of this bug are newly significant in Emacs 27.  The fact
> that it strikes when the debugger opens, means that it can multiply the
> difficulty of analysing other bugs.  And the fix looks quite small and
> safe enough to qualify for emacs-27.

I'm okay with making the change on the emacs-27 branch, but please put
some of the description above in the commit log message, including why
calling default_value etc. avoids the problem (which might not be
obvious, unless one remembers by heart what Fdefault_value does).

Thanks.