Fuzzing
Find edge cases, crashes, and security vulnerabilities by testing your code against millions of random inputs.
Fuzzing is especially valuable for testing code that handles untrusted data like parsers, file format handlers, and network protocols.
Key Features
- What is Fuzzing?: Understanding fuzzing and its benefits
- When to Use Fuzzing: Identifying good candidates for fuzz testing
- Writing Fuzz Targets: Creating effective fuzz tests
- Running Fuzz Tests: VSCode and command-line usage
- Integrate with Non-Template Projects: Adding fuzzing to existing projects
What is Fuzzing?
Fuzzing in Simple Terms
Fuzzing is a testing technique that automatically generates random or semi-random inputs to find bugs your unit tests might miss.
Fuzzing works by:
- Generating random input data (bytes, strings, structured data)
- Feeding that data to your code
- Watching for crashes, panics, or assertion failures
- Saving inputs that cause problems so you can reproduce and fix bugs
What Can Fuzzing Find?
- Buffer overflows and out-of-bounds access
- Panics on malformed or unexpected input
- Infinite loops or excessive memory usage
- Integer overflows and arithmetic errors
- Logic errors in edge cases
When to Use Fuzzing
When to Use Fuzzing
Fuzzing is most valuable for code that processes external or untrusted input.
Consider fuzzing if your project:
- Parses file formats (images, documents, configs)
- Handles network protocols or serialized data
- Processes user input that could be malformed
- Uses
unsafecode with complex invariants
Fuzzing vs Unit Tests
Unit tests check specific cases you think of. Fuzzing explores inputs you didn't anticipate.
Use both: unit tests for known scenarios, fuzzing to discover unknown edge cases.
Writing Fuzz Targets
A fuzz target is a function that receives random input and passes it to your code.
Basic Fuzz Target:
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
// fuzzed code goes here
});
Example: Fuzzing a Parser:
#![no_main]
use libfuzzer_sys::fuzz_target;
use my_library::parse_config;
fuzz_target!(|data: &[u8]| {
// Convert bytes to string, ignore invalid UTF-8
if let Ok(input) = std::str::from_utf8(data) {
// Your parser should handle any input without panicking
let _ = parse_config(input);
}
});
Writing Effective Fuzz Targets
- Start with simple byte slice input (
&[u8]) - Don't panic on invalid input-return early instead
- Test one entry point per fuzz target
- Use
arbitrarycrate for structured input when needed
Fuzz targets live in fuzz/fuzz_targets/. The template includes fuzz_example.rs as a starting point.
Running Fuzz Tests
Fuzzing requires nightly Rust
Fuzzing uses unstable compiler features. Commands use cargo +nightly to select the nightly toolchain.
Using VSCode Tasks:
Press Ctrl+Shift+P → "Run Task" → Select List Fuzz Targets to see available targets.
Using Command Line:
cd src
# Run the default fuzz target
cargo +nightly fuzz run fuzz_example
# List all available fuzz targets
cargo +nightly fuzz list
# Run with a time limit (60 seconds)
cargo +nightly fuzz run fuzz_example -- -max_total_time=60
Windows Setup:
Windows requires additional setup
Follow the Windows setup guide before fuzzing on Windows.
Run fuzz commands from Developer PowerShell for VS 20XX or x64 Native Tools Command Prompt for VS 20XX to ensure the MSVC linker is available.
When a Bug is Found:
Fuzzing saves crash-inducing inputs to fuzz/artifacts/fuzz_example/. Use these to reproduce and fix bugs:
# Reproduce a crash
cargo +nightly fuzz run fuzz_example fuzz/artifacts/fuzz_example/crash-xxxxx
Integrate with Non-Template Projects
Info
If your project was not built on Reloaded template, here's how you can add fuzzing.
Install cargo-fuzz:
cargo install cargo-fuzz
Initialize fuzzing in your project:
cd src # or your project root
cargo fuzz init
This creates a fuzz/ directory with a basic fuzz target.
Create a fuzz target:
Edit fuzz/fuzz_targets/fuzz_example.rs (or create a new target):
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
// Call your code with random input
});
VSCode Tasks Setup
Add Fuzz Tasks to VSCode
Add this task to your .vscode/tasks.json file to easily list available fuzz targets.
Add this task configuration to your .vscode/tasks.json (create the file if it doesn't exist):
{
"version": "2.0.0",
"tasks": [
{
"label": "List Fuzz Targets",
"type": "shell",
"command": "cargo install cargo-fuzz --quiet && cargo +nightly fuzz list",
"group": "test",
"presentation": {
"reveal": "always"
},
"problemMatcher": []
}
]
}
Running Fuzz Targets
Run fuzz targets from the command line: cargo +nightly fuzz run <target_name>
Each fuzz target file includes the run command in its header comment for easy reference.