Commit 0d913da1 authored by Philipp Stephani's avatar Philipp Stephani

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.
parent 49ac7802
......@@ -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
......
......@@ -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));
......
......@@ -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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment