Subject: Re: bug#75593: 31.0.50; Faulty macro kills Emacs

From: Pip Cet <[email-masked]>
Date: Wed, 15 Jan 2025 22:20:42 +0000

Alexander Prähauser via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <[email-masked]> writes:

> "Eli Zaretskii" <[email-masked]> writes:
>
> emacs -Q killermacro.el (or wherever you saved the file)
> M-x eval-buffer
>
> That should do it.

Reproducible here: the problem is that Feval does not verify its
LEXICAL argument is a valid lexical environment.  In your case, it's a
non-list cons cell.

Two ways to fix this:

1. Call Flength on the lexical environment.  This will throw an error if
the environment is invalid, including when it is circular, which might
otherwise result in unquittable infloops (this is currently subject of
bug#75520).

However, this may slow down a very critical piece of code (OTOH, it can
also conceivably speed it up, by ensuring that the lexical environment
is in a high-priority cache).

2. Revise all code which assumes Vinternal_interpreter_environment isn't
too bad.  In particular, this code:

	  for (Lisp_Object p = Vinternal_interpreter_environment;
	       !NILP (p); p = XCDR(p))
	    {
	      Lisp_Object e = XCAR (p);
	      if (SYMBOLP (e))
		dynvars = Fcons(e, dynvars);
	    }

should be

          Lisp_Object p = Vinternal_interpreter_environment;
          FOR_EACH_TAIL (p)
	    {
	      Lisp_Object e = XCAR (p);
	      if (SYMBOLP (e))
		dynvars = Fcons(e, dynvars);
	    }

(As virtually all places which used !NILP instead of CONSP were fixed a
while ago, my cocci script did not catch this case.)

We'll probably have to do both.

Here's (1):

commit 651362816bd5237b0f5aaea70d72a29aa9b8852e (HEAD)
Author: Pip Cet <[email-masked]>
Date:   Wed Jan 15 22:17:43 2025 +0000

    Ensure Vinternal_interpreter_environment isn't malformed (bug#75593)
    
    * src/eval.c (Feval): Call 'Flength' on the lexical environment,
    ensuring it is a list.

diff --git a/src/eval.c b/src/eval.c
index 941d121c2fb..2619bd57415 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2446,8 +2446,11 @@ DEFUN ("eval", Feval, Seval, 1, 2, 0,
   (Lisp_Object form, Lisp_Object lexical)
 {
   specpdl_ref count = SPECPDL_INDEX ();
-  specbind (Qinternal_interpreter_environment,
-	    CONSP (lexical) || NILP (lexical) ? lexical : list_of_t);
+  if (CONSP (lexical) || NILP (lexical))
+    Flength (lexical);
+  else
+    lexical = list_of_t;
+  specbind (Qinternal_interpreter_environment, lexical);
   return unbind_to (count, eval_sub (form));
 }