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.
This commit is contained in:
parent
49ac780228
commit
0d913da15c
3 changed files with 35 additions and 5 deletions
|
@ -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
|
||||
|
|
18
src/eval.c
18
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));
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue