<p>Some virtual machines needs to verify bytecode before running, like JVM.</p>
<p>But, why does the bytecode need to be verified before uploading to a virtual machine?</p>

<bytecode><verification>
Why does the bytecode need to be verified before uploading to a virtual machine?
<p>JVM does not <em>need</em> bytecode to be verified. It <em>allows</em> to verify it, thanks to certain (sometimes quite damaging) design decisions.</p>
<p>With a verified bytecode you can safeguard from a set of runtime errors - you can check if all stack operations are sound, that only allowed system library calls are ever performed (if you need to sandbox the untrustworthy bytecode), etc.</p>

CC BY-SA 4.0
2023-06-18T09:18:29.410Z
2023-06-18T09:18:29.410Z
SK-logic
CC BY-SA 4.0
2023-06-19T21:37:20.017Z
Can you elaborate on the "sometimes quite damaging design decisions"?
Seggan
CC BY-SA 4.0
2023-06-20T08:36:00.730Z
@Seggan compare JVM or CLR VMs to, say, a full-blown Forth. The former are very limited in what you can do with stack. Stack layout cannot change in between function calls - they always consume fixed number of arguments from stack, always return a single value or nothing on a stack. In an unrestricted Forth stack VM any word can do whatever it fancy with the stack, and it gives tons of flexibility.
SK-logic
<p>Presumably, JVM bytecode is verified because</p>
<ol>
<li>Java code is supposed to be <a href="https://en.wikipedia.org/wiki/Memory_safety" rel="noreferrer">memory-safe</a>, i.e. it should not be possible for a well-formed Java program to corrupt the state of the JVM, segfault or access memory it's not supposed to;</li>
<li>Performing these checks at runtime while the program is executing would have unacceptable performance costs;</li>
<li>Java is <a href="https://en.wikipedia.org/wiki/Ahead-of-time_compilation" rel="noreferrer">compiled AOT</a> and distributed in bytecode form, typically packaged in JAR files; and</li>
<li>The JVM's design requirements included a need to run Java software from untrusted sources, e.g. in web applets.</li>
</ol>
<p>It's not sufficient for only the compiler to perform the relevant checks, because the distributor of the bytecode can't necessarily be trusted. Verifying bytecode at program load-time is therefore a good balance of the desired security and performance concerns. But it's the particular combination of the above four concerns which make this true. Consider:</p>
<ul>
<li>In C, C++ or unsafe Rust, the language gives the programmer powerful tools which <em>could</em> be used violate memory safety, and trusts the programmer to write code which won't. Since the programmer can write code which isn't statically checkable by the compiler, the compiled output is also not statically checkable.</li>
<li>The CPython interpreter uses bytecode, and Python libraries can be distributed in bytecode form, but all the necessary checks for safety are performed at runtime, and the cost of these checks is considered acceptable. So in the present design there is no need for CPython to also verify bytecode when the program is loaded, although there have been attempts to introduce a verifier anyway (see the rejected <a href="https://peps.python.org/pep-0330/" rel="noreferrer">PEP 330</a>).</li>
<li>Some Javascript engines compile to bytecode and then interpret it, but Javascript code is distributed in source form, not bytecode. Since the program is compiled to bytecode locally, the compiler's output is trusted and therefore doesn't need to be verified.</li>
<li>If only bytecode from trusted sources needs to be run, the author can be trusted to have compiled to correct bytecode, so it need not be verified at program load-time. If the author is trusted but the provenance of the distribution is not, it is still simpler to use <a href="https://en.wikipedia.org/wiki/Digital_signature" rel="noreferrer">signature verification</a> to verify the bytecode's author.</li>
</ul>
<p>Of course, running untrusted bytecode has other risks besides memory safety. For example, you don't want untrusted code to have full access to your filesystem or network, but bytecode verification can't check for this.</p>
<p>In the era of web applets, the JVM addressed these other risks by performing runtime checks as directed by the user; these checks were implemented in the <a href="https://docs.oracle.com/javase/tutorial/essential/environment/security.html" rel="noreferrer">security manager</a>, which could have a security policy set by the user or by trusted code, before the untrusted third-party code was loaded and executed. However, the <a href="https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/lang/SecurityManager.html" rel="noreferrer">SecurityManager API</a> has been deprecated since Java 19 and was removed in Java 21.</p>

