<p>you can find explanation here:
<a href="https://bitcointalk.org/index.php?topic=5095376.msg49150302#msg49150302" rel="noreferrer">https://bitcointalk.org/index.php?topic=5095376.msg49150302#msg49150302</a></p>

<blockquote>
  <p>the issue was actually with OP_RETURN. What OP_RETURN used to do is it would skip to the end of the script so whatever was on the stack was interpreted for the final script result. So what you could do was create a scriptSig that was just</p>
</blockquote>

<pre><code>OP_TRUE OP_RETURN
</code></pre>

<blockquote>
  <p>which would push true to the stack and skip the rest of the script (which included the scriptPubKey at this time). The interpreter would see that at the end of script execution a true was left on the stack so it would say that the script passed. Obviously this is bad because the nothing in the scriptPubKey was evaluated so none of the spending conditions were actually met.</p>
  
  <p>In fixing this bug, Satoshi disabled many other opcodes, changed OP_RETURN to always cause script execution to fail, and separated the execution of the scriptSig and the scriptPubKey so that the scriptPubKey is always executed.</p>
</blockquote>

CC BY-SA 4.0
2019-01-11T19:19:18.640Z
I don't think that this is correct.  At the point when the change to separate scriptSig and scriptPubKey execution `OP_RETURN` was already returning a `false`, causing the execution to fail.
arubi
CC BY-SA 4.0
2019-01-11T19:29:11.907Z
Actually, version `0.3.6` changed the behavior of `OP_RETURN` and version `0.3.7` had script execution change.  Granted, the two versions are two days apart from each other and there is a single commit in between which is only a docs and build system change
arubi
CC BY-SA 4.0
2019-01-11T21:03:35.103Z
I think Liu is correct. Before the upgrade for input and output script runs to be 2 consecutive runs (where the 2nd run inherits the stack state of the 1st), they were effectively concatenated and evaluated as a single script run. In such a case, a data push or op_return would relegate the output script to data.
James C.
CC BY-SA 4.0
2019-01-11T21:07:08.843Z
But what I'm saying is, it seems that there was no way to abuse op_return at the time when the change was done to execute scriptsig and scriptpubkey separately.  op_return was already returning false at that point so prepending it would not help.  A `PUSHDATA` op along with the size of the scriptpubkey seems like it would though!  Though this is not the part that is quoted.
arubi
CC BY-SA 4.0
2019-01-11T08:03:28.573Z
2019-01-11T15:56:37.503Z
2019-01-11T15:56:37.503Z
LIU YUE
<p><a href="https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch06.asciidoc" rel="noreferrer">https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch06.asciidoc</a></p>

<blockquote>
  <p>In the original bitcoin client, the unlocking and locking scripts were
  concatenated and executed in sequence. For security reasons, this was
  changed in 2010, because of a vulnerability that allowed a malformed
  unlocking script to push data onto the stack and corrupt the locking
  script. In the current implementation, the scripts are executed
  separately with the stack transferred between the two executions, as
  described next.</p>
  
  <p>First, the unlocking script is executed, using the stack execution
  engine. If the unlocking script is executed without errors (e.g., it
  has no "dangling" operators left over), the main stack is copied and
  the locking script is executed. If the result of executing the locking
  script with the stack data copied from the unlocking script is "TRUE,"
  the unlocking script has succeeded in resolving the conditions imposed
  by the locking script and, therefore, the input is a valid
  authorization to spend the UTXO.</p>
</blockquote>

<p>In this chapter, Andreas states that due to a bug with malformed unlocking scripts, the scripts are now executed separately.</p>

<p>Here is my understanding:</p>

<p>The unlocking script is first executed on the main stack.
If the unlocking script is valid, the entire stack is copied and the locking script is then executed.</p>

<p><strong>Is there a reason why the stack is not copied to an alternate stack and then the unlocking script is executed on the alt stack? This way, if the unlocking script is malformed, it would not corrupt the rest of the main stack.</strong></p>

<transactions><validation><mastering-bitcoin>
How does copying main stack prevent malformed unlocking scripts vulnerabilities?
Huy
# How does copying main stack prevent malformed unlocking scripts vulnerabilities?

(Asked by: username_0 on 2018-10-20)

<https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch06.asciidoc>

> In the original bitcoin client, the unlocking and locking scripts were
> concatenated and executed in sequence. For security reasons, this was
> changed in 2010, because of a vulnerability that allowed a malformed
> unlocking script to push data onto the stack and corrupt the locking
> script. In the current implementation, the scripts are executed
> separately with the stack transferred between the two executions, as
> described next.
>
> First, the unlocking script is executed, using the stack execution
> engine. If the unlocking script is executed without errors (e.g., it
> has no "dangling" operators left over), the main stack is copied and
> the locking script is executed. If the result of executing the locking
> script with the stack data copied from the unlocking script is "TRUE,"
> the unlocking script has succeeded in resolving the conditions imposed
> by the locking script and, therefore, the input is a valid
> authorization to spend the UTXO.

In this chapter, Andreas states that due to a bug with malformed unlocking scripts, the scripts are now executed separately.

Here is my understanding:

The unlocking script is first executed on the main stack.
If the unlocking script is valid, the entire stack is copied and the locking script is then executed.

**Is there a reason why the stack is not copied to an alternate stack and then the unlocking script is executed on the alt stack? This way, if the unlocking script is malformed, it would not corrupt the rest of the main stack.**

**Tags:** transactions, validation, mastering-bitcoin


---

## 1 answers

### Answer by username_1 on 2019-01-11. Score: 6

you can find explanation here:
<https://bitcointalk.org/index.php?topic=5095376.msg49150302#msg49150302>

> the issue was actually with OP\_RETURN. What OP\_RETURN used to do is it would skip to the end of the script so whatever was on the stack was interpreted for the final script result. So what you could do was create a scriptSig that was just

```
OP_TRUE OP_RETURN

```

> which would push true to the stack and skip the rest of the script (which included the scriptPubKey at this time). The interpreter would see that at the end of script execution a true was left on the stack so it would say that the script passed. Obviously this is bad because the nothing in the scriptPubKey was evaluated so none of the spending conditions were actually met.
>
> In fixing this bug, Satoshi disabled many other opcodes, changed OP\_RETURN to always cause script execution to fail, and separated the execution of the scriptSig and the scriptPubKey so that the scriptPubKey is always executed.

> **Comments:**
> **username_2**: I don't think that this is correct.  At the point when the change to separate scriptSig and scriptPubKey execution `OP_RETURN` was already returning a `false`, causing the execution to fail.  
> **username_2**: Actually, version `0.3.6` changed the behavior of `OP_RETURN` and version `0.3.7` had script execution change.  Granted, the two versions are two days apart from each other and there is a single commit in between which is only a docs and build system change  
> **username_3**: I think Liu is correct. Before the upgrade for input and output script runs to be 2 consecutive runs (where the 2nd run inherits the stack state of the 1st), they were effectively concatenated and evaluated as a single script run. In such a case, a data push or op_return would relegate the output script to data.  
> **username_2**: But what I'm saying is, it seems that there was no way to abuse op_return at the time when the change was done to execute scriptsig and scriptpubkey separately.  op_return was already returning false at that point so prepending it would not help.  A `PUSHDATA` op along with the size of the scriptpubkey seems like it would though!  Though this is not the part that is quoted.  

---

