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