Repository navigation
feat(fuzz): add a cargo-fuzz crate for the P2P wire parsers and req/resp codec - #768
Draft
pablodeymo wants to merge 1 commit into
Draft
pablodeymo wants to merge 1 commit into
pablodeymo wants to merge 1 commit into
Conversation
input path, so every parser a peer's bytes reach is fuzzed and not only unit-tested: snappy, varint and chunked-response framing, topic strings, ENRs, the lean and beacon gossip and req/resp containers, XMSS material, the gossipsub message id, and the req/resp Codec itself driven over an in-memory cursor for every lean and beacon protocol. The crate is its own workspace on a pinned nightly so libfuzzer and nightly stay out of the production build, pins libssz and the libp2p fork to the workspace's revs, and its lockfile joins the cooldown check. ethlambda-p2p gains a `fuzzing` feature, off by default, that re-exports the crate-private helpers the targets need. Makefile targets and docs/fuzzing.md cover running, reproducing and minimising; there is no CI job yet. The varint target already finds a latent shift overflow in decode_varint on a sixth continuation byte, unreachable from the wire because read_varint stops at five; the fix is left for its own PR.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🗒️ Description / Motivation
ethlambda had no fuzzing. Every byte a remote peer sends goes through a
parser (snappy, varint, chunked response framing, SSZ containers, topic
strings, ENRs) and then the req/resp
Codec, and none of that wasexercised beyond hand-written unit tests and the spec fixtures. A panic or
an unbounded allocation anywhere on that path is a remote crash of the
node.
This adds a
cargo-fuzz(libFuzzer) crate atfuzz/, with sixteencoverage-guided targets over the P2P input path, bottom-up: the wire
parsers first (layer 0), then the framing and the real
Codecas libp2pdrives it, over an in-memory cursor with no runtime (layer 1). It copies
the layout and workflow shape of
lambdaclass/libssz's fuzz crate so thetooling is familiar. Generic SSZ decoding is not fuzzed here: libssz already
fuzzes it, differentially against lighthouse's
ethereum_ssz.Deliberately not in this PR: a CI job (the targets are run by hand for
now; a smoke/nightly workflow is a follow-up), the validation rules with a
store (layer 2) and a hostile-peer driver against the live actor (layer 3).
What Changed
fuzz/: a separate cargo workspace on the pinned nightly(
fuzz/rust-toolchain.toml, the same date the cooldown check installs),so
libfuzzer-sysand nightly never enter the production lockfile orbuild. Its lockfile is committed and covered by
make cooldown-check.src/lib.rs: two helpers, a selector-bytesplitand a once-builtConfig::mainnet().fuzz_targets/: sixteen targets, each documenting its property at thetop. Layer 0:
snappy_raw,topic_strings,enr_parse,lean_gossip_ssz,lean_req_resp_ssz,beacon_gossip_decode,beacon_slot_readers,beacon_status_metadata,beacon_container_ssz,xmss_decode. Layer 1:varint,snappy_framed,chunked_response,codec_lean,codec_beacon,message_id.crates/net/p2p: afuzzingcargo feature, off by default, thatre-exports the crate-private gossip codec helpers, the lean topic parser,
the req/resp framing functions, the codec (as
ReqRespCodec, sinceCodecis already a name at the crate root) and a wrapper over theprivate message-id function. The production API is unchanged.
Makefile:fuzz-list,fuzz FUZZ_TARGET=<name>,fuzz-smoke FUZZ_SECONDS=<n>;fuzz/Cargo.tomladded to the cooldown check'smanifest list.
docs/fuzzing.md(linked from the mdbook index): how to run, reproduceand minimise, the target table, the design and the crash policy.
Correctness / Behavior Guarantees
feature-gated set of
pub uselines and one feature-gated wrapperfunction in
ethlambda-p2p.fuzz/Cargo.tomlpins libssz and the libp2p fork to the same revs theworkspace does, so the targets cannot fuzz a different decoder or build a
different
StreamProtocoltype than the node ships.whatever the header claims; compress/decompress and write/read round trips
are the identity; the slot readers agree with the full decode; chunked
responses never exceed their limit; a request or response the codec read
writes and reads back the same.
Tests Added / Run
cargo fuzz build) and ran 20 s under-timeout=10 -rss_limit_mb=2048. Fifteen are clean.varinttrips onff ff ff ff ff 0a.decode_varint(req_resp/encoding.rs:320) shifts by 35 bits on a sixthcontinuation byte, a panic with overflow checks and a silent wrap without.
Not reachable from the wire: its only production caller,
read_varint,stops after five bytes. The fix (bound the loop, regression test) is left
for its own PR per the crash policy in
docs/fuzzing.md; until then thisone target fails immediately.
cargo clippy -p ethlambda-p2p --features fuzzing -- -D warnings: clean.cargo test -p ethlambda-p2p --profile release-fast: passing.make cooldown-checkwith the fuzz lockfile included: clean.Related Issues / PRs
decode_varint; a fuzz CI workflow (smoke per PR, nightlywith a cached corpus); layer 2 and 3 targets.
✅ Verification Checklist
make fmt— cleanmake lint(clippy with-D warnings) — cleanmake test(test-consensusplustest-node, atrelease-fast) — onlyethlambda-p2p's tests run locally; no other crate's code changed