LCOV - code coverage report
Current view: top level - src/test/fuzz - descriptor_parse.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 100.0 % 68 68
Test Date: 2026-03-31 04:13:53 Functions: 100.0 % 7 7
Branches: 64.4 % 104 67

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2009-present 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                 :       14740 : static void TestDescriptor(const Descriptor& desc, FlatSigningProvider& sig_provider, std::string& dummy, std::optional<bool>& is_ranged, std::optional<bool>& is_solvable)
      19                 :             : {
      20                 :             :     // Trivial helpers.
      21                 :       14740 :     (void)desc.IsRange();
      22                 :       14740 :     (void)desc.IsSingleType();
      23                 :       14740 :     (void)desc.GetOutputType();
      24                 :             : 
      25         [ +  + ]:       14740 :     if (is_ranged.has_value()) {
      26         [ -  + ]:       12068 :         assert(desc.IsRange() == *is_ranged);
      27                 :             :     } else {
      28                 :        2672 :         is_ranged = desc.IsRange();
      29                 :             :     }
      30         [ +  + ]:       14740 :     if (is_solvable.has_value()) {
      31         [ -  + ]:       12068 :         assert(desc.IsSolvable() == *is_solvable);
      32                 :             :     } else {
      33                 :        2672 :         is_solvable = desc.IsSolvable();
      34                 :             :     }
      35                 :             : 
      36                 :             :     // Serialization to string representation.
      37                 :       14740 :     (void)desc.ToString();
      38                 :       14740 :     (void)desc.ToPrivateString(sig_provider, dummy);
      39                 :       14740 :     (void)desc.ToNormalizedString(sig_provider, dummy);
      40                 :             : 
      41                 :             :     // Serialization to Script.
      42                 :       14740 :     DescriptorCache cache;
      43                 :       14740 :     std::vector<CScript> out_scripts;
      44         [ +  - ]:       14740 :     (void)desc.Expand(0, sig_provider, out_scripts, sig_provider, &cache);
      45         [ +  - ]:       14740 :     (void)desc.ExpandPrivate(0, sig_provider, sig_provider);
      46         [ +  - ]:       14740 :     (void)desc.ExpandFromCache(0, cache, out_scripts, sig_provider);
      47                 :             : 
      48                 :             :     // If we could serialize to script we must be able to infer using the same provider.
      49         [ +  + ]:       14740 :     if (!out_scripts.empty()) {
      50   [ +  -  -  + ]:       14202 :         assert(InferDescriptor(out_scripts.back(), sig_provider));
      51                 :             : 
      52                 :             :         // The ScriptSize() must match the size of the serialized Script. (ScriptSize() is set for all descs but 'combo()'.)
      53         [ +  - ]:       14202 :         const bool is_combo{!desc.IsSingleType()};
      54   [ +  +  +  +  :       14377 :         assert(is_combo || desc.ScriptSize() == out_scripts.back().size());
                   +  - ]
      55                 :             :     }
      56                 :             : 
      57         [ +  - ]:       14740 :     const auto max_sat_maxsig{desc.MaxSatisfactionWeight(true)};
      58         [ +  - ]:       14740 :     const auto max_sat_nonmaxsig{desc.MaxSatisfactionWeight(true)};
      59         [ +  - ]:       14740 :     const auto max_elems{desc.MaxSatisfactionElems()};
      60                 :             :     // We must be able to estimate the max satisfaction size for any solvable descriptor (but combo).
      61   [ +  +  +  -  :       14740 :     const bool is_nontop_or_nonsolvable{!*is_solvable || !desc.GetOutputType()};
                   +  + ]
      62   [ +  +  +  -  :       14740 :     const bool is_input_size_info_set{max_sat_maxsig && max_sat_nonmaxsig && max_elems};
                   -  + ]
      63         [ -  + ]:         507 :     assert(is_input_size_info_set || is_nontop_or_nonsolvable);
      64                 :             : 
      65         [ +  - ]:       14740 :     auto max_key_expr = desc.GetMaxKeyExpr();
      66         [ +  - ]:       14740 :     auto key_count = desc.GetKeyCount();
      67   [ +  +  -  + ]:       14740 :     assert((max_key_expr == 0 && key_count == 0) || max_key_expr + 1 == key_count);
      68                 :       14740 : }
      69                 :             : 
      70                 :           2 : void initialize_descriptor_parse()
      71                 :             : {
      72   [ +  -  +  -  :           2 :     static ECC_Context ecc_context{};
                   +  - ]
      73                 :           2 :     SelectParams(ChainType::MAIN);
      74                 :           2 : }
      75                 :             : 
      76                 :           1 : void initialize_mocked_descriptor_parse()
      77                 :             : {
      78                 :           1 :     initialize_descriptor_parse();
      79                 :           1 :     MOCKED_DESC_CONVERTER.Init();
      80                 :           1 : }
      81                 :             : 
      82         [ +  - ]:        3001 : FUZZ_TARGET(mocked_descriptor_parse, .init = initialize_mocked_descriptor_parse)
      83                 :             : {
      84         [ -  + ]:        2543 :     const std::string mocked_descriptor{buffer.begin(), buffer.end()};
      85   [ -  +  +  -  :        2543 :     if (const auto descriptor = MOCKED_DESC_CONVERTER.GetDescriptor(mocked_descriptor)) {
                   +  + ]
      86   [ +  -  +  + ]:        2526 :         if (IsTooExpensive(MakeUCharSpan(*descriptor))) return;
      87                 :        2518 :         FlatSigningProvider signing_provider;
      88         [ -  + ]:        2518 :         std::string error;
      89   [ -  +  +  - ]:        2518 :         const auto desc = Parse(*descriptor, signing_provider, error);
      90                 :        2518 :         std::optional<bool> is_ranged;
      91                 :        2518 :         std::optional<bool> is_solvable;
      92         [ +  + ]:       11903 :         for (const auto& d : desc) {
      93         [ -  + ]:        9385 :             assert(d);
      94         [ +  - ]:        9385 :             TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable);
      95                 :             :         }
      96                 :        5061 :     }
      97                 :        2543 : }
      98                 :             : 
      99         [ +  - ]:        2800 : FUZZ_TARGET(descriptor_parse, .init = initialize_descriptor_parse)
     100                 :             : {
     101         [ +  + ]:        2342 :     if (IsTooExpensive(buffer)) return;
     102                 :             : 
     103                 :        2336 :     const std::string descriptor(buffer.begin(), buffer.end());
     104                 :        2336 :     FlatSigningProvider signing_provider;
     105                 :        2336 :     std::string error;
     106         [ +  + ]:        7008 :     for (const bool require_checksum : {true, false}) {
     107   [ -  +  +  - ]:        4672 :         const auto desc = Parse(descriptor, signing_provider, error, require_checksum);
     108                 :        4672 :         std::optional<bool> is_ranged;
     109                 :        4672 :         std::optional<bool> is_solvable;
     110         [ +  + ]:       10027 :         for (const auto& d : desc) {
     111         [ -  + ]:        5355 :             assert(d);
     112         [ +  - ]:        5355 :             TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable);
     113                 :             :         }
     114                 :        4672 :     }
     115                 :        2336 : }
        

Generated by: LCOV version 2.0-1