diff options
Diffstat (limited to 'src/test/fuzz/descriptor_parse.cpp')
-rw-r--r-- | src/test/fuzz/descriptor_parse.cpp | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp index b9a5560ffb..765daa3db7 100644 --- a/src/test/fuzz/descriptor_parse.cpp +++ b/src/test/fuzz/descriptor_parse.cpp @@ -15,14 +15,24 @@ MockedDescriptorConverter MOCKED_DESC_CONVERTER; /** Test a successfully parsed descriptor. */ -static void TestDescriptor(const Descriptor& desc, FlatSigningProvider& sig_provider, std::string& dummy) +static void TestDescriptor(const Descriptor& desc, FlatSigningProvider& sig_provider, std::string& dummy, std::optional<bool>& is_ranged, std::optional<bool>& is_solvable) { // Trivial helpers. (void)desc.IsRange(); - const bool is_solvable{desc.IsSolvable()}; (void)desc.IsSingleType(); (void)desc.GetOutputType(); + if (is_ranged.has_value()) { + assert(desc.IsRange() == *is_ranged); + } else { + is_ranged = desc.IsRange(); + } + if (is_solvable.has_value()) { + assert(desc.IsSolvable() == *is_solvable); + } else { + is_solvable = desc.IsSolvable(); + } + // Serialization to string representation. (void)desc.ToString(); (void)desc.ToPrivateString(sig_provider, dummy); @@ -48,7 +58,7 @@ static void TestDescriptor(const Descriptor& desc, FlatSigningProvider& sig_prov const auto max_sat_nonmaxsig{desc.MaxSatisfactionWeight(true)}; const auto max_elems{desc.MaxSatisfactionElems()}; // We must be able to estimate the max satisfaction size for any solvable descriptor (but combo). - const bool is_nontop_or_nonsolvable{!is_solvable || !desc.GetOutputType()}; + const bool is_nontop_or_nonsolvable{!*is_solvable || !desc.GetOutputType()}; const bool is_input_size_info_set{max_sat_maxsig && max_sat_nonmaxsig && max_elems}; assert(is_input_size_info_set || is_nontop_or_nonsolvable); } @@ -72,25 +82,45 @@ FUZZ_TARGET(mocked_descriptor_parse, .init = initialize_mocked_descriptor_parse) // out strings which could correspond to a descriptor containing a too large derivation path. if (HasDeepDerivPath(buffer)) return; + // Some fragments can take a virtually unlimited number of sub-fragments (thresh, multi_a) but + // may perform quadratic operations on them. Limit the number of sub-fragments per fragment. + if (HasTooManySubFrag(buffer)) return; + + // The script building logic performs quadratic copies in the number of nested wrappers. Limit + // the number of nested wrappers per fragment. + if (HasTooManyWrappers(buffer)) return; + const std::string mocked_descriptor{buffer.begin(), buffer.end()}; if (const auto descriptor = MOCKED_DESC_CONVERTER.GetDescriptor(mocked_descriptor)) { FlatSigningProvider signing_provider; std::string error; const auto desc = Parse(*descriptor, signing_provider, error); - if (desc) TestDescriptor(*desc, signing_provider, error); + std::optional<bool> is_ranged; + std::optional<bool> is_solvable; + for (const auto& d : desc) { + assert(d); + TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable); + } } } FUZZ_TARGET(descriptor_parse, .init = initialize_descriptor_parse) { - // See comment above for rationale. + // See comments above for rationales. if (HasDeepDerivPath(buffer)) return; + if (HasTooManySubFrag(buffer)) return; + if (HasTooManyWrappers(buffer)) return; const std::string descriptor(buffer.begin(), buffer.end()); FlatSigningProvider signing_provider; std::string error; for (const bool require_checksum : {true, false}) { const auto desc = Parse(descriptor, signing_provider, error, require_checksum); - if (desc) TestDescriptor(*desc, signing_provider, error); + std::optional<bool> is_ranged; + std::optional<bool> is_solvable; + for (const auto& d : desc) { + assert(d); + TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable); + } } } |