Branch data Line data Source code
1 : : // Copyright (c) 2019-2022 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 : 0 : void initialize_script()
35 : : {
36 : 0 : SelectParams(ChainType::REGTEST);
37 : 0 : }
38 : :
39 [ # # ]: 0 : FUZZ_TARGET(script, .init = initialize_script)
40 : : {
41 : 0 : FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
42 : 0 : const CScript script{ConsumeScript(fuzzed_data_provider)};
43 : :
44 : 0 : CompressedScript compressed;
45 [ # # # # ]: 0 : if (CompressScript(script, compressed)) {
46 [ # # ]: 0 : const unsigned int size = compressed[0];
47 : 0 : compressed.erase(compressed.begin());
48 [ # # ]: 0 : assert(size <= 5);
49 : 0 : CScript decompressed_script;
50 [ # # ]: 0 : const bool ok = DecompressScript(decompressed_script, size, compressed);
51 [ # # ]: 0 : assert(ok);
52 [ # # ]: 0 : assert(script == decompressed_script);
53 : 0 : }
54 : :
55 : 0 : TxoutType which_type;
56 [ # # ]: 0 : bool is_standard_ret = IsStandard(script, std::nullopt, which_type);
57 [ # # ]: 0 : if (!is_standard_ret) {
58 [ # # # # : 0 : assert(which_type == TxoutType::NONSTANDARD ||
# # ]
59 : : which_type == TxoutType::NULL_DATA ||
60 : : which_type == TxoutType::MULTISIG);
61 : : }
62 [ # # ]: 0 : if (which_type == TxoutType::NONSTANDARD) {
63 [ # # ]: 0 : assert(!is_standard_ret);
64 : : }
65 [ # # ]: 0 : if (which_type == TxoutType::NULL_DATA) {
66 [ # # ]: 0 : assert(script.IsUnspendable());
67 : : }
68 [ # # ]: 0 : if (script.IsUnspendable()) {
69 [ # # # # ]: 0 : assert(which_type == TxoutType::NULL_DATA ||
70 : : which_type == TxoutType::NONSTANDARD);
71 : : }
72 : :
73 : 0 : CTxDestination address;
74 [ # # ]: 0 : bool extract_destination_ret = ExtractDestination(script, address);
75 [ # # ]: 0 : if (!extract_destination_ret) {
76 [ # # ]: 0 : assert(which_type == TxoutType::PUBKEY ||
77 : : which_type == TxoutType::NONSTANDARD ||
78 : : which_type == TxoutType::NULL_DATA ||
79 : : which_type == TxoutType::MULTISIG);
80 : : }
81 [ # # # # ]: 0 : if (which_type == TxoutType::NONSTANDARD ||
82 [ # # ]: 0 : which_type == TxoutType::NULL_DATA ||
83 : : which_type == TxoutType::MULTISIG) {
84 [ # # ]: 0 : assert(!extract_destination_ret);
85 : : }
86 : :
87 : 0 : const FlatSigningProvider signing_provider;
88 [ # # ]: 0 : (void)InferDescriptor(script, signing_provider);
89 [ # # ]: 0 : (void)IsSegWitOutput(signing_provider, script);
90 : :
91 [ # # ]: 0 : (void)RecursiveDynamicUsage(script);
92 : :
93 : 0 : std::vector<std::vector<unsigned char>> solutions;
94 [ # # ]: 0 : (void)Solver(script, solutions);
95 : :
96 [ # # ]: 0 : (void)script.HasValidOps();
97 [ # # ]: 0 : (void)script.IsPayToAnchor();
98 [ # # ]: 0 : (void)script.IsPayToScriptHash();
99 [ # # ]: 0 : (void)script.IsPayToWitnessScriptHash();
100 [ # # ]: 0 : (void)script.IsPushOnly();
101 [ # # ]: 0 : (void)script.GetSigOpCount(/* fAccurate= */ false);
102 : :
103 : 0 : {
104 : 0 : const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
105 : 0 : CompressedScript compressed_script;
106 : 0 : compressed_script.assign(bytes.begin(), bytes.end());
107 : : // DecompressScript(..., ..., bytes) is not guaranteed to be defined if the bytes vector is too short
108 [ # # # # ]: 0 : if (compressed_script.size() >= 32) {
109 : 0 : CScript decompressed_script;
110 [ # # ]: 0 : DecompressScript(decompressed_script, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), compressed_script);
111 : 0 : }
112 : 0 : }
113 : :
114 : 0 : const std::optional<CScript> other_script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
115 [ # # ]: 0 : if (other_script) {
116 : 0 : {
117 : 0 : CScript script_mut{script};
118 [ # # ]: 0 : (void)FindAndDelete(script_mut, *other_script);
119 : 0 : }
120 : 0 : const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider);
121 : 0 : const uint32_t u32{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
122 : 0 : const uint32_t flags{u32 | SCRIPT_VERIFY_P2SH};
123 : 0 : {
124 : 0 : CScriptWitness wit;
125 [ # # ]: 0 : for (const auto& s : random_string_vector) {
126 [ # # ]: 0 : wit.stack.emplace_back(s.begin(), s.end());
127 : : }
128 [ # # ]: 0 : (void)CountWitnessSigOps(script, *other_script, &wit, flags);
129 : 0 : wit.SetNull();
130 : 0 : }
131 : 0 : }
132 : :
133 [ # # ]: 0 : (void)GetOpName(ConsumeOpcodeType(fuzzed_data_provider));
134 [ # # ]: 0 : (void)ScriptErrorString(static_cast<ScriptError>(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, SCRIPT_ERR_ERROR_COUNT)));
135 : :
136 : 0 : {
137 : 0 : const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
138 : 0 : CScript append_script{bytes.begin(), bytes.end()};
139 [ # # ]: 0 : append_script << fuzzed_data_provider.ConsumeIntegral<int64_t>();
140 [ # # ]: 0 : append_script << ConsumeOpcodeType(fuzzed_data_provider);
141 [ # # ]: 0 : append_script << CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
142 : 0 : append_script << ConsumeRandomLengthByteVector(fuzzed_data_provider);
143 : 0 : }
144 : :
145 : 0 : {
146 : 0 : const CTxDestination tx_destination_1{
147 [ # # ]: 0 : fuzzed_data_provider.ConsumeBool() ?
148 : 0 : DecodeDestination(fuzzed_data_provider.ConsumeRandomLengthString()) :
149 [ # # ]: 0 : ConsumeTxDestination(fuzzed_data_provider)};
150 : 0 : const CTxDestination tx_destination_2{ConsumeTxDestination(fuzzed_data_provider)};
151 [ # # ]: 0 : const std::string encoded_dest{EncodeDestination(tx_destination_1)};
152 [ # # ]: 0 : const UniValue json_dest{DescribeAddress(tx_destination_1)};
153 [ # # ]: 0 : (void)GetKeyForDestination(/*store=*/{}, tx_destination_1);
154 [ # # ]: 0 : const CScript dest{GetScriptForDestination(tx_destination_1)};
155 [ # # ]: 0 : const bool valid{IsValidDestination(tx_destination_1)};
156 : :
157 [ # # ]: 0 : if (!std::get_if<PubKeyDestination>(&tx_destination_1)) {
158 : : // Only try to round trip non-pubkey destinations since PubKeyDestination has no encoding
159 [ # # # # ]: 0 : Assert(dest.empty() != valid);
160 [ # # # # ]: 0 : Assert(tx_destination_1 == DecodeDestination(encoded_dest));
161 [ # # # # ]: 0 : Assert(valid == IsValidDestinationString(encoded_dest));
162 : : }
163 : :
164 : 0 : (void)(tx_destination_1 < tx_destination_2);
165 [ # # ]: 0 : if (tx_destination_1 == tx_destination_2) {
166 [ # # # # ]: 0 : Assert(encoded_dest == EncodeDestination(tx_destination_2));
167 [ # # # # : 0 : Assert(json_dest.write() == DescribeAddress(tx_destination_2).write());
# # # # ]
168 [ # # # # ]: 0 : Assert(dest == GetScriptForDestination(tx_destination_2));
169 : : }
170 : 0 : }
171 : 0 : }
|