emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 0d913da: Prevent dubious argument lists


From: Philipp Stephani
Subject: [Emacs-diffs] master 0d913da: Prevent dubious argument lists
Date: Fri, 18 Nov 2016 17:36:25 +0000 (UTC)

branch: master
commit 0d913da15c094bf596dd685acecf3438228c15cf
Author: Philipp Stephani <address@hidden>
Commit: Philipp Stephani <address@hidden>

    Prevent dubious argument lists
    
    See Bug#24912 and Bug#24913.
    
    * src/eval.c (funcall_lambda): Detect more dubious argument lists.
    * lisp/emacs-lisp/bytecomp.el (byte-compile-check-lambda-list): Detect
    more dubious argument lists.
    * test/src/eval-tests.el (eval-tests--bugs-24912-and-24913): Add unit
    test.
---
 lisp/emacs-lisp/bytecomp.el |    7 +++++--
 src/eval.c                  |   18 +++++++++++++++---
 test/src/eval-tests.el      |   15 +++++++++++++++
 3 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 428e21c..85daa43 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2672,8 +2672,11 @@ If FORM is a lambda or a macro, byte-compile it as a 
function."
               (when (cddr list)
                 (error "Garbage following &rest VAR in lambda-list")))
              ((eq arg '&optional)
-              (unless (cdr list)
-                (error "Variable name missing after &optional")))
+              (when (or (null (cdr list))
+                         (memq (cadr list) '(&optional &rest)))
+                (error "Variable name missing after &optional"))
+               (when (memq '&optional (cddr list))
+                 (error "Duplicate &optional")))
              ((memq arg vars)
               (byte-compile-warn "repeated variable %s in lambda-list" arg))
              (t
diff --git a/src/eval.c b/src/eval.c
index caeb791..884e1eb 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2888,6 +2888,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
     emacs_abort ();
 
   i = optional = rest = 0;
+  bool previous_optional_or_rest = false;
   for (; CONSP (syms_left); syms_left = XCDR (syms_left))
     {
       QUIT;
@@ -2897,9 +2898,19 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
        xsignal1 (Qinvalid_function, fun);
 
       if (EQ (next, Qand_rest))
-       rest = 1;
+        {
+          if (rest || previous_optional_or_rest)
+            xsignal1 (Qinvalid_function, fun);
+          rest = 1;
+          previous_optional_or_rest = true;
+        }
       else if (EQ (next, Qand_optional))
-       optional = 1;
+        {
+          if (optional || rest || previous_optional_or_rest)
+            xsignal1 (Qinvalid_function, fun);
+          optional = 1;
+          previous_optional_or_rest = true;
+        }
       else
        {
          Lisp_Object arg;
@@ -2922,10 +2933,11 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
          else
            /* Dynamically bind NEXT.  */
            specbind (next, arg);
+          previous_optional_or_rest = false;
        }
     }
 
-  if (!NILP (syms_left))
+  if (!NILP (syms_left) || previous_optional_or_rest)
     xsignal1 (Qinvalid_function, fun);
   else if (i < nargs)
     xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 75999e1..fe08506 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -32,4 +32,19 @@
   ;; This should not crash.
   (should-error (funcall '(closure)) :type 'invalid-function))
 
+(ert-deftest eval-tests--bugs-24912-and-24913 ()
+  "Checks that Emacs doesn’t accept weird argument lists.
+Bug#24912 and Bug#24913."
+  (dolist (args '((&optional) (&rest) (&optional &rest) (&rest &optional)
+                  (&optional &rest a) (&optional a &rest)
+                  (&rest a &optional) (&rest &optional a)
+                  (&optional &optional) (&optional &optional a)
+                  (&optional a &optional b)
+                  (&rest &rest) (&rest &rest a)
+                  (&rest a &rest b)))
+    (should-error (eval `(funcall (lambda ,args)) t) :type 'invalid-function)
+    (should-error (byte-compile-check-lambda-list args))
+    (let ((byte-compile-debug t))
+      (should-error (eval `(byte-compile (lambda ,args)) t)))))
+
 ;;; eval-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]