Skip to content

Add fuzz targets for sv2 datatypes#2074

Open
lucasbalieiro wants to merge 3 commits intostratum-mining:mainfrom
lucasbalieiro:add-fuzz-targets-datatypes
Open

Add fuzz targets for sv2 datatypes#2074
lucasbalieiro wants to merge 3 commits intostratum-mining:mainfrom
lucasbalieiro:add-fuzz-targets-datatypes

Conversation

@lucasbalieiro
Copy link
Collaborator

closes #2062.

this PR introduces a single fuzz target that covers all Sv2 datatypes and removes the outdated per-datatype targets.

because the number of datatypes is large, maintaining one fuzz target per type would create significant duplication and overhead. Instead, this follows the same consolidated fuzzing approach we adopted for Sv2 messages in #2028.

While broad fuzz targets are generally discouraged, the same justification applies here: Sv2 datatypes share a common construction pattern, so grouping them provides good coverage without meaningful loss of effectiveness. See the rationale discussed in #2028: #2028 (comment)

@lucasbalieiro lucasbalieiro changed the title Add fuzz targets datatypes Add fuzz targets for sv2 datatypes Feb 3, 2026
@lucasbalieiro lucasbalieiro marked this pull request as ready for review February 3, 2026 19:43
@lucasbalieiro
Copy link
Collaborator Author

@erickcestari, just pinging you to see if you have the time to review it also.

@lucasbalieiro
Copy link
Collaborator Author

as discussed in today’s dev call regarding coverage paths, this PR closes #2062 because the new fuzz targets exercise all critical public entry points that accept untrusted data, primarily from_bytes and to_bytes.

After reviewing the binary_sv2 coverage report: https://stratum-mining.github.io/stratum-fuzzing-corpus

we still see large red regions suggesting low coverage. However, this appears to be largely artificial. Many of the uncovered sections correspond to code paths that are effectively unused.

One example is: stratum/sv2/binary-sv2/src/codec/impls.rs
image

Several impl blocks in that file can be removed without affecting compilation or unit tests, which indicates they are dead code rather than missed fuzz coverage.

Another potentially confusing case is: stratum/sv2/binary-sv2/src/lib.rs
image

These functions appear uncovered because they are thin wrappers around the Encodable / Decodable traits. In practice, they are exercised through the Serialize / Deserialize derive macros, which reach the same to_bytes / from_bytes implementations via a different call path. For example, message types use the macro-generated path:

#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
pub struct ChannelEndpointChanged {
/// Unique identifier of the channel that has changed its endpoint.
pub channel_id: u32,
}

The remaining uncovered areas are mostly:

  • unimplemented!() placeholders
  • defensive error branches
  • edge cases better validated with prop-tests or struct-aware fuzzing

In other words, the fuzzing effort covers the meaningful attack surface (untrusted parsing and serialization), and the apparent gaps are largely artifacts of reporting rather than real blind spots.

@lucasbalieiro lucasbalieiro force-pushed the add-fuzz-targets-datatypes branch from 5dd080f to a4be349 Compare February 4, 2026 14:38
Copy link
Contributor

@erickcestari erickcestari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The macro is a nice cleanup that reduces duplication. However, applying the same buffer to every type wastes ~98% of work on failed parses.

Using the first byte as a selector lets the fuzzer learn which paths are interesting:
https://appsec.guide/docs/fuzzing/techniques/writing-harnesses/#interleaved-fuzzing

#![no_main]
mod common;
use binary_sv2::{...};
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
    if data.is_empty() { return; }
    
    let selector = data[0];
    let payload = data[1..].to_vec();
    
    match selector % 52 {  // number of types
        0 => test_datatype_roundtrip!(PubKey, payload),
        1 => test_datatype_roundtrip!(Signature, payload),
        2 => test_datatype_roundtrip!(Str0255, payload),
        // ... etc
        _ => unreachable!(),
    }
});

@lucasbalieiro lucasbalieiro force-pushed the add-fuzz-targets-datatypes branch from 18bb340 to 1787255 Compare February 6, 2026 03:14
@lucasbalieiro lucasbalieiro force-pushed the add-fuzz-targets-datatypes branch from 1787255 to d574416 Compare February 6, 2026 03:17
@lucasbalieiro
Copy link
Collaborator Author

@erickcestari, thanks for this insight.

I also adapted the other targets that we have for the messages with this strategy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add fuzz coverage to binary_sv2

2 participants