LCOV - code coverage report
Current view: top level - src/test/fuzz - script.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 5 108 4.6 %
Date: 2023-09-26 12:08:55 Functions: 6 8 75.0 %

          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           2 : #include <script/sign.h>
      18           2 : #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           2 : #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           4 : 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             :     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           0 :     }
      62           0 :     if (which_type == TxoutType::NONSTANDARD) {
      63           0 :         assert(!is_standard_ret);
      64           0 :     }
      65           0 :     if (which_type == TxoutType::NULL_DATA) {
      66           0 :         assert(script.IsUnspendable());
      67           0 :     }
      68           0 :     if (script.IsUnspendable()) {
      69           0 :         assert(which_type == TxoutType::NULL_DATA ||
      70             :                which_type == TxoutType::NONSTANDARD);
      71           0 :     }
      72             : 
      73           0 :     CTxDestination address;
      74           2 :     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           0 :     }
      81           0 :     if (which_type == TxoutType::NONSTANDARD ||
      82           0 :         which_type == TxoutType::NULL_DATA ||
      83           0 :         which_type == TxoutType::MULTISIG) {
      84           0 :         assert(!extract_destination_ret);
      85           0 :     }
      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.IsPayToScriptHash();
      98           0 :     (void)script.IsPayToWitnessScriptHash();
      99           0 :     (void)script.IsPushOnly();
     100           0 :     (void)script.GetSigOpCount(/* fAccurate= */ false);
     101             : 
     102             :     {
     103           0 :         const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
     104           0 :         CompressedScript compressed_script;
     105           0 :         compressed_script.assign(bytes.begin(), bytes.end());
     106             :         // DecompressScript(..., ..., bytes) is not guaranteed to be defined if the bytes vector is too short
     107           0 :         if (compressed_script.size() >= 32) {
     108           0 :             CScript decompressed_script;
     109           0 :             DecompressScript(decompressed_script, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), compressed_script);
     110           0 :         }
     111           0 :     }
     112             : 
     113           0 :     const std::optional<CScript> other_script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
     114           0 :     if (other_script) {
     115             :         {
     116           0 :             CScript script_mut{script};
     117           0 :             (void)FindAndDelete(script_mut, *other_script);
     118           0 :         }
     119           0 :         const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider);
     120           0 :         const uint32_t u32{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
     121           0 :         const uint32_t flags{u32 | SCRIPT_VERIFY_P2SH};
     122             :         {
     123           0 :             CScriptWitness wit;
     124           0 :             for (const auto& s : random_string_vector) {
     125           0 :                 wit.stack.emplace_back(s.begin(), s.end());
     126             :             }
     127           0 :             (void)CountWitnessSigOps(script, *other_script, &wit, flags);
     128           0 :             wit.SetNull();
     129           0 :         }
     130           0 :     }
     131             : 
     132           0 :     (void)GetOpName(ConsumeOpcodeType(fuzzed_data_provider));
     133           0 :     (void)ScriptErrorString(static_cast<ScriptError>(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, SCRIPT_ERR_ERROR_COUNT)));
     134             : 
     135             :     {
     136           0 :         const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
     137           0 :         CScript append_script{bytes.begin(), bytes.end()};
     138           0 :         append_script << fuzzed_data_provider.ConsumeIntegral<int64_t>();
     139           0 :         append_script << ConsumeOpcodeType(fuzzed_data_provider);
     140           0 :         append_script << CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
     141           0 :         append_script << ConsumeRandomLengthByteVector(fuzzed_data_provider);
     142           0 :     }
     143             : 
     144             :     {
     145           0 :         const CTxDestination tx_destination_1{
     146           0 :             fuzzed_data_provider.ConsumeBool() ?
     147           0 :                 DecodeDestination(fuzzed_data_provider.ConsumeRandomLengthString()) :
     148           0 :                 ConsumeTxDestination(fuzzed_data_provider)};
     149           0 :         const CTxDestination tx_destination_2{ConsumeTxDestination(fuzzed_data_provider)};
     150           0 :         const std::string encoded_dest{EncodeDestination(tx_destination_1)};
     151           0 :         const UniValue json_dest{DescribeAddress(tx_destination_1)};
     152           0 :         (void)GetKeyForDestination(/*store=*/{}, tx_destination_1);
     153           0 :         const CScript dest{GetScriptForDestination(tx_destination_1)};
     154           0 :         const bool valid{IsValidDestination(tx_destination_1)};
     155             : 
     156           0 :         if (!std::get_if<PubKeyDestination>(&tx_destination_1)) {
     157             :             // Only try to round trip non-pubkey destinations since PubKeyDestination has no encoding
     158           0 :             Assert(dest.empty() != valid);
     159           0 :             Assert(tx_destination_1 == DecodeDestination(encoded_dest));
     160           0 :             Assert(valid == IsValidDestinationString(encoded_dest));
     161           0 :         }
     162             : 
     163           0 :         (void)(tx_destination_1 < tx_destination_2);
     164           0 :         if (tx_destination_1 == tx_destination_2) {
     165           0 :             Assert(encoded_dest == EncodeDestination(tx_destination_2));
     166           0 :             Assert(json_dest.write() == DescribeAddress(tx_destination_2).write());
     167           0 :             Assert(dest == GetScriptForDestination(tx_destination_2));
     168           0 :         }
     169           0 :     }
     170           0 : }

Generated by: LCOV version 1.14