CC BY-SA 4.0
2023-06-18T16:30:49.977Z
2023-06-18T20:40:03.827Z
2023-06-18T20:40:03.827Z
kaya3
CC BY-SA 4.0
2023-06-19T14:30:53.883Z
Note there have been many incidents where the "local" bytecode compilation in Javascript led to ACE. The strategy used nowadays is to run JS in a special process using OS-specific sandboxing techniques to prevent memory errors from doing harm.
mousetail 'he-him'
CC BY-SA 4.0
2023-06-19T18:26:44.103Z
@mousetail Bytecode verification would potentially help there if the bug was in the compiler (so that it sometimes output invalid bytecode, and the verifier would catch it). If the bug is in the bytecode interpreter (or the JIT compiler) then a bytecode verifier wouldn't catch it. You're right though that in principle bytecode verification can be useful outside of the narrow circumstances I described in my answer; I was only trying to address when it's needed, not all the cases it could be useful.
kaya3
# Why does the bytecode need to be verified before uploading to a virtual machine?
Posted by: username_0 on 2023-06-18
Some virtual machines needs to verify bytecode before running, like JVM.

But, why does the bytecode need to be verified before uploading to a virtual machine?
**Tags:** bytecode verification
---
## 2 answers
### Answer by username_3 on 2023-06-18. Score: 8 | Accepted answer
Presumably, JVM bytecode is verified because

1. Java code is supposed to be [memory-safe](https://en.wikipedia.org/wiki/Memory_safety), i.e. it should not be possible for a well-formed Java program to corrupt the state of the JVM, segfault or access memory it's not supposed to;
2. Performing these checks at runtime while the program is executing would have unacceptable performance costs;
3. Java is [compiled AOT](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) and distributed in bytecode form, typically packaged in JAR files; and
4. The JVM's design requirements included a need to run Java software from untrusted sources, e.g. in web applets.

It's not sufficient for only the compiler to perform the relevant checks, because the distributor of the bytecode can't necessarily be trusted. Verifying bytecode at program load-time is therefore a good balance of the desired security and performance concerns. But it's the particular combination of the above four concerns which make this true. Consider:

* In C, C++ or unsafe Rust, the language gives the programmer powerful tools which *could* be used violate memory safety, and trusts the programmer to write code which won't. Since the programmer can write code which isn't statically checkable by the compiler, the compiled output is also not statically checkable.
* The CPython interpreter uses bytecode, and Python libraries can be distributed in bytecode form, but all the necessary checks for safety are performed at runtime, and the cost of these checks is considered acceptable. So in the present design there is no need for CPython to also verify bytecode when the program is loaded, although there have been attempts to introduce a verifier anyway (see the rejected [PEP 330](https://peps.python.org/pep-0330/)).
* Some Javascript engines compile to bytecode and then interpret it, but Javascript code is distributed in source form, not bytecode. Since the program is compiled to bytecode locally, the compiler's output is trusted and therefore doesn't need to be verified.
* If only bytecode from trusted sources needs to be run, the author can be trusted to have compiled to correct bytecode, so it need not be verified at program load-time. If the author is trusted but the provenance of the distribution is not, it is still simpler to use [signature verification](https://en.wikipedia.org/wiki/Digital_signature) to verify the bytecode's author.

Of course, running untrusted bytecode has other risks besides memory safety. For example, you don't want untrusted code to have full access to your filesystem or network, but bytecode verification can't check for this.

In the era of web applets, the JVM addressed these other risks by performing runtime checks as directed by the user; these checks were implemented in the [security manager](https://docs.oracle.com/javase/tutorial/essential/environment/security.html), which could have a security policy set by the user or by trusted code, before the untrusted third-party code was loaded and executed. However, the [SecurityManager API](https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/lang/SecurityManager.html) has been deprecated since Java 19 and was removed in Java 21.
> **Comments:**
> **username_4** (2023-06-19): Note there have been many incidents where the "local" bytecode compilation in Javascript led to ACE. The strategy used nowadays is to run JS in a special process using OS-specific sandboxing techniques to prevent memory errors from doing harm.  
> **username_3** (2023-06-19): @mousetail Bytecode verification would potentially help there if the bug was in the compiler (so that it sometimes output invalid bytecode, and the verifier would catch it). If the bug is in the bytecode interpreter (or the JIT compiler) then a bytecode verifier wouldn't catch it. You're right though that in principle bytecode verification can be useful outside of the narrow circumstances I described in my answer; I was only trying to address when it's needed, not all the cases it could be useful.  
---
### Answer by username_1 on 2023-06-18. Score: 4
JVM does not *need* bytecode to be verified. It *allows* to verify it, thanks to certain (sometimes quite damaging) design decisions.

With a verified bytecode you can safeguard from a set of runtime errors - you can check if all stack operations are sound, that only allowed system library calls are ever performed (if you need to sandbox the untrustworthy bytecode), etc.
> **Comments:**
> **username_2** (2023-06-19): Can you elaborate on the "sometimes quite damaging design decisions"?  
> **username_1** (2023-06-20): @Seggan compare JVM or CLR VMs to, say, a full-blown Forth. The former are very limited in what you can do with stack. Stack layout cannot change in between function calls - they always consume fixed number of arguments from stack, always return a single value or nothing on a stack. In an unrestricted Forth stack VM any word can do whatever it fancy with the stack, and it gives tons of flexibility.  
---
