Add fuzzing coverage for the mesh stack
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 1.9k
- Forks
- 238
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 100
Description
Add fuzzing coverage for the mesh stack
Summary
In sync, we landed on a staged fuzzing plan for mesh.
I want to build this on top of the fuzzing infrastructure that already exists in the repo instead of inventing something new. The priority order should be:
mesh_protobuffirstmesh_channel_corenextmesh_remoteas a follow-onmesh_nodeout of scope unless later work turns up a concrete reason to pull it in
That gives us a path that is both practical and high-value.
Why this is worth doing
The repo already has a real fuzzing story:
- docs at
Guide/src/dev_guide/tests/fuzzing.md - repo integration in
xtask/src/tasks/fuzz/mod.rs - an existing mesh-adjacent example in
support/mesh/mesh_rpc/fuzz/fuzz_mesh_ttrpc_server.rs
What we do not have today is dedicated fuzz coverage for the core mesh crates themselves.
That leaves a pretty obvious gap:
mesh_protobufis the low-level serialization / deserialization layer and explicitly supports transferring resourcesmesh_channel_coreowns the core channel machinery, including the failure and lifecycle paths that unit tests usually under-covermesh_remoteowns the cross-process transport layer and still contains platform-facing unsafe codemesh_nodelooks lower-risk right now and should not block the rest
I don’t think this needs to be sold as “fuzz all of mesh at once.” The right framing is: start with the highest-value, easiest-to-land targets and stage the rest.
Proposed scope by crate
1. mesh_protobuf
This should be the first landing.
mesh_protobuf lives at support/mesh/mesh_protobuf/ and is the low-level encoding layer behind the mesh derive story. Its src/lib.rs explicitly describes it as the low-level serialization and deserialization layer for mesh messages, including external resources.
The direction here is to add fuzzing for as many generated type patterns as possible, not just one hand-written message type.
That means I want coverage for representative derived shapes such as:
- scalars and scalar-heavy structs
- enums / oneof-style patterns
- nested structs
- vectors and other collection-like shapes
- resource-carrying messages
- wrapper / transparent-style types
I also want both sides of the problem covered:
- malformed input decode
- encode/decode roundtrip behavior for representative generated types
This is the cleanest place to start because it has a well-defined boundary, it is already a serialization layer, and it gives us immediate value without needing to solve the harder transport story first.
2. mesh_channel_core
This should be the second landing.
mesh_channel_core lives at support/mesh/mesh_channel_core/ and is the core channel implementation underneath the higher-level mesh channel APIs.
The important part here is not “send some messages and see if they arrive.” We already know how to write happy-path unit tests for that. The value is in fuzzing the weird lifecycle and failure paths:
- send / recv / close / drop sequencing
- cancellation paths
- closed-channel behavior
- bounded / edge conditions
- oneshot lifecycle edges
- other state-machine paths that are easy to miss with example-based tests
This is where I want operation-sequence or state-machine-style harnesses rather than a single simple byte-to-parser fuzzer.
If mesh_protobuf is the cleanest serialization target, mesh_channel_core is the highest-value “make sure the failure paths are actually robust” target.
3. mesh_remote
This should be a follow-on, not the thing that blocks the first landing.
mesh_remote lives at support/mesh/mesh_remote/ and owns the cross-process transport side of mesh. That is also where the remaining platform-facing unsafe code is concentrated today, especially in the Unix and ALPC implementations.
I do want fuzzing here, but I think the right direction is functional fuzzing, not just hammering raw OS glue in place.
So the plan should be:
- identify a good functional / protocol-level fuzz surface
- peel the remaining unsafe transport-specific pieces into a smaller helper crate or boundary where that makes sense
- then fuzz the higher-level remote behavior against malformed messages, bad sequencing, and transport edge cases
I do not want to block mesh_protobuf and mesh_channel_core on solving all of this first.
In other words: mesh_remote belongs in the plan, but it should be staged after the first two crates, and part of the work here is making the unsafe surface smaller and more explicit before we fuzz across it.
4. mesh_node
mesh_node lives at support/mesh/mesh_node/.
Right now this looks fine to leave out of the initial scope. I don’t want to block the work on a crate that does not look like the highest-payoff fuzz target today.
If later work turns up a specific parser-like surface, unsafe boundary, or failure mode that deserves fuzzing, we can open that up then. For now, I think “should be OK” is the right call.
Why I want this staged
I don’t want this to turn into an all-or-nothing fuzzing project.
A reasonable path is:
- land
mesh_protobuffuzzing first - add
mesh_channel_corefuzzing next - tackle
mesh_remotefunctional fuzzing after that, along with the unsafe-boundary cleanup that makes it tractable - keep
mesh_nodeout unless we find a reason to revisit it
That gives us real coverage quickly, keeps the issue actionable, and avoids making the transport cleanup a blocker for the first win.
Goals
- Add real fuzz targets for the highest-value mesh crates using the existing repo fuzzing infrastructure
- Cover as many representative generated-type patterns as practical in
mesh_protobuf - Exercise failure, cancellation, close, and lifecycle paths in
mesh_channel_core - Create a credible path to functional fuzzing in
mesh_remote - Keep the work incremental enough that we can land it in stages instead of waiting for one giant change
Non-goals
- Fuzz every mesh crate in the first pass
- Block on
mesh_node - Solve all
mesh_remoteunsafe refactoring before we land any mesh fuzzing at all - Turn this into a huge PR-time fuzzing requirement for every change
Validation
For this effort to be successful, I want the new targets to:
- fit into the existing
xtask fuzz/ cargo-fuzz flow - build and run locally
- be reproducible with saved repro inputs
- come with seeded corpora for obvious edge cases
- be in a shape that can later feed longer-running fuzz jobs
Concretely:
mesh_protobufshould tolerate arbitrary input and representative generated-type roundtrips without panics or other obvious unsound behaviormesh_channel_coreshould survive weird lifecycle orderings and failure-path operation sequences without panics or other obvious unsound behaviormesh_remoteshould eventually have at least one functional fuzzing surface after we tighten the unsafe boundary enough to make that a good investment
Rough implementation plan
- Add a new fuzz crate under
support/mesh/mesh_protobuf/fuzz/, modeled after the existing in-tree fuzz crates. - Add one or more
mesh_protobuftargets that cover malformed input decode and representative generated type patterns. - Add
support/mesh/mesh_channel_core/fuzz/with operation-sequence / state-machine harnesses formpscandoneshotbehavior. - Audit
mesh_remoteto identify the best functional fuzz surface and the unsafe transport-specific pieces that should move behind a smaller boundary. - Add at least one
mesh_remotefunctional fuzz target as a follow-on. - Revisit
mesh_nodeonly if the earlier work gives us a concrete reason to do so.
Open questions
- Do we want one broad
mesh_protobuftarget or several smaller targets by generated-pattern family? - How much concurrency do we want in the first
mesh_channel_coreharness versus a simpler single-threaded operation model? - What is the right boundary for shrinking
mesh_remoteunsafe code before fuzzing: helper module, separate crate, or just tighter isolation inside the existing crate?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Guide/src/dev_guide/tests/fuzzing.md and xtask/src/tasks/fuzz/mod.rs, then inspect support/mesh/mesh_protobuf/ and the existing support/mesh/mesh_rpc/fuzz/fuzz_mesh_ttrpc_server.rs example. The initial milestone is fuzzing mesh_protobuf with malformed-input and representative roundtrip targets that build and run through the existing cargo-fuzz flow; mesh_channel_core and mesh_remote are staged follow-ons.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- distributed-systems, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100