Branch data Line data Source code
1 : : // Copyright (c) 2019-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 <chainparams.h>
6 : : #include <compressor.h>
7 : : #include <core_io.h>
8 : : #include <core_memusage.h>
9 : : #include <key_io.h>
10 : : #include <policy/policy.h>
11 : : #include <pubkey.h>
12 : : #include <rpc/util.h>
13 : : #include <script/descriptor.h>
14 : : #include <script/interpreter.h>
15 : : #include <script/script.h>
16 : : #include <script/script_error.h>
17 : : #include <script/sign.h>
18 : : #include <script/signingprovider.h>
19 : : #include <script/solver.h>
20 : : #include <streams.h>
21 : : #include <test/fuzz/FuzzedDataProvider.h>
22 : : #include <test/fuzz/fuzz.h>
23 : : #include <test/fuzz/util.h>
24 : : #include <univalue.h>
25 : : #include <util/chaintype.h>
26 : :
27 : : #include <algorithm>
28 : : #include <cassert>
29 : : #include <cstdint>
30 : : #include <optional>
31 : : #include <string>
32 : : #include <vector>
33 : :
34 : 1 : void initialize_script()
35 : : {
36 : 1 : SelectParams(ChainType::REGTEST);
37 : 1 : }
38 : :
39 [ + - ]: 2837 : FUZZ_TARGET(script, .init = initialize_script)
40 : : {
41 : 2379 : FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
42 : 2379 : const CScript script{ConsumeScript(fuzzed_data_provider)};
43 : :
44 : 2379 : CompressedScript compressed;
45 [ + - + + ]: 2379 : if (CompressScript(script, compressed)) {
46 [ - + ]: 14 : const unsigned int size = compressed[0];
47 : 14 : compressed.erase(compressed.begin());
48 [ - + ]: 14 : assert(size <= 5);
49 : 14 : CScript decompressed_script;
50 [ + - ]: 14 : const bool ok = DecompressScript(decompressed_script, size, compressed);
51 [ - + ]: 14 : assert(ok);
52 [ - + ]: 14 : assert(script == decompressed_script);
53 : 14 : }
54 : :
55 : 2379 : TxoutType which_type;
56 [ + - ]: 2379 : bool is_standard_ret = IsStandard(script, which_type);
57 [ + + ]: 2379 : if (!is_standard_ret) {
58 [ + + + - : 2252 : assert(which_type == TxoutType::NONSTANDARD ||
- + ]
59 : : which_type == TxoutType::NULL_DATA ||
60 : : which_type == TxoutType::MULTISIG);
61 : : }
62 [ + + ]: 2379 : if (which_type == TxoutType::NONSTANDARD) {
63 [ - + ]: 874 : assert(!is_standard_ret);
64 : : }
65 [ + + ]: 2379 : if (which_type == TxoutType::NULL_DATA) {
66 [ - + ]: 14 : assert(script.IsUnspendable());
67 : : }
68 [ + + ]: 2379 : if (script.IsUnspendable()) {
69 [ + + - + ]: 111 : assert(which_type == TxoutType::NULL_DATA ||
70 : : which_type == TxoutType::NONSTANDARD);
71 : : }
72 : :
73 : 2379 : CTxDestination address;
74 [ + - ]: 2379 : bool extract_destination_ret = ExtractDestination(script, address);
75 [ + + ]: 2379 : if (!extract_destination_ret) {
76 [ + + + + : 2304 : assert(which_type == TxoutType::PUBKEY ||
+ + - + ]
77 : : which_type == TxoutType::NONSTANDARD ||
78 : : which_type == TxoutType::NULL_DATA ||
79 : : which_type == TxoutType::MULTISIG);
80 : : }
81 [ + + + + ]: 2379 : if (which_type == TxoutType::NONSTANDARD ||
82 [ + + ]: 1491 : which_type == TxoutType::NULL_DATA ||
83 : : which_type == TxoutType::MULTISIG) {
84 [ - + ]: 2274 : assert(!extract_destination_ret);
85 : : }
86 : :
87 : 2379 : const FlatSigningProvider signing_provider;
88 [ + - ]: 2379 : (void)InferDescriptor(script, signing_provider);
89 [ + - ]: 2379 : (void)IsSegWitOutput(signing_provider, script);
90 : :
91 [ + + ]: 2379 : (void)RecursiveDynamicUsage(script);
92 : :
93 : 2379 : std::vector<std::vector<unsigned char>> solutions;
94 [ + - ]: 2379 : (void)Solver(script, solutions);
95 : :
96 : 2379 : {
97 : 2379 : const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
98 : 2379 : CompressedScript compressed_script;
99 : 2379 : compressed_script.assign(bytes.begin(), bytes.end());
100 : : // DecompressScript(..., ..., bytes) is not guaranteed to be defined if the bytes vector is too short
101 [ + + + + ]: 2912 : if (compressed_script.size() >= 32) {
102 : 563 : CScript decompressed_script;
103 [ + - ]: 563 : DecompressScript(decompressed_script, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), compressed_script);
104 : 563 : }
105 : 2379 : }
106 : :
107 : 2379 : const std::optional<CScript> other_script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
108 [ + + ]: 2379 : if (other_script) {
109 : 399 : {
110 : 399 : CScript script_mut{script};
111 [ + - ]: 399 : (void)FindAndDelete(script_mut, *other_script);
112 : 0 : }
113 : 399 : const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider);
114 : 399 : const auto flags_rand{fuzzed_data_provider.ConsumeIntegral<script_verify_flags::value_type>()};
115 : 399 : const auto flags = script_verify_flags::from_int(flags_rand) | SCRIPT_VERIFY_P2SH;
116 : 399 : {
117 : 399 : CScriptWitness wit;
118 [ + + ]: 1687 : for (const auto& s : random_string_vector) {
119 [ - + + - ]: 1288 : wit.stack.emplace_back(s.begin(), s.end());
120 : : }
121 [ + - ]: 399 : (void)CountWitnessSigOps(script, *other_script, wit, flags);
122 : 399 : wit.SetNull();
123 : 0 : }
124 : 399 : }
125 : :
126 [ + - ]: 2379 : (void)GetOpName(ConsumeOpcodeType(fuzzed_data_provider));
127 [ + - ]: 2379 : (void)ScriptErrorString(static_cast<ScriptError>(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, SCRIPT_ERR_ERROR_COUNT)));
128 : :
129 : 2379 : {
130 : 2379 : const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
131 : 2379 : CScript append_script{bytes.begin(), bytes.end()};
132 [ + - ]: 2379 : append_script << fuzzed_data_provider.ConsumeIntegral<int64_t>();
133 [ + - ]: 2379 : append_script << ConsumeOpcodeType(fuzzed_data_provider);
134 [ + - ]: 2379 : append_script << CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
135 [ - + ]: 2379 : append_script << ConsumeRandomLengthByteVector(fuzzed_data_provider);
136 : 2379 : }
137 : :
138 : 2379 : {
139 : 2379 : const CTxDestination tx_destination_1{
140 [ + + ]: 2379 : fuzzed_data_provider.ConsumeBool() ?
141 : 420 : DecodeDestination(fuzzed_data_provider.ConsumeRandomLengthString()) :
142 [ + - ]: 2379 : ConsumeTxDestination(fuzzed_data_provider)};
143 : 2379 : const CTxDestination tx_destination_2{ConsumeTxDestination(fuzzed_data_provider)};
144 [ + - ]: 2379 : const std::string encoded_dest{EncodeDestination(tx_destination_1)};
145 [ + - ]: 2379 : const UniValue json_dest{DescribeAddress(tx_destination_1)};
146 [ + - ]: 2379 : (void)GetKeyForDestination(/*store=*/{}, tx_destination_1);
147 [ + - ]: 2379 : const CScript dest{GetScriptForDestination(tx_destination_1)};
148 [ + - ]: 2379 : const bool valid{IsValidDestination(tx_destination_1)};
149 : :
150 [ + + ]: 2379 : if (!std::get_if<PubKeyDestination>(&tx_destination_1)) {
151 : : // Only try to round trip non-pubkey destinations since PubKeyDestination has no encoding
152 [ + + - + ]: 2328 : Assert(dest.empty() != valid);
153 [ + - - + ]: 2314 : Assert(tx_destination_1 == DecodeDestination(encoded_dest));
154 [ + - - + ]: 2379 : Assert(valid == IsValidDestinationString(encoded_dest));
155 : : }
156 : :
157 : 2379 : (void)(tx_destination_1 < tx_destination_2);
158 [ + + ]: 2379 : if (tx_destination_1 == tx_destination_2) {
159 [ + - - + ]: 1973 : Assert(encoded_dest == EncodeDestination(tx_destination_2));
160 [ + - + - : 1973 : Assert(json_dest.write() == DescribeAddress(tx_destination_2).write());
+ - - + ]
161 [ + - - + ]: 1973 : Assert(dest == GetScriptForDestination(tx_destination_2));
162 : : }
163 : 2379 : }
164 : 2379 : }
|