Branch data Line data Source code
1 : : // Copyright (c) 2009-present 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 : : #include <util/check.h>
13 : :
14 : : #include <ios>
15 : : #include <utility>
16 : : #include <vector>
17 : :
18 : 4613 : static SpanReader& operator>>(SpanReader& ds, script_verify_flags& f)
19 : : {
20 : 4613 : script_verify_flags::value_type n{0};
21 : 4613 : ds >> n;
22 [ - + ]: 4599 : f = script_verify_flags::from_int(n);
23 [ - + ]: 4599 : assert(n == f.as_int());
24 : 4599 : return ds;
25 : : }
26 : :
27 [ + - ]: 2814 : FUZZ_TARGET(script_flags)
28 : : {
29 [ + + ]: 2338 : if (buffer.size() > 100'000) return;
30 : 2337 : SpanReader ds{buffer};
31 : 2337 : try {
32 [ + + ]: 2337 : const CTransaction tx(deserialize, TX_WITH_WITNESS, ds);
33 : :
34 : 2312 : script_verify_flags verify_flags;
35 [ + + ]: 2312 : ds >> verify_flags;
36 : :
37 [ + - ]: 2303 : assert(verify_flags == script_verify_flags::from_int(verify_flags.as_int()));
38 : :
39 [ + - + + ]: 2303 : if (!IsValidFlagCombination(verify_flags)) return;
40 : :
41 : 2301 : script_verify_flags fuzzed_flags;
42 [ + + ]: 2301 : ds >> fuzzed_flags;
43 : :
44 : 2296 : std::vector<CTxOut> spent_outputs;
45 [ - + + + ]: 238393 : for (unsigned i = 0; i < tx.vin.size(); ++i) {
46 : 236136 : CTxOut prevout;
47 [ + + ]: 236136 : ds >> prevout;
48 [ + + ]: 236097 : if (!MoneyRange(prevout.nValue)) {
49 : : // prevouts should be consensus-valid
50 : 89827 : prevout.nValue = 1;
51 : : }
52 [ + - ]: 236097 : spent_outputs.push_back(prevout);
53 : 236136 : }
54 : 2257 : PrecomputedTransactionData txdata;
55 [ + - ]: 2257 : txdata.Init(tx, std::move(spent_outputs));
56 : :
57 [ - + + + ]: 235448 : for (unsigned i = 0; i < tx.vin.size(); ++i) {
58 [ + - ]: 233383 : const CTxOut& prevout = txdata.m_spent_outputs.at(i);
59 [ + - ]: 233383 : const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata, MissingDataBehavior::ASSERT_FAIL};
60 : :
61 : 233383 : ScriptError serror;
62 [ + - + - : 233383 : const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror);
+ - ]
63 [ - + ]: 233383 : assert(ret == (serror == SCRIPT_ERR_OK));
64 : :
65 : : // Verify that removing flags from a passing test or adding flags to a failing test does not change the result
66 [ + + ]: 233383 : if (ret) {
67 : 26210 : verify_flags &= ~fuzzed_flags;
68 : : } else {
69 : 207173 : verify_flags |= fuzzed_flags;
70 : : }
71 [ + - + + ]: 233383 : if (!IsValidFlagCombination(verify_flags)) return;
72 : :
73 : 233191 : ScriptError serror_fuzzed;
74 [ + - + - : 233191 : const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed);
+ - ]
75 [ - + ]: 233191 : assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK));
76 : :
77 [ - + ]: 233191 : assert(ret_fuzzed == ret);
78 : 233383 : }
79 [ - + ]: 4633 : } catch (const std::ios_base::failure&) {
80 : 78 : return;
81 : 78 : }
82 : : }
|