]> git.eshelyaron.com Git - emacs.git/commitdiff
Prevent dubious argument lists
authorPhilipp Stephani <phst@google.com>
Wed, 9 Nov 2016 22:13:52 +0000 (23:13 +0100)
committerPhilipp Stephani <phst@google.com>
Fri, 18 Nov 2016 17:02:57 +0000 (18:02 +0100)
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
src/eval.c
test/src/eval-tests.el

index 428e21c7a393a1b9dddfa897f0e78a0fa10cddcc..85daa43eaed5a70b0d158f36d6e236597f1787c0 100644 (file)
@@ -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
index caeb791c19bd891ffd3bd93c565985e19a8c5a27..884e1ebfb89d1f11db8c4ec55f6161cd3759d3e8 100644 (file)
@@ -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));
index 75999e1a25a2d69a157b6f86d1629e533a025e3f..fe08506ed25b035ef6f6b8ca2d4f4525cca0ecfd 100644 (file)
   ;; 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