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 % 70 70
Test Date: 2026-06-29 07:05:34 Functions: 100.0 % 7 7
Branches: 63.9 % 108 69

             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                 :       26450 : 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                 :       26450 :     (void)desc.IsRange();
      22                 :       26450 :     (void)desc.IsSingleType();
      23                 :       26450 :     (void)desc.GetOutputType();
      24                 :             : 
      25         [ +  + ]:       26450 :     if (is_ranged.has_value()) {
      26         [ -  + ]:       22113 :         assert(desc.IsRange() == *is_ranged);
      27                 :             :     } else {
      28                 :        4337 :         is_ranged = desc.IsRange();
      29                 :             :     }
      30         [ +  + ]:       26450 :     if (is_solvable.has_value()) {
      31         [ -  + ]:       22113 :         assert(desc.IsSolvable() == *is_solvable);
      32                 :             :     } else {
      33                 :        4337 :         is_solvable = desc.IsSolvable();
      34                 :             :     }
      35                 :             : 
      36                 :             :     // Serialization to string representation.
      37                 :       26450 :     (void)desc.ToString();
      38                 :       26450 :     (void)desc.ToPrivateString(sig_provider, dummy);
      39                 :       26450 :     (void)desc.ToNormalizedString(sig_provider, dummy);
      40                 :             : 
      41                 :             :     // Serialization to Script.
      42                 :       26450 :     DescriptorCache cache;
      43                 :       26450 :     std::vector<CScript> out_scripts;
      44         [ +  - ]:       26450 :     (void)desc.Expand(0, sig_provider, out_scripts, sig_provider, &cache);
      45         [ +  - ]:       26450 :     (void)desc.ExpandPrivate(0, sig_provider, sig_provider);
      46         [ +  - ]:       26450 :     (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         [ +  + ]:       26450 :     if (!out_scripts.empty()) {
      50   [ +  -  -  + ]:       25145 :         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         [ +  - ]:       25145 :         const bool is_combo{!desc.IsSingleType()};
      54   [ +  +  +  +  :       25452 :         assert(is_combo || desc.ScriptSize() == out_scripts.back().size());
                   +  - ]
      55                 :             :     }
      56                 :             : 
      57         [ +  - ]:       26450 :     const auto max_sat_maxsig{desc.MaxSatisfactionWeight(true)};
      58         [ +  - ]:       26450 :     const auto max_sat_nonmaxsig{desc.MaxSatisfactionWeight(false)};
      59                 :             :     // Whether an estimate is available must not depend on the signature-size
      60                 :             :     // assumption, and assuming non-max-size signatures must never increase it.
      61         [ -  + ]:       26450 :     assert(max_sat_maxsig.has_value() == max_sat_nonmaxsig.has_value());
      62         [ -  + ]:       26450 :     assert(max_sat_nonmaxsig <= max_sat_maxsig);
      63         [ +  - ]:       26450 :     const auto max_elems{desc.MaxSatisfactionElems()};
      64                 :             :     // We must be able to estimate the max satisfaction size for any solvable descriptor (but combo).
      65   [ +  +  +  -  :       26450 :     const bool is_nontop_or_nonsolvable{!*is_solvable || !desc.GetOutputType()};
                   +  + ]
      66   [ +  +  +  -  :       26450 :     const bool is_input_size_info_set{max_sat_maxsig && max_sat_nonmaxsig && max_elems};
                   -  + ]
      67         [ -  + ]:         927 :     assert(is_input_size_info_set || is_nontop_or_nonsolvable);
      68                 :             : 
      69         [ +  - ]:       26450 :     auto max_key_expr = desc.GetMaxKeyExpr();
      70         [ +  - ]:       26450 :     auto key_count = desc.GetKeyCount();
      71   [ +  +  -  + ]:       26450 :     assert((max_key_expr == 0 && key_count == 0) || max_key_expr + 1 == key_count);
      72                 :       26450 : }
      73                 :             : 
      74                 :           2 : void initialize_descriptor_parse()
      75                 :             : {
      76   [ +  -  +  -  :           2 :     static ECC_Context ecc_context{};
                   +  - ]
      77                 :           2 :     SelectParams(ChainType::MAIN);
      78                 :           2 : }
      79                 :             : 
      80                 :           1 : void initialize_mocked_descriptor_parse()
      81                 :             : {
      82                 :           1 :     initialize_descriptor_parse();
      83                 :           1 :     MOCKED_DESC_CONVERTER.Init();
      84                 :           1 : }
      85                 :             : 
      86         [ +  - ]:        5157 : FUZZ_TARGET(mocked_descriptor_parse, .init = initialize_mocked_descriptor_parse)
      87                 :             : {
      88         [ -  + ]:        4691 :     const std::string mocked_descriptor{buffer.begin(), buffer.end()};
      89   [ -  +  +  -  :        4691 :     if (const auto descriptor = MOCKED_DESC_CONVERTER.GetDescriptor(mocked_descriptor)) {
                   +  + ]
      90   [ +  -  +  + ]:        4669 :         if (IsTooExpensive(MakeUCharSpan(*descriptor))) return;
      91                 :        4653 :         FlatSigningProvider signing_provider;
      92         [ -  + ]:        4653 :         std::string error;
      93   [ -  +  +  - ]:        4653 :         const auto desc = Parse(*descriptor, signing_provider, error);
      94                 :        4653 :         std::optional<bool> is_ranged;
      95                 :        4653 :         std::optional<bool> is_solvable;
      96         [ +  + ]:       23444 :         for (const auto& d : desc) {
      97         [ -  + ]:       18791 :             assert(d);
      98         [ +  - ]:       18791 :             TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable);
      99                 :             :         }
     100                 :        9344 :     }
     101                 :        4691 : }
     102                 :             : 
     103         [ +  - ]:        3747 : FUZZ_TARGET(descriptor_parse, .init = initialize_descriptor_parse)
     104                 :             : {
     105         [ +  + ]:        3281 :     if (IsTooExpensive(buffer)) return;
     106                 :             : 
     107                 :        3272 :     const std::string descriptor(buffer.begin(), buffer.end());
     108                 :        3272 :     FlatSigningProvider signing_provider;
     109                 :        3272 :     std::string error;
     110         [ +  + ]:        9816 :     for (const bool require_checksum : {true, false}) {
     111   [ -  +  +  - ]:        6544 :         const auto desc = Parse(descriptor, signing_provider, error, require_checksum);
     112                 :        6544 :         std::optional<bool> is_ranged;
     113                 :        6544 :         std::optional<bool> is_solvable;
     114         [ +  + ]:       14203 :         for (const auto& d : desc) {
     115         [ -  + ]:        7659 :             assert(d);
     116         [ +  - ]:        7659 :             TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable);
     117                 :             :         }
     118                 :        6544 :     }
     119                 :        3272 : }
        

Generated by: LCOV version 2.0-1