npx skills add https://github.com/trailofbits/skills --skill cargo-fuzzcargo-fuzz 是使用 Cargo 进行 Rust 项目模糊测试的实际首选工具。它使用 libFuzzer 作为后端,并提供了一个方便的 Cargo 子命令,可自动为你的 Rust 项目启用相关的编译标志,包括对 AddressSanitizer 等消毒器的支持。
cargo-fuzz 是目前使用 Cargo 的 Rust 项目主要且最成熟的模糊测试解决方案。
| 模糊测试工具 | 最适合 | 复杂度 |
|---|---|---|
| cargo-fuzz | 基于 Cargo 的 Rust 项目,快速设置 | 低 |
| AFL++ | 多核模糊测试,非 Cargo 项目 | 中 |
| LibAFL | 自定义模糊测试器,研究,高级用例 | 高 |
在以下情况选择 cargo-fuzz:
#![no_main]
use libfuzzer_sys::fuzz_target;
fn harness(data: &[u8]) {
your_project::check_buf(data);
}
fuzz_target!(|data: &[u8]| {
harness(data);
});
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
初始化和运行:
cargo fuzz init
# 使用你的测试工具编辑 fuzz/fuzz_targets/fuzz_target_1.rs
cargo +nightly fuzz run fuzz_target_1
cargo-fuzz 需要 nightly 版本的 Rust 工具链,因为它使用了仅在 nightly 版本中可用的功能。
# 安装 nightly 工具链
rustup install nightly
# 安装 cargo-fuzz
cargo install cargo-fuzz
cargo +nightly --version
cargo fuzz --version
当你的代码结构化为库 crate 时,cargo-fuzz 效果最佳。如果你有一个二进制项目,请将你的 main.rs 拆分为:
src/main.rs # 入口点(main 函数)
src/lib.rs # 要模糊测试的代码(公共函数)
Cargo.toml
初始化模糊测试:
cargo fuzz init
这将创建:
fuzz/
├── Cargo.toml
└── fuzz_targets/
└── fuzz_target_1.rs
#![no_main]
use libfuzzer_sys::fuzz_target;
fn harness(data: &[u8]) {
// 1. 如果需要,验证输入大小
if data.is_empty() {
return;
}
// 2. 使用模糊数据调用目标函数
your_project::target_function(data);
}
fuzz_target!(|data: &[u8]| {
harness(data);
});
| 应该做 | 不应该做 |
|---|---|
| 将代码结构化为库 crate | 将所有代码保留在 main.rs 中 |
使用 fuzz_target! 宏 | 编写自定义 main 函数 |
优雅地处理 Result::Err | 在预期错误时 panic |
| 保持测试工具确定性 | 使用随机数生成器 |
另请参阅: 关于详细的测试工具编写技术以及使用
arbitrarycrate 进行结构感知模糊测试,请参阅 fuzz-harness-writing 技术技能。
cargo-fuzz 与 arbitrary crate 集成,用于结构感知模糊测试:
// 在你的库 crate 中
use arbitrary::Arbitrary;
#[derive(Debug, Arbitrary)]
pub struct Name {
data: String
}
// 在你的模糊测试目标中
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: your_project::Name| {
data.check_buf();
});
添加到你的库的 Cargo.toml:
[dependencies]
arbitrary = { version = "1", features = ["derive"] }
cargo +nightly fuzz run fuzz_target_1
如果你的项目不使用 unsafe Rust,禁用消毒器以获得 2 倍性能提升:
cargo +nightly fuzz run --sanitizer none fuzz_target_1
检查你的项目是否使用了 unsafe 代码:
cargo install cargo-geiger
cargo geiger
# 运行特定的测试用例(例如,一个崩溃)
cargo +nightly fuzz run fuzz_target_1 fuzz/artifacts/fuzz_target_1/crash-<hash>
# 运行所有语料库条目而不进行模糊测试
cargo +nightly fuzz run fuzz_target_1 fuzz/corpus/fuzz_target_1 -- -runs=0
cargo +nightly fuzz run fuzz_target_1 -- -dict=./dict.dict
| 输出 | 含义 |
|---|---|
NEW | 发现了新的增加覆盖率的输入 |
pulse | 周期性状态更新 |
INITED | 模糊测试器初始化成功 |
| 带有堆栈跟踪的崩溃 | 发现错误,已保存到 fuzz/artifacts/ |
语料库位置:fuzz/corpus/fuzz_target_1/ 崩溃位置:fuzz/artifacts/fuzz_target_1/
ASan 默认启用,用于检测内存错误:
cargo +nightly fuzz run fuzz_target_1
对于纯安全 Rust(你的代码或依赖项中没有 unsafe 块):
cargo +nightly fuzz run --sanitizer none fuzz_target_1
性能影响: ASan 增加约 2 倍开销。对于安全 Rust,禁用以提高模糊测试速度。
cargo install cargo-geiger
cargo geiger
另请参阅: 关于详细的消毒器配置、标志和故障排除,请参阅 address-sanitizer 技术技能。
cargo-fuzz 与 Rust 的覆盖率工具集成,以分析模糊测试的有效性。
rustup toolchain install nightly --component llvm-tools-preview
cargo install cargo-binutils
cargo install rustfilt
# 从语料库生成覆盖率数据
cargo +nightly fuzz coverage fuzz_target_1
创建覆盖率生成脚本:
cat <<'EOF' > ./generate_html
#!/bin/sh
if [ $# -lt 1 ]; then
echo "Error: Name of fuzz target is required."
echo "Usage: $0 fuzz_target [sources...]"
exit 1
fi
FUZZ_TARGET="$1"
shift
SRC_FILTER="$@"
TARGET=$(rustc -vV | sed -n 's|host: ||p')
cargo +nightly cov -- show -Xdemangler=rustfilt \
"target/$TARGET/coverage/$TARGET/release/$FUZZ_TARGET" \
-instr-profile="fuzz/coverage/$FUZZ_TARGET/coverage.profdata" \
-show-line-counts-or-regions -show-instantiations \
-format=html -o fuzz_html/ $SRC_FILTER
EOF
chmod +x ./generate_html
生成 HTML 报告:
./generate_html fuzz_target_1 src/lib.rs
HTML 报告保存到:fuzz_html/
另请参阅: 关于详细的覆盖率分析技术和系统性覆盖率改进,请参阅 coverage-analysis 技术技能。
| 提示 | 为何有帮助 |
|---|---|
| 从种子语料库开始 | 显著加快初始覆盖率发现速度 |
对安全 Rust 使用 --sanitizer none | 2 倍性能提升 |
| 定期检查覆盖率 | 识别测试工具或种子语料库中的空白 |
| 对解析器使用字典 | 帮助克服魔数检查 |
| 将代码结构化为库 | cargo-fuzz 集成所必需 |
在 -- 之后传递选项给 libFuzzer:
# 查看所有选项
cargo +nightly fuzz run fuzz_target_1 -- -help=1
# 设置每次运行的超时时间
cargo +nightly fuzz run fuzz_target_1 -- -timeout=10
# 使用字典
cargo +nightly fuzz run fuzz_target_1 -- -dict=dict.dict
# 限制最大输入大小
cargo +nightly fuzz run fuzz_target_1 -- -max_len=1024
# 实验性的分叉支持(不推荐)
cargo +nightly fuzz run --jobs 1 fuzz_target_1
注意:多核模糊测试功能是实验性的,不推荐使用。对于并行模糊测试,请考虑手动运行多个实例或使用 AFL++。
ogg crate 解析 Ogg 媒体容器文件。解析器是极佳的模糊测试目标,因为它们处理不受信任的数据。
# 克隆并初始化
git clone https://github.com/RustAudio/ogg.git
cd ogg/
cargo fuzz init
测试工具位于 fuzz/fuzz_targets/fuzz_target_1.rs:
#![no_main]
use ogg::{PacketReader, PacketWriter};
use ogg::writing::PacketWriteEndInfo;
use std::io::Cursor;
use libfuzzer_sys::fuzz_target;
fn harness(data: &[u8]) {
let mut pck_rdr = PacketReader::new(Cursor::new(data.to_vec()));
pck_rdr.delete_unread_packets();
let output = Vec::new();
let mut pck_wtr = PacketWriter::new(Cursor::new(output));
if let Ok(_) = pck_rdr.read_packet() {
if let Ok(r) = pck_rdr.read_packet() {
match r {
Some(pck) => {
let inf = if pck.last_in_stream() {
PacketWriteEndInfo::EndStream
} else if pck.last_in_page() {
PacketWriteEndInfo::EndPage
} else {
PacketWriteEndInfo::NormalPacket
};
let stream_serial = pck.stream_serial();
let absgp_page = pck.absgp_page();
let _ = pck_wtr.write_packet(
pck.data, stream_serial, inf, absgp_page
);
}
None => return,
}
}
}
}
fuzz_target!(|data: &[u8]| {
harness(data);
});
种子语料库:
mkdir fuzz/corpus/fuzz_target_1/
curl -o fuzz/corpus/fuzz_target_1/320x240.ogg \
https://commons.wikimedia.org/wiki/File:320x240.ogg
运行:
cargo +nightly fuzz run fuzz_target_1
分析覆盖率:
cargo +nightly fuzz coverage fuzz_target_1
./generate_html fuzz_target_1 src/lib.rs
| 问题 | 原因 | 解决方案 |
|---|---|---|
| "requires nightly" 错误 | 使用 stable 工具链 | 使用 cargo +nightly fuzz |
| 模糊测试性能慢 | 对安全 Rust 启用了 ASan | 添加 --sanitizer none 标志 |
| "cannot find binary" | 没有库 crate | 将代码从 main.rs 移动到 lib.rs |
| 消毒器编译问题 | nightly 版本错误 | 尝试不同的 nightly:rustup install nightly-2024-01-01 |
| 覆盖率低 | 缺少种子语料库 | 添加样本输入到 fuzz/corpus/fuzz_target_1/ |
| 未找到魔数 | 没有字典 | 创建包含魔数的字典文件 |
| 技能 | 用例 |
|---|---|
| fuzz-harness-writing | 使用 arbitrary crate 进行结构感知模糊测试 |
| address-sanitizer | 理解 ASan 输出和配置 |
| coverage-analysis | 测量和提高模糊测试有效性 |
| fuzzing-corpus | 构建和管理种子语料库 |
| fuzzing-dictionaries | 为格式感知模糊测试创建字典 |
| 技能 | 何时考虑 |
|---|---|
| libfuzzer | 使用类似工作流程模糊测试 C/C++ 代码 |
| aflpp | 多核模糊测试或非 Cargo Rust 项目 |
| libafl | 高级模糊测试研究或自定义模糊测试器开发 |
Rust Fuzz Book - cargo-fuzz cargo-fuzz 的官方文档,涵盖安装、使用和高级功能。
arbitrary crate 文档 使用 Rust 类型的自动派生进行结构感知模糊测试的指南。
cargo-fuzz GitHub 仓库 cargo-fuzz 的源代码、问题跟踪器和示例。
每周安装量
1.1K
仓库
GitHub Stars
3.9K
首次出现
Jan 19, 2026
安全审计
安装于
claude-code990
opencode944
gemini-cli921
codex918
cursor896
github-copilot861
cargo-fuzz is the de facto choice for fuzzing Rust projects when using Cargo. It uses libFuzzer as the backend and provides a convenient Cargo subcommand that automatically enables relevant compilation flags for your Rust project, including support for sanitizers like AddressSanitizer.
cargo-fuzz is currently the primary and most mature fuzzing solution for Rust projects using Cargo.
| 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 |
Choose cargo-fuzz when:
#![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
cargo-fuzz requires the nightly Rust toolchain because it uses features only available in nightly.
# Install nightly toolchain
rustup install nightly
# Install cargo-fuzz
cargo install cargo-fuzz
cargo +nightly --version
cargo fuzz --version
cargo-fuzz works best when your code is structured as a library crate. If you have a binary project, split your main.rs into:
src/main.rs # Entry point (main function)
src/lib.rs # Code to fuzz (public functions)
Cargo.toml
Initialize fuzzing:
cargo fuzz init
This creates:
fuzz/
├── Cargo.toml
└── fuzz_targets/
└── fuzz_target_1.rs
#![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);
});
| 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 |
See Also: For detailed harness writing techniques and structure-aware fuzzing with the
arbitrarycrate, see the fuzz-harness-writing technique skill.
cargo-fuzz integrates with the arbitrary crate for structure-aware fuzzing:
// In your library crate
use arbitrary::Arbitrary;
#[derive(Debug, Arbitrary)]
pub struct Name {
data: String
}
// In your fuzz target
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: your_project::Name| {
data.check_buf();
});
Add to your library's Cargo.toml:
[dependencies]
arbitrary = { version = "1", features = ["derive"] }
cargo +nightly fuzz run fuzz_target_1
If your project doesn't use unsafe Rust, disable sanitizers for 2x performance boost:
cargo +nightly fuzz run --sanitizer none fuzz_target_1
Check if your project uses unsafe code:
cargo install cargo-geiger
cargo geiger
# Run a specific test case (e.g., a crash)
cargo +nightly fuzz run fuzz_target_1 fuzz/artifacts/fuzz_target_1/crash-<hash>
# Run all corpus entries without fuzzing
cargo +nightly fuzz run fuzz_target_1 fuzz/corpus/fuzz_target_1 -- -runs=0
cargo +nightly fuzz run fuzz_target_1 -- -dict=./dict.dict
| 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/
ASan is enabled by default and detects memory errors:
cargo +nightly fuzz run fuzz_target_1
For pure safe Rust (no unsafe blocks in your code or dependencies):
cargo +nightly fuzz run --sanitizer none fuzz_target_1
Performance impact: ASan adds ~2x overhead. Disable for safe Rust to improve fuzzing speed.
cargo install cargo-geiger
cargo geiger
See Also: For detailed sanitizer configuration, flags, and troubleshooting, see the address-sanitizer technique skill.
cargo-fuzz integrates with Rust's coverage tools to analyze fuzzing effectiveness.
rustup toolchain install nightly --component llvm-tools-preview
cargo install cargo-binutils
cargo install rustfilt
# Generate coverage data from corpus
cargo +nightly fuzz coverage fuzz_target_1
Create coverage generation script:
cat <<'EOF' > ./generate_html
#!/bin/sh
if [ $# -lt 1 ]; then
echo "Error: Name of fuzz target is required."
echo "Usage: $0 fuzz_target [sources...]"
exit 1
fi
FUZZ_TARGET="$1"
shift
SRC_FILTER="$@"
TARGET=$(rustc -vV | sed -n 's|host: ||p')
cargo +nightly cov -- show -Xdemangler=rustfilt \
"target/$TARGET/coverage/$TARGET/release/$FUZZ_TARGET" \
-instr-profile="fuzz/coverage/$FUZZ_TARGET/coverage.profdata" \
-show-line-counts-or-regions -show-instantiations \
-format=html -o fuzz_html/ $SRC_FILTER
EOF
chmod +x ./generate_html
Generate HTML report:
./generate_html fuzz_target_1 src/lib.rs
HTML report saved to: fuzz_html/
See Also: For detailed coverage analysis techniques and systematic coverage improvement, see the coverage-analysis technique skill.
| 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 |
Pass options to libFuzzer after --:
# 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
# Use dictionary
cargo +nightly fuzz run fuzz_target_1 -- -dict=dict.dict
# Limit maximum input size
cargo +nightly fuzz run fuzz_target_1 -- -max_len=1024
# Experimental forking support (not recommended)
cargo +nightly fuzz run --jobs 1 fuzz_target_1
Note: The multi-core fuzzing feature is experimental and not recommended. For parallel fuzzing, consider running multiple instances manually or using AFL++.
The ogg crate parses Ogg media container files. Parsers are excellent fuzzing targets because they handle untrusted data.
# Clone and initialize
git clone https://github.com/RustAudio/ogg.git
cd ogg/
cargo fuzz init
Harness at fuzz/fuzz_targets/fuzz_target_1.rs:
#![no_main]
use ogg::{PacketReader, PacketWriter};
use ogg::writing::PacketWriteEndInfo;
use std::io::Cursor;
use libfuzzer_sys::fuzz_target;
fn harness(data: &[u8]) {
let mut pck_rdr = PacketReader::new(Cursor::new(data.to_vec()));
pck_rdr.delete_unread_packets();
let output = Vec::new();
let mut pck_wtr = PacketWriter::new(Cursor::new(output));
if let Ok(_) = pck_rdr.read_packet() {
if let Ok(r) = pck_rdr.read_packet() {
match r {
Some(pck) => {
let inf = if pck.last_in_stream() {
PacketWriteEndInfo::EndStream
} else if pck.last_in_page() {
PacketWriteEndInfo::EndPage
} else {
PacketWriteEndInfo::NormalPacket
};
let stream_serial = pck.stream_serial();
let absgp_page = pck.absgp_page();
let _ = pck_wtr.write_packet(
pck.data, stream_serial, inf, absgp_page
);
}
None => return,
}
}
}
}
fuzz_target!(|data: &[u8]| {
harness(data);
});
Seed the corpus:
mkdir fuzz/corpus/fuzz_target_1/
curl -o fuzz/corpus/fuzz_target_1/320x240.ogg \
https://commons.wikimedia.org/wiki/File:320x240.ogg
Run:
cargo +nightly fuzz run fuzz_target_1
Analyze coverage:
cargo +nightly fuzz coverage fuzz_target_1
./generate_html fuzz_target_1 src/lib.rs
| 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 |
| Sanitizer compilation issues | Wrong nightly version | Try different nightly: rustup install nightly-2024-01-01 |
| Low coverage |
| Skill | Use Case |
|---|---|
| fuzz-harness-writing | Structure-aware fuzzing with arbitrary crate |
| address-sanitizer | Understanding ASan output and configuration |
| coverage-analysis | Measuring and improving fuzzing effectiveness |
| fuzzing-corpus | Building and managing seed corpora |
| fuzzing-dictionaries | Creating dictionaries for format-aware fuzzing |
| Skill | When to Consider |
|---|---|
| libfuzzer | Fuzzing C/C++ code with similar workflow |
| aflpp | Multi-core fuzzing or non-Cargo Rust projects |
| libafl | Advanced fuzzing research or custom fuzzer development |
Rust Fuzz Book - cargo-fuzz Official documentation for cargo-fuzz covering installation, usage, and advanced features.
arbitrary crate documentation Guide to structure-aware fuzzing with automatic derivation for Rust types.
cargo-fuzz GitHub Repository Source code, issue tracker, and examples for cargo-fuzz.
Weekly Installs
1.1K
Repository
GitHub Stars
3.9K
First Seen
Jan 19, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykWarn
Installed on
claude-code990
opencode944
gemini-cli921
codex918
cursor896
github-copilot861
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
NestJS专家服务 | 企业级TypeScript后端开发与架构设计
1,000 周安装
安全代码卫士:AI驱动的安全编码指南与最佳实践,防止SQL注入、XSS攻击
1,000 周安装
ESLint迁移到Oxlint完整指南:JavaScript/TypeScript项目性能优化工具
1,000 周安装
Chrome CDP 命令行工具:轻量级浏览器自动化,支持截图、执行JS、无障碍快照
1,000 周安装
Sanity内容建模最佳实践:结构化内容设计原则与无头CMS指南
1,000 周安装
AI Sprint规划器 - 敏捷团队Scrum迭代计划工具,自动估算故事点与容量管理
1,000 周安装
| Missing seed corpus |
Add sample inputs to fuzz/corpus/fuzz_target_1/ |
| Magic value not found | No dictionary | Create dictionary file with magic values |