From 9e5f9a1b519dd12566c80390ad8038f2380ad3da Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Sat, 15 Jan 2022 15:24:39 -0500 Subject: [PATCH] MLAMBDA: fix local property cleanup when binding fails NIL is pushed onto the LOCLIST pdl early on in MLAMBDA, but MUNLOCAL does not necessarily get called if an error occurs before evaluating the body of the lambda expression. This is a very old bug in Maxima. One problem is related to the validation of parameters, and this is only a problem when simp:false. If an error occurs while validating the lambda parameters, then MUNLOCAL is not called and LOCLIST does not get cleaned up. (See my commit 07287100 which started validating lambda expressions during simplification. Before this commit, this problem also occurred when simp:true.) Another problem is related to the attempt at actually binding the parameters. There is an UNWIND-PROTECT that is meant to handle cleanup, but if binding fails then the cleanup does not actually occur, and so LOCLIST does not get cleaned up. LOCLIST not being cleaned up can cause various problems, such as the leaking of local properties and the fact that LOCLIST can continue to grow as errors occur: (%i1) f () := (local (q), q () := 'oops, lambda ([], 1) (1))$ (%i2) f ()$ (%i3) q (); (%o3) oops (%i4) :lisp loclist (($Q)) (%i4) f ()$ (%i5) :lisp loclist (($Q) ($Q)) Now we wait until binding succeeds before pushing onto LOCLIST. This fixes both of the problems described above. No problems with the test suite or share test suite. --- src/mlisp.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlisp.lisp b/src/mlisp.lisp index 7ad6dbdd5..53936a40b 100644 --- a/src/mlisp.lisp +++ b/src/mlisp.lisp @@ -187,7 +187,6 @@ is EQ to FNNAME if the latter is non-NIL." ; are applied to arguments. (setq noevalargs nil) (let ((params (cdadr fn))( mlocp t)) - (setq loclist (cons nil loclist)) (do ((a) (p)) ((or (null params) (and (null args) (not (mdeflistp params)))) (setq args (nreconc a args) params (nreconc p params))) @@ -213,6 +212,7 @@ is EQ to FNNAME if the latter is non-NIL." (vector-push args ar) (vector-push fnname ar) (mbind finish2032 args fnname) + (push nil loclist) (setq finish2033 t) (let ((aexprp (and aexprp (not (atom (caddr fn))) (eq (caar (caddr fn)) 'lambda)))) -- 2.11.4.GIT