Branch data Line data Source code
1 : : // Copyright (c) 2009-2021 The Bitcoin Core developers 2 : : // Distributed under the MIT software license, see the accompanying 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : : 5 : : #include <consensus/amount.h> 6 : : #include <primitives/transaction.h> 7 : : #include <script/interpreter.h> 8 : : #include <serialize.h> 9 : : #include <streams.h> 10 : : #include <test/fuzz/fuzz.h> 11 [ + - ]: 2 : #include <test/util/script.h> 12 [ + - ]: 2 : 13 : 2 : #include <cassert> 14 [ + - ]: 2 : #include <ios> 15 [ + - ][ + - ]: 2 : #include <utility> [ + - ] 16 : : #include <vector> 17 : : 18 [ + - ][ + - ]: 6 : FUZZ_TARGET(script_flags) 19 : : { 20 [ # # ]: 0 : if (buffer.size() > 100'000) return; 21 : 0 : DataStream ds{buffer}; 22 [ + - ]: 2 : try { 23 [ # # ]: 2 : const CTransaction tx(deserialize, TX_WITH_WITNESS, ds); 24 [ + - ]: 2 : 25 [ + - ][ + - ]: 2 : unsigned int verify_flags; [ + - ] 26 [ # # ]: 0 : ds >> verify_flags; 27 : : 28 [ # # ][ # # ]: 0 : if (!IsValidFlagCombination(verify_flags)) return; 29 : : 30 [ + - ][ + - ]: 4 : unsigned int fuzzed_flags; [ # # ] 31 [ + - ][ + - ]: 2 : ds >> fuzzed_flags; [ # # ][ # # ] 32 : : 33 : 0 : std::vector<CTxOut> spent_outputs; 34 [ # # ]: 0 : for (unsigned i = 0; i < tx.vin.size(); ++i) { 35 [ # # ]: 0 : CTxOut prevout; 36 [ # # ]: 0 : ds >> prevout; 37 [ # # ][ # # ]: 0 : if (!MoneyRange(prevout.nValue)) { 38 : : // prevouts should be consensus-valid 39 : 0 : prevout.nValue = 1; 40 : 0 : } 41 [ # # ]: 0 : spent_outputs.push_back(prevout); 42 : 0 : } 43 [ # # ]: 0 : PrecomputedTransactionData txdata; 44 [ # # ]: 0 : txdata.Init(tx, std::move(spent_outputs)); 45 : : 46 [ # # ]: 0 : for (unsigned i = 0; i < tx.vin.size(); ++i) { 47 [ # # ]: 0 : const CTxOut& prevout = txdata.m_spent_outputs.at(i); 48 [ # # ]: 0 : const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata, MissingDataBehavior::ASSERT_FAIL}; 49 : : 50 : : ScriptError serror; 51 [ # # ][ # # ]: 0 : const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror); [ # # ] 52 [ # # ]: 0 : assert(ret == (serror == SCRIPT_ERR_OK)); 53 : : 54 : : // Verify that removing flags from a passing test or adding flags to a failing test does not change the result 55 [ # # ]: 0 : if (ret) { 56 : 0 : verify_flags &= ~fuzzed_flags; 57 : 0 : } else { 58 : 0 : verify_flags |= fuzzed_flags; 59 : : } 60 [ # # ][ # # ]: 0 : if (!IsValidFlagCombination(verify_flags)) return; 61 : : 62 : : ScriptError serror_fuzzed; 63 [ # # ][ # # ]: 0 : const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed); [ # # ] 64 [ # # ]: 0 : assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK)); 65 : : 66 [ # # ]: 0 : assert(ret_fuzzed == ret); 67 [ # # ]: 0 : } 68 [ # # ][ # # ]: 0 : } catch (const std::ios_base::failure&) { 69 : : return; 70 [ # # ]: 0 : } 71 [ # # ]: 0 : }