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