diff options
author | Ava Chow <github@achow101.com> | 2024-01-04 18:04:10 -0500 |
---|---|---|
committer | Ava Chow <github@achow101.com> | 2024-01-04 18:10:22 -0500 |
commit | d44554567f2726e572027a146516d87e4dcea2f5 (patch) | |
tree | db561b67e105a2af776ffa42d2386a7ee6b59599 /src/test | |
parent | 737e5884cc82dc352cef3ef26abc1cb8d3500b8b (diff) | |
parent | a44808fb437864878c2d9696b8a96193091446ee (diff) |
Merge bitcoin/bitcoin#28832: fuzz: rule-out too deep derivation paths in descriptor parsing targets
a44808fb437864878c2d9696b8a96193091446ee fuzz: rule-out too deep derivation paths in descriptor parsing targets (Antoine Poinsot)
Pull request description:
This fixes the `mocked_descriptor_parse` timeout reported in #28812 and direct the targets more toward what they are intended to fuzz: the descriptor syntax.
ACKs for top commit:
sipa:
utACK a44808fb437864878c2d9696b8a96193091446ee
achow101:
ACK a44808fb437864878c2d9696b8a96193091446ee
dergoegge:
ACK a44808fb437864878c2d9696b8a96193091446ee - Not running into timeouts anymore
TheCharlatan:
ACK a44808fb437864878c2d9696b8a96193091446ee
Tree-SHA512: a5dd1dbe9adf8f088bdc435addab88b56f435e6d7d2065bd6d5c6d80a32e3f1f97d3d2323131ab233618cd6dcc477c458abe3c4c865ab569449b8bc176231e93
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/fuzz/descriptor_parse.cpp | 8 | ||||
-rw-r--r-- | src/test/fuzz/util/descriptor.cpp | 14 | ||||
-rw-r--r-- | src/test/fuzz/util/descriptor.h | 10 |
3 files changed, 32 insertions, 0 deletions
diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp index 5474b38204..6ea315d4e2 100644 --- a/src/test/fuzz/descriptor_parse.cpp +++ b/src/test/fuzz/descriptor_parse.cpp @@ -67,6 +67,11 @@ void initialize_mocked_descriptor_parse() FUZZ_TARGET(mocked_descriptor_parse, .init = initialize_mocked_descriptor_parse) { + // Key derivation is expensive. Deriving deep derivation paths take a lot of compute and we'd + // rather spend time elsewhere in this target, like on the actual descriptor syntax. So rule + // out strings which could correspond to a descriptor containing a too large derivation path. + if (HasDeepDerivPath(buffer)) return; + const std::string mocked_descriptor{buffer.begin(), buffer.end()}; if (const auto descriptor = MOCKED_DESC_CONVERTER.GetDescriptor(mocked_descriptor)) { FlatSigningProvider signing_provider; @@ -78,6 +83,9 @@ FUZZ_TARGET(mocked_descriptor_parse, .init = initialize_mocked_descriptor_parse) FUZZ_TARGET(descriptor_parse, .init = initialize_descriptor_parse) { + // See comment above for rationale. + if (HasDeepDerivPath(buffer)) return; + const std::string descriptor(buffer.begin(), buffer.end()); FlatSigningProvider signing_provider; std::string error; diff --git a/src/test/fuzz/util/descriptor.cpp b/src/test/fuzz/util/descriptor.cpp index 5bfd2721ce..df78bdf314 100644 --- a/src/test/fuzz/util/descriptor.cpp +++ b/src/test/fuzz/util/descriptor.cpp @@ -70,3 +70,17 @@ std::optional<std::string> MockedDescriptorConverter::GetDescriptor(std::string_ return desc; } + +bool HasDeepDerivPath(const FuzzBufferType& buff, const int max_depth) +{ + auto depth{0}; + for (const auto& ch: buff) { + if (ch == ',') { + // A comma is always present between two key expressions, so we use that as a delimiter. + depth = 0; + } else if (ch == '/') { + if (++depth > max_depth) return true; + } + } + return false; +} diff --git a/src/test/fuzz/util/descriptor.h b/src/test/fuzz/util/descriptor.h index 6289b91b07..cd41dbafa3 100644 --- a/src/test/fuzz/util/descriptor.h +++ b/src/test/fuzz/util/descriptor.h @@ -8,6 +8,7 @@ #include <key_io.h> #include <util/strencodings.h> #include <script/descriptor.h> +#include <test/fuzz/fuzz.h> #include <functional> @@ -45,4 +46,13 @@ public: std::optional<std::string> GetDescriptor(std::string_view mocked_desc) const; }; +//! Default maximum number of derivation indexes in a single derivation path when limiting its depth. +constexpr int MAX_DEPTH{2}; + +/** + * Whether the buffer, if it represents a valid descriptor, contains a derivation path deeper than + * a given maximum depth. Note this may also be hit for deriv paths in origins. + */ +bool HasDeepDerivPath(const FuzzBufferType& buff, const int max_depth = MAX_DEPTH); + #endif // BITCOIN_TEST_FUZZ_UTIL_DESCRIPTOR_H |