diff options
Diffstat (limited to 'src/script.cpp')
| -rw-r--r-- | src/script.cpp | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/src/script.cpp b/src/script.cpp index d2111ed..44eed93 100644 --- a/src/script.cpp +++ b/src/script.cpp | |||
| @@ -67,6 +67,24 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI | |||
| 67 | if (!script.GetOp(pc, opcode, vchPushValue)) | 67 | if (!script.GetOp(pc, opcode, vchPushValue)) |
| 68 | return false; | 68 | return false; |
| 69 | 69 | ||
| 70 | if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) | ||
| 71 | return false; | ||
| 72 | |||
| 73 | // Disabled opcodes. Checked before the fExec test, so they invalidate | ||
| 74 | // the script even inside a branch that is never taken. | ||
| 75 | // | ||
| 76 | // These are unbounded: OP_CAT grows a stack element without limit | ||
| 77 | // (<x> OP_DUP OP_CAT repeated doubles it each time, so a tiny script | ||
| 78 | // exhausts memory), and OP_LSHIFT shifts by an attacker-supplied | ||
| 79 | // amount with no ceiling. Both let any transaction take down every | ||
| 80 | // node that validates it. Bitcoin removed the whole group for this. | ||
| 81 | if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT || | ||
| 82 | opcode == OP_RIGHT || opcode == OP_INVERT || opcode == OP_AND || | ||
| 83 | opcode == OP_OR || opcode == OP_XOR || opcode == OP_2MUL || | ||
| 84 | opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_DIV || | ||
| 85 | opcode == OP_MOD || opcode == OP_LSHIFT || opcode == OP_RSHIFT) | ||
| 86 | return false; | ||
| 87 | |||
| 70 | if (fExec && opcode <= OP_PUSHDATA4) | 88 | if (fExec && opcode <= OP_PUSHDATA4) |
| 71 | stack.push_back(vchPushValue); | 89 | stack.push_back(vchPushValue); |
| 72 | else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) | 90 | else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) |
| @@ -169,9 +187,18 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI | |||
| 169 | 187 | ||
| 170 | case OP_RETURN: | 188 | case OP_RETURN: |
| 171 | { | 189 | { |
| 172 | pc = pend; | 190 | // Must fail the script outright, never just stop executing it. |
| 191 | // | ||
| 192 | // scriptSig and scriptPubKey are evaluated as one concatenated | ||
| 193 | // script (see VerifySignature). The 0.1.0 behaviour here was | ||
| 194 | // "pc = pend", which jumps past everything that follows — so a | ||
| 195 | // scriptSig of <OP_TRUE OP_RETURN> skipped the entire | ||
| 196 | // scriptPubKey, including OP_CHECKSIG, and the final | ||
| 197 | // CastToBool(stack.back()) saw the attacker's own OP_TRUE. | ||
| 198 | // That let anyone spend anyone else's outputs without a | ||
| 199 | // signature. Bitcoin closed this in 0.3.5. | ||
| 200 | return false; | ||
| 173 | } | 201 | } |
| 174 | break; | ||
| 175 | 202 | ||
| 176 | 203 | ||
| 177 | // | 204 | // |