upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/script.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script.cpp')
-rw-r--r--src/script.cpp31
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 //