Merge bitcoin/bitcoin#34288: fuzz: Exclude too expensive inputs in miniscript_string target

fac70ea8b5 fuzz: Exclude too expensive inputs in miniscript_string target (MarcoFalke)
fa90786478 iwyu: Fix includes for test/fuzz/util/descriptor module (MarcoFalke)

Pull request description:

  Fixes https://github.com/bitcoin/bitcoin/issues/30498

  Accepting "expensive" fuzz inputs which have no real use-case is problematic, because it prevents the fuzz engine from spending time on the next useful fuzz input.

  For example this one will take several seconds (the flamegraph shows the time is spent in minscipt `NoDupCheck`):

  ```
  curl -fLO '41bae50cff'
  FUZZ=miniscript_string /usr/bin/time   ./bld-cmake/bin/fuzz  ./41bae50cffd1741150a1b330d02ab09f46ff8cd1
  ```

  Inspecting the inputs shows that it has many sub frags, so rejecting based on `HasTooManySubFrag` should be sufficient.

ACKs for top commit:
  darosior:
    ACK fac70ea8b5
  brunoerg:
    code review ACK fac70ea8b5
  dergoegge:
    utACK fac70ea8b5

Tree-SHA512: 7f1e0d9ce24d67ec63e5b7c2dd194efa51f38beb013564690afe0f920e5ff1980c85ce344828c0dc3f34b6851db7fe72a76b1a775c6d51c94fb91431834f453b
This commit is contained in:
merge-script
2026-01-15 13:55:27 +00:00
3 changed files with 19 additions and 8 deletions

View File

@@ -11,6 +11,7 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/fuzz/util/descriptor.h>
#include <util/strencodings.h>
#include <algorithm>
@@ -1234,9 +1235,12 @@ FUZZ_TARGET(miniscript_smart, .init = FuzzInitSmart)
/* Fuzz tests that test parsing from a string, and roundtripping via string. */
FUZZ_TARGET(miniscript_string, .init = FuzzInit)
{
constexpr auto is_too_expensive{[](std::span<const uint8_t> buf) { return HasTooManySubFrag(buf) || HasTooManyWrappers(buf); }};
if (buffer.empty()) return;
FuzzedDataProvider provider(buffer.data(), buffer.size());
auto str = provider.ConsumeBytesAsString(provider.remaining_bytes() - 1);
if (is_too_expensive(MakeUCharSpan(str))) return;
const ParserContext parser_ctx{(MsCtx)provider.ConsumeBool()};
auto parsed = miniscript::FromString(str, parser_ctx);
if (!parsed) return;

View File

@@ -4,6 +4,11 @@
#include <test/fuzz/util/descriptor.h>
#include <key.h>
#include <key_io.h>
#include <pubkey.h>
#include <util/strencodings.h>
#include <ranges>
#include <stack>

View File

@@ -5,18 +5,20 @@
#ifndef BITCOIN_TEST_FUZZ_UTIL_DESCRIPTOR_H
#define BITCOIN_TEST_FUZZ_UTIL_DESCRIPTOR_H
#include <key_io.h>
#include <util/strencodings.h>
#include <script/descriptor.h>
#include <test/fuzz/fuzz.h>
#include <functional>
#include <array>
#include <cinttypes>
#include <cstddef>
#include <limits>
#include <optional>
#include <span>
#include <string>
#include <string_view>
/**
* Converts a mocked descriptor string to a valid one. Every key in a mocked descriptor key is
* Converts a mocked descriptor string to a valid one. Every key in a mocked descriptor is
* represented by 2 hex characters preceded by the '%' character. We parse the two hex characters
* as an index in a list of pre-generated keys. This list contains keys of the various types
* accepted in descriptor keys expressions.
* accepted in descriptor key expressions.
*/
class MockedDescriptorConverter {
private: