LCOV - code coverage report
Current view: top level - src/test/fuzz - descriptor_parse.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 0.0 % 56 0
Test Date: 2024-08-28 04:44:32 Functions: 0.0 % 7 0
Branches: 0.0 % 84 0

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2009-2021 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 <key_io.h>
       7                 :             : #include <pubkey.h>
       8                 :             : #include <script/descriptor.h>
       9                 :             : #include <test/fuzz/fuzz.h>
      10                 :             : #include <test/fuzz/util/descriptor.h>
      11                 :             : #include <util/chaintype.h>
      12                 :             : #include <util/strencodings.h>
      13                 :             : 
      14                 :             : //! The converter of mocked descriptors, needs to be initialized when the target is.
      15                 :             : MockedDescriptorConverter MOCKED_DESC_CONVERTER;
      16                 :             : 
      17                 :             : /** Test a successfully parsed descriptor. */
      18                 :           0 : static void TestDescriptor(const Descriptor& desc, FlatSigningProvider& sig_provider, std::string& dummy)
      19                 :             : {
      20                 :             :     // Trivial helpers.
      21                 :           0 :     (void)desc.IsRange();
      22                 :           0 :     const bool is_solvable{desc.IsSolvable()};
      23                 :           0 :     (void)desc.IsSingleType();
      24                 :           0 :     (void)desc.GetOutputType();
      25                 :             : 
      26                 :             :     // Serialization to string representation.
      27                 :           0 :     (void)desc.ToString();
      28                 :           0 :     (void)desc.ToPrivateString(sig_provider, dummy);
      29                 :           0 :     (void)desc.ToNormalizedString(sig_provider, dummy);
      30                 :             : 
      31                 :             :     // Serialization to Script.
      32                 :           0 :     DescriptorCache cache;
      33                 :           0 :     std::vector<CScript> out_scripts;
      34         [ #  # ]:           0 :     (void)desc.Expand(0, sig_provider, out_scripts, sig_provider, &cache);
      35         [ #  # ]:           0 :     (void)desc.ExpandPrivate(0, sig_provider, sig_provider);
      36         [ #  # ]:           0 :     (void)desc.ExpandFromCache(0, cache, out_scripts, sig_provider);
      37                 :             : 
      38                 :             :     // If we could serialize to script we must be able to infer using the same provider.
      39         [ #  # ]:           0 :     if (!out_scripts.empty()) {
      40   [ #  #  #  # ]:           0 :         assert(InferDescriptor(out_scripts.back(), sig_provider));
      41                 :             : 
      42                 :             :         // The ScriptSize() must match the size of the serialized Script. (ScriptSize() is set for all descs but 'combo()'.)
      43         [ #  # ]:           0 :         const bool is_combo{!desc.IsSingleType()};
      44   [ #  #  #  #  :           0 :         assert(is_combo || desc.ScriptSize() == out_scripts.back().size());
                   #  # ]
      45                 :             :     }
      46                 :             : 
      47         [ #  # ]:           0 :     const auto max_sat_maxsig{desc.MaxSatisfactionWeight(true)};
      48         [ #  # ]:           0 :     const auto max_sat_nonmaxsig{desc.MaxSatisfactionWeight(true)};
      49         [ #  # ]:           0 :     const auto max_elems{desc.MaxSatisfactionElems()};
      50                 :             :     // We must be able to estimate the max satisfaction size for any solvable descriptor (but combo).
      51   [ #  #  #  #  :           0 :     const bool is_nontop_or_nonsolvable{!is_solvable || !desc.GetOutputType()};
                   #  # ]
      52   [ #  #  #  #  :           0 :     const bool is_input_size_info_set{max_sat_maxsig && max_sat_nonmaxsig && max_elems};
                   #  # ]
      53         [ #  # ]:           0 :     assert(is_input_size_info_set || is_nontop_or_nonsolvable);
      54                 :           0 : }
      55                 :             : 
      56                 :           0 : void initialize_descriptor_parse()
      57                 :             : {
      58   [ #  #  #  #  :           0 :     static ECC_Context ecc_context{};
                   #  # ]
      59                 :           0 :     SelectParams(ChainType::MAIN);
      60                 :           0 : }
      61                 :             : 
      62                 :           0 : void initialize_mocked_descriptor_parse()
      63                 :             : {
      64                 :           0 :     initialize_descriptor_parse();
      65                 :           0 :     MOCKED_DESC_CONVERTER.Init();
      66                 :           0 : }
      67                 :             : 
      68         [ #  # ]:           0 : FUZZ_TARGET(mocked_descriptor_parse, .init = initialize_mocked_descriptor_parse)
      69                 :             : {
      70                 :             :     // Key derivation is expensive. Deriving deep derivation paths take a lot of compute and we'd
      71                 :             :     // rather spend time elsewhere in this target, like on the actual descriptor syntax. So rule
      72                 :             :     // out strings which could correspond to a descriptor containing a too large derivation path.
      73         [ #  # ]:           0 :     if (HasDeepDerivPath(buffer)) return;
      74                 :             : 
      75                 :             :     // Some fragments can take a virtually unlimited number of sub-fragments (thresh, multi_a) but
      76                 :             :     // may perform quadratic operations on them. Limit the number of sub-fragments per fragment.
      77         [ #  # ]:           0 :     if (HasTooManySubFrag(buffer)) return;
      78                 :             : 
      79                 :             :     // The script building logic performs quadratic copies in the number of nested wrappers. Limit
      80                 :             :     // the number of nested wrappers per fragment.
      81         [ #  # ]:           0 :     if (HasTooManyWrappers(buffer)) return;
      82                 :             : 
      83         [ #  # ]:           0 :     const std::string mocked_descriptor{buffer.begin(), buffer.end()};
      84   [ #  #  #  # ]:           0 :     if (const auto descriptor = MOCKED_DESC_CONVERTER.GetDescriptor(mocked_descriptor)) {
      85                 :           0 :         FlatSigningProvider signing_provider;
      86         [ #  # ]:           0 :         std::string error;
      87         [ #  # ]:           0 :         const auto desc = Parse(*descriptor, signing_provider, error);
      88   [ #  #  #  # ]:           0 :         if (desc) TestDescriptor(*desc, signing_provider, error);
      89                 :           0 :     }
      90                 :           0 : }
      91                 :             : 
      92         [ #  # ]:           0 : FUZZ_TARGET(descriptor_parse, .init = initialize_descriptor_parse)
      93                 :             : {
      94                 :             :     // See comments above for rationales.
      95         [ #  # ]:           0 :     if (HasDeepDerivPath(buffer)) return;
      96         [ #  # ]:           0 :     if (HasTooManySubFrag(buffer)) return;
      97         [ #  # ]:           0 :     if (HasTooManyWrappers(buffer)) return;
      98                 :             : 
      99                 :           0 :     const std::string descriptor(buffer.begin(), buffer.end());
     100                 :           0 :     FlatSigningProvider signing_provider;
     101                 :           0 :     std::string error;
     102         [ #  # ]:           0 :     for (const bool require_checksum : {true, false}) {
     103         [ #  # ]:           0 :         const auto desc = Parse(descriptor, signing_provider, error, require_checksum);
     104   [ #  #  #  # ]:           0 :         if (desc) TestDescriptor(*desc, signing_provider, error);
     105                 :           0 :     }
     106                 :           0 : }
        

Generated by: LCOV version 2.0-1