skills/5dlabs/cto/cargo-fuzz

cargo-fuzz

Originally fromtrailofbits/skills
SKILL.md

cargo-fuzz

cargo-fuzz is the de facto choice for fuzzing Rust projects using Cargo. It uses libFuzzer as the backend and provides automatic sanitizer support including AddressSanitizer.

When to Use

Choose cargo-fuzz when:

  • Your project uses Cargo (required)
  • You want simple, quick setup with minimal configuration
  • You need integrated sanitizer support
  • You're fuzzing Rust code with or without unsafe blocks
Fuzzer Best For Complexity
cargo-fuzz Cargo-based Rust projects, quick setup Low
AFL++ Multi-core fuzzing, non-Cargo projects Medium
LibAFL Custom fuzzers, research, advanced use cases High

Installation

cargo-fuzz requires the nightly Rust toolchain.

# Install nightly toolchain
rustup install nightly

# Install cargo-fuzz
cargo install cargo-fuzz

# Verify
cargo +nightly fuzz --version

Quick Start

#![no_main]
use libfuzzer_sys::fuzz_target;

fn harness(data: &[u8]) {
    your_project::check_buf(data);
}

fuzz_target!(|data: &[u8]| {
    harness(data);
});

Initialize and run:

cargo fuzz init
# Edit fuzz/fuzz_targets/fuzz_target_1.rs with your harness
cargo +nightly fuzz run fuzz_target_1

Writing a Harness

Project Structure

cargo-fuzz works best when your code is structured as a library crate:

src/
  main.rs    # Entry point (main function)
  lib.rs     # Code to fuzz (public functions)
Cargo.toml
fuzz/
  Cargo.toml
  fuzz_targets/
    fuzz_target_1.rs

Harness Structure

#![no_main]
use libfuzzer_sys::fuzz_target;

fn harness(data: &[u8]) {
    // 1. Validate input size if needed
    if data.is_empty() {
        return;
    }
    
    // 2. Call target function with fuzz data
    your_project::target_function(data);
}

fuzz_target!(|data: &[u8]| {
    harness(data);
});

Harness Rules

Do Don't
Structure code as library crate Keep everything in main.rs
Use fuzz_target! macro Write custom main function
Handle Result::Err gracefully Panic on expected errors
Keep harness deterministic Use random number generators

Structure-Aware Fuzzing

Use the arbitrary crate for structure-aware fuzzing:

// In your library crate
use arbitrary::Arbitrary;

#[derive(Debug, Arbitrary)]
pub struct Config {
    pub timeout: u32,
    pub retries: u8,
    pub data: Vec<u8>,
}
// In your fuzz target
#![no_main]
use libfuzzer_sys::fuzz_target;

fuzz_target!(|config: your_project::Config| {
    your_project::process_config(config);
});

Add to your library's Cargo.toml:

[dependencies]
arbitrary = { version = "1", features = ["derive"] }

Running Campaigns

Basic Run

cargo +nightly fuzz run fuzz_target_1

Without Sanitizers (Safe Rust)

If your project doesn't use unsafe Rust, disable sanitizers for 2x performance:

cargo +nightly fuzz run --sanitizer none fuzz_target_1

Check if your project uses unsafe code:

cargo install cargo-geiger
cargo geiger

Using Dictionaries

cargo +nightly fuzz run fuzz_target_1 -- -dict=./dict.dict

libFuzzer Options

# See all options
cargo +nightly fuzz run fuzz_target_1 -- -help=1

# Set timeout per run
cargo +nightly fuzz run fuzz_target_1 -- -timeout=10

# Limit maximum input size
cargo +nightly fuzz run fuzz_target_1 -- -max_len=1024

Interpreting Output

Output Meaning
NEW New coverage-increasing input discovered
pulse Periodic status update
INITED Fuzzer initialized successfully
Crash with stack trace Bug found, saved to fuzz/artifacts/
  • Corpus location: fuzz/corpus/fuzz_target_1/
  • Crashes location: fuzz/artifacts/fuzz_target_1/

Coverage Analysis

Prerequisites

rustup toolchain install nightly --component llvm-tools-preview
cargo install cargo-binutils
cargo install rustfilt

Generating Coverage Reports

# Generate coverage data from corpus
cargo +nightly fuzz coverage fuzz_target_1

Tips and Tricks

Tip Why It Helps
Start with a seed corpus Dramatically speeds up initial coverage discovery
Use --sanitizer none for safe Rust 2x performance improvement
Check coverage regularly Identifies gaps in harness or seed corpus
Use dictionaries for parsers Helps overcome magic value checks
Structure code as library Required for cargo-fuzz integration

Troubleshooting

Problem Cause Solution
"requires nightly" error Using stable toolchain Use cargo +nightly fuzz
Slow fuzzing performance ASan enabled for safe Rust Add --sanitizer none flag
"cannot find binary" No library crate Move code from main.rs to lib.rs
Low coverage Missing seed corpus Add sample inputs to fuzz/corpus/
Magic value not found No dictionary Create dictionary file with magic values

Example: Parsing Library

#![no_main]
use libfuzzer_sys::fuzz_target;
use std::io::Cursor;

fuzz_target!(|data: &[u8]| {
    let mut reader = Cursor::new(data.to_vec());
    
    // Parse the data - don't panic on expected errors
    if let Ok(parsed) = my_parser::parse(&mut reader) {
        // Optionally re-serialize to check roundtrip
        let _ = my_parser::serialize(&parsed);
    }
});

Attribution

Based on trailofbits/skills cargo-fuzz skill.

Weekly Installs
3
Repository
5dlabs/cto
First Seen
Jan 24, 2026
Installed on
claude-code2
windsurf1
trae1
opencode1
codex1
antigravity1