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

From: Pip Cet <[email-masked]>
Date: Fri, 17 Jan 2025 11:34:58 +0000

"Stefan Monnier" <[email-masked]> writes:

>> IOW, can we prevent crashes in a way that is cheap in production
>> builds, since 'eval' is quite a hotspot?
>
> I would actually be surprised if `Feval` is a hotspot.

Do we need to fix the case where the lexenv variable is modified by Lisp
code while it is the lexical environment?

(defmacro f () x)
(let ((l (list (cons 'l nil))))
  (setcdr (car l) l)
  (eval '(progn
	   (setcdr l 3)
	   (f))
	l))

crashes (this is the dotted-list case; the circular case causes an
unquittable infloop).

My original plan was to avoid looking at what Fmake_interpreted_closure
does with its lexenv.  It currently seems to me that it is simply
resurrected as Vinternal_interpreter_environment upon execution.

If that's true, maybe we should simply fix the Qmacro code in eval_sub
and hope for the best.

diff --git a/src/eval.c b/src/eval.c
index 941d121c2fb..43a7cb78cb6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2658,12 +2658,12 @@ eval_sub (Lisp_Object form)
 
 	  /* Make the macro aware of any defvar declarations in scope. */
 	  Lisp_Object dynvars = Vmacroexp__dynvars;
-	  for (Lisp_Object p = Vinternal_interpreter_environment;
-	       !NILP (p); p = XCDR(p))
+	  Lisp_Object p = Vinternal_interpreter_environment;
+	  FOR_EACH_TAIL (p)
 	    {
 	      Lisp_Object e = XCAR (p);
 	      if (SYMBOLP (e))
-		dynvars = Fcons(e, dynvars);
+		dynvars = Fcons (e, dynvars);
 	    }
 	  if (!EQ (dynvars, Vmacroexp__dynvars))
 	    specbind (Qmacroexp__dynvars, dynvars);