aboutsummaryrefslogtreecommitdiff
path: root/src/test/fuzz/descriptor_parse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/fuzz/descriptor_parse.cpp')
-rw-r--r--src/test/fuzz/descriptor_parse.cpp42
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);
+ }
}
}