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 : : #include <test/util/script.h>
12 : :
13 : : #include <cassert>
14 : : #include <ios>
15 : : #include <utility>
16 : : #include <vector>
17 : :
18 [ + - ]: 2440 : FUZZ_TARGET(script_flags)
19 : : {
20 [ + + ]: 2028 : if (buffer.size() > 100'000) return;
21 : 2027 : DataStream ds{buffer};
22 : 2027 : try {
23 [ + + ]: 2027 : const CTransaction tx(deserialize, TX_WITH_WITNESS, ds);
24 : :
25 : 2000 : unsigned int verify_flags;
26 [ + + ]: 2000 : ds >> verify_flags;
27 : :
28 [ + - + + ]: 1995 : if (!IsValidFlagCombination(verify_flags)) return;
29 : :
30 : 1991 : unsigned int fuzzed_flags;
31 [ + + ]: 1991 : ds >> fuzzed_flags;
32 : :
33 : 1989 : std::vector<CTxOut> spent_outputs;
34 [ + + ]: 103916 : for (unsigned i = 0; i < tx.vin.size(); ++i) {
35 : 101948 : CTxOut prevout;
36 [ + + ]: 101948 : ds >> prevout;
37 [ + + ]: 101927 : if (!MoneyRange(prevout.nValue)) {
38 : : // prevouts should be consensus-valid
39 : 36291 : prevout.nValue = 1;
40 : : }
41 [ + - ]: 101927 : spent_outputs.push_back(prevout);
42 : 101948 : }
43 : 1968 : PrecomputedTransactionData txdata;
44 [ + - ]: 1968 : txdata.Init(tx, std::move(spent_outputs));
45 : :
46 [ + + ]: 102292 : for (unsigned i = 0; i < tx.vin.size(); ++i) {
47 [ + - ]: 100531 : const CTxOut& prevout = txdata.m_spent_outputs.at(i);
48 [ + - ]: 100531 : const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata, MissingDataBehavior::ASSERT_FAIL};
49 : :
50 : 100531 : ScriptError serror;
51 [ + - + - : 100531 : const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror);
+ - ]
52 [ - + ]: 100531 : 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 [ + + ]: 100531 : if (ret) {
56 : 11682 : verify_flags &= ~fuzzed_flags;
57 : : } else {
58 : 88849 : verify_flags |= fuzzed_flags;
59 : : }
60 [ + - + + ]: 100531 : if (!IsValidFlagCombination(verify_flags)) return;
61 : :
62 : 100324 : ScriptError serror_fuzzed;
63 [ + - + - : 100324 : const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed);
+ - ]
64 [ - + ]: 100324 : assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK));
65 : :
66 [ - + ]: 100324 : assert(ret_fuzzed == ret);
67 : 100531 : }
68 [ - + ]: 4016 : } catch (const std::ios_base::failure&) {
69 : 55 : return;
70 : 55 : }
71 : 2027 : }
|