Subject: bug#34757: Invalid bytecode from byte compiler

From: Pip Cet <[email-masked]>
Date: Fri, 8 Mar 2019 21:13:37 +0000

On Tue, Mar 5, 2019 at 3:30 PM chuntaro <[email-masked]> wrote:
>
> Invalid bytecode is output and error occurs when executed.

If I'm looking at this correctly, the problem is that the byte code
which is generated in an intermediate step:

0       constant  2
1       constant  print
2       constant  1
3       call      1
4       discard
5       constant  3
6       return

is considered a "trivial function" by byte-compile-out-toplevel, which
assumes that all values on the stack are used by the call.

We could fix byte-compile-out-toplevel to properly analyze how many
stack arguments the call takes, but this patch simply treats forms
like this as nontrivial:

diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 0b8f8824b4c..4e54e08ce14 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -3025,6 +3025,7 @@ byte-compile-out-toplevel
                        (or (null (cdr rest))
                            (and (memq output-type '(file progn t))
                                 (cdr (cdr rest))
+                                (eql (length body) (cdr (car rest)))
                                 (eq (car (nth 1 rest)) 'byte-discard)
                                 (progn (setq rest (cdr rest)) t))))
                   (setq maycall nil)    ; Only allow one real function call.
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 0b8f8824b4c..4e54e08ce14 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -3025,6 +3025,7 @@ byte-compile-out-toplevel
                        (or (null (cdr rest))
                            (and (memq output-type '(file progn t))
                                 (cdr (cdr rest))
+                                (eql (length body) (cdr (car rest)))
                                 (eq (car (nth 1 rest)) 'byte-discard)
                                 (progn (setq rest (cdr rest)) t))))
                   (setq maycall nil)	; Only allow one real function call.