aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Stephani2016-11-09 23:13:52 +0100
committerPhilipp Stephani2016-11-18 18:02:57 +0100
commit0d913da15c094bf596dd685acecf3438228c15cf (patch)
tree342d5e0222a35dc93cca8858317e038a76e91c27
parent49ac78022802dfff08367477e8d09d17d3c73e68 (diff)
downloademacs-0d913da15c094bf596dd685acecf3438228c15cf.tar.gz
emacs-0d913da15c094bf596dd685acecf3438228c15cf.zip
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.
-rw-r--r--lisp/emacs-lisp/bytecomp.el7
-rw-r--r--src/eval.c18
-rw-r--r--test/src/eval-tests.el15
3 files changed, 35 insertions, 5 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 428e21c7a39..85daa43eaed 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."
2672 (when (cddr list) 2672 (when (cddr list)
2673 (error "Garbage following &rest VAR in lambda-list"))) 2673 (error "Garbage following &rest VAR in lambda-list")))
2674 ((eq arg '&optional) 2674 ((eq arg '&optional)
2675 (unless (cdr list) 2675 (when (or (null (cdr list))
2676 (error "Variable name missing after &optional"))) 2676 (memq (cadr list) '(&optional &rest)))
2677 (error "Variable name missing after &optional"))
2678 (when (memq '&optional (cddr list))
2679 (error "Duplicate &optional")))
2677 ((memq arg vars) 2680 ((memq arg vars)
2678 (byte-compile-warn "repeated variable %s in lambda-list" arg)) 2681 (byte-compile-warn "repeated variable %s in lambda-list" arg))
2679 (t 2682 (t
diff --git a/src/eval.c b/src/eval.c
index caeb791c19b..884e1ebfb89 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2888,6 +2888,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
2888 emacs_abort (); 2888 emacs_abort ();
2889 2889
2890 i = optional = rest = 0; 2890 i = optional = rest = 0;
2891 bool previous_optional_or_rest = false;
2891 for (; CONSP (syms_left); syms_left = XCDR (syms_left)) 2892 for (; CONSP (syms_left); syms_left = XCDR (syms_left))
2892 { 2893 {
2893 QUIT; 2894 QUIT;
@@ -2897,9 +2898,19 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
2897 xsignal1 (Qinvalid_function, fun); 2898 xsignal1 (Qinvalid_function, fun);
2898 2899
2899 if (EQ (next, Qand_rest)) 2900 if (EQ (next, Qand_rest))
2900 rest = 1; 2901 {
2902 if (rest || previous_optional_or_rest)
2903 xsignal1 (Qinvalid_function, fun);
2904 rest = 1;
2905 previous_optional_or_rest = true;
2906 }
2901 else if (EQ (next, Qand_optional)) 2907 else if (EQ (next, Qand_optional))
2902 optional = 1; 2908 {
2909 if (optional || rest || previous_optional_or_rest)
2910 xsignal1 (Qinvalid_function, fun);
2911 optional = 1;
2912 previous_optional_or_rest = true;
2913 }
2903 else 2914 else
2904 { 2915 {
2905 Lisp_Object arg; 2916 Lisp_Object arg;
@@ -2922,10 +2933,11 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
2922 else 2933 else
2923 /* Dynamically bind NEXT. */ 2934 /* Dynamically bind NEXT. */
2924 specbind (next, arg); 2935 specbind (next, arg);
2936 previous_optional_or_rest = false;
2925 } 2937 }
2926 } 2938 }
2927 2939
2928 if (!NILP (syms_left)) 2940 if (!NILP (syms_left) || previous_optional_or_rest)
2929 xsignal1 (Qinvalid_function, fun); 2941 xsignal1 (Qinvalid_function, fun);
2930 else if (i < nargs) 2942 else if (i < nargs)
2931 xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs)); 2943 xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 75999e1a25a..fe08506ed25 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -32,4 +32,19 @@
32 ;; This should not crash. 32 ;; This should not crash.
33 (should-error (funcall '(closure)) :type 'invalid-function)) 33 (should-error (funcall '(closure)) :type 'invalid-function))
34 34
35(ert-deftest eval-tests--bugs-24912-and-24913 ()
36 "Checks that Emacs doesn’t accept weird argument lists.
37Bug#24912 and Bug#24913."
38 (dolist (args '((&optional) (&rest) (&optional &rest) (&rest &optional)
39 (&optional &rest a) (&optional a &rest)
40 (&rest a &optional) (&rest &optional a)
41 (&optional &optional) (&optional &optional a)
42 (&optional a &optional b)
43 (&rest &rest) (&rest &rest a)
44 (&rest a &rest b)))
45 (should-error (eval `(funcall (lambda ,args)) t) :type 'invalid-function)
46 (should-error (byte-compile-check-lambda-list args))
47 (let ((byte-compile-debug t))
48 (should-error (eval `(byte-compile (lambda ,args)) t)))))
49
35;;; eval-tests.el ends here 50;;; eval-tests.el ends here