Browse Source

Sanity check transaction scripts in DecodeHexTx

Make sure that the scripts of decoded transactions are valid scripts.
tags/v0.15.1
Andrew Chow 4 years ago
parent
commit
ac4e438229
3 changed files with 31 additions and 4 deletions
  1. 26
    3
      src/core_read.cpp
  2. 2
    1
      src/script/script.cpp
  3. 3
    0
      src/script/script.h

+ 26
- 3
src/core_read.cpp View File

@@ -88,10 +88,32 @@ CScript ParseScript(const std::string& s)
return result;
}

// Check that all of the input and output scripts of a transaction contains valid opcodes
bool CheckTxScriptsSanity(const CMutableTransaction& tx)
{
// Check input scripts for non-coinbase txs
if (!CTransaction(tx).IsCoinBase()) {
for (unsigned int i = 0; i < tx.vin.size(); i++) {
if (!tx.vin[i].scriptSig.HasValidOps() || tx.vin[i].scriptSig.size() > MAX_SCRIPT_SIZE) {
return false;
}
}
}
// Check output scripts
for (unsigned int i = 0; i < tx.vout.size(); i++) {
if (!tx.vout[i].scriptPubKey.HasValidOps() || tx.vout[i].scriptPubKey.size() > MAX_SCRIPT_SIZE) {
return false;
}
}
return true;
}

bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness)
{
if (!IsHex(strHexTx))
if (!IsHex(strHexTx)) {
return false;
}

std::vector<unsigned char> txData(ParseHex(strHexTx));

@@ -99,7 +121,7 @@ bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTry
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
try {
ssData >> tx;
if (ssData.eof()) {
if (ssData.eof() && CheckTxScriptsSanity(tx)) {
return true;
}
}
@@ -111,8 +133,9 @@ bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTry
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
try {
ssData >> tx;
if (!ssData.empty())
if (!ssData.empty()) {
return false;
}
}
catch (const std::exception&) {
return false;

+ 2
- 1
src/script/script.cpp View File

@@ -273,7 +273,8 @@ bool CScript::HasValidOps() const
CScript::const_iterator it = begin();
while (it < end()) {
opcodetype opcode;
if (!GetOp(it, opcode) || opcode > 0xb9) {
std::vector<unsigned char> item;
if (!GetOp(it, opcode, item) || opcode > MAX_OPCODE || item.size() > MAX_SCRIPT_ELEMENT_SIZE) {
return false;
}
}

+ 3
- 0
src/script/script.h View File

@@ -190,6 +190,9 @@ enum opcodetype
OP_INVALIDOPCODE = 0xff,
};

// Maximum value that an opcode can be
static const unsigned int MAX_OPCODE = OP_NOP10;

const char* GetOpName(opcodetype opcode);

class scriptnum_error : public std::runtime_error

Loading…
Cancel
Save