cargo-fuzz

repository·main·Indexed 23 days ago

https://github.com/rust-fuzz/cargo-fuzz

A cargo subcommand for fuzzing Rust code using libFuzzer. It provides tools to initialize fuzzing projects, manage targets, and debug failing inputs. Key features include support for LLVM sanitizers (address, leak, memory, thread), corpus minimization via `cmin`, test case minimization via `tmin`, and coverage analysis. Requires a Rust nightly compiler and a C++ compiler with C++11 support on Unix-like operating systems (x86-64 or Aarch64).

Tokens
3.5K
Snippets
2
Records
30
Agent score
78%

What's inside cargo-fuzz

  1. Install cargo-fuzz

    main

    Install the cargo-fuzz subcommand using cargo install.

    Prerequisites:

    • OS: Unix-like operating systems only (not Windows).
    • Architecture: x86-64 or Aarch64.
    • Compiler: A Rust nightly compiler (required for unstable command-line flags) and a C++ compiler with C++11 support.
    • Dependencies: libFuzzer requires LLVM sanitizer support.
    $ cargo install cargo-fuzz
  2. Initialize a cargo fuzz project

    main

    Use cargo fuzz init to set up a fuzzing project for your crate.

    Workspace Configuration:

    • Standard Workspace: By default, the fuzz directory is created as part of your existing workspace.
    • Independent Workspace: If you want the fuzz directory to use an independent workspace, use the --fuzzing-workspace=true flag.
    • Manual Step for Workspaces: If your crate uses cargo workspaces, you must manually add the fuzz directory to the workspace.members list in your root Cargo.toml.
  3. Identify a `cargo-fuzz` project via Cargo.toml

    main

    The tool identifies a directory as a cargo-fuzz project by checking the Cargo.toml manifest. A manifest is considered a fuzz manifest if it contains the following TOML structure:

    [package.metadata.cargo-fuzz]
    # This must be set to true
    true = true

    When running commands, cargo-fuzz searches upwards from the current working directory to find the first Cargo.toml that is not a fuzz manifest, which it then treats as the root of the actual Rust crate being fuzzed.

  4. Understand the `cargo-fuzz` project directory structure

    main

    A cargo-fuzz project organizes its data into several specific subdirectories within the fuzzing directory. Understanding these paths is useful for manual inspection or custom automation:

    • Fuzz Targets: Located in fuzz/fuzz_targets/ (formerly fuzz/fuzzers/). This is where your .rs fuzz target files reside.
    • Corpus: Located in fuzz/corpus/<target>/. This directory stores the input files used by the fuzzer to find new paths.
    • Coverage: Located in fuzz/coverage/<target>/. This contains coverage.profdata and a raw directory for coverage data.
    • Artifacts: Located in fuzz/artifacts/<target>/. This directory is used by libFuzzer to store crashing inputs (note that the directory ends with a trailing slash to satisfy libFuzzer's path joining requirements).
  5. Initialize a new fuzzing project

    main

    To start fuzzing a Rust crate, you must initialize a fuzzing project structure. This creates a fuzz directory containing a Cargo.toml (with necessary metadata), a .gitignore, and a template for your first fuzz target.

    Note: If your crate uses cargo workspaces, you must manually add the fuzz directory to the workspace.members list in your root Cargo.toml.

  6. Add a new fuzz target

    main
    Once a fuzz project is initialized, you can add new fuzz targets. Adding a target creates the necessary target script file, sets up the target's specific corpus and artifacts directories, and updates the fuzz/Cargo.toml manifest to include the new binary.
  7. Generate coverage information

    main
    Generate code coverage reports for a specific target using a given corpus. This requires the project to be built with source-based coverage enabled. The tool will process the input files in parallel and merge the resulting raw coverage data into a single output file using llvm-profdata.
  8. Run a fuzz target

    main

    Execute the fuzzer on a specific target. If the fuzzer discovers a crashing input, it will save it as an artifact and print a summary including:

    • The path to the failing input.
    • The std::fmt::Debug output of the input (if supported).
    • Commands to reproduce the crash using cargo fuzz run or minimize it using cargo fuzz tmin.