cargo-fuzzSkill cargo-fuzz

cargo-fuzz 是一个用于Rust项目的模糊测试工具,基于libFuzzer后端和Cargo构建系统,提供快速设置、集成消毒器支持和覆盖率分析。关键词:模糊测试、Rust、Cargo、libFuzzer、测试工具、软件安全。

测试 0 次安装 0 次浏览 更新于 3/24/2026

name: cargo-fuzz type: 模糊测试器 description: > cargo-fuzz 是使用Cargo的Rust项目事实上的模糊测试工具。 用于通过libFuzzer后端对Rust代码进行模糊测试。

cargo-fuzz

cargo-fuzz 是当使用Cargo时,模糊测试Rust项目的首选工具。它使用libFuzzer作为后端,并提供一个方便的Cargo子命令,自动为您的Rust项目启用相关编译标志,包括支持如AddressSanitizer等消毒器。

何时使用

cargo-fuzz 是目前使用Cargo的Rust项目的主要和最成熟的模糊测试解决方案。

模糊测试器 最适合 复杂性
cargo-fuzz 基于Cargo的Rust项目,快速设置
AFL++ 多核心模糊测试,非Cargo项目 中等
LibAFL 自定义模糊测试器,研究,高级用例

选择 cargo-fuzz 当:

  • 您的项目使用Cargo(必需)
  • 您希望简单、快速设置,最小配置
  • 您需要集成消毒器支持
  • 您正在模糊测试带或不带不安全块的Rust代码

快速开始

#![no_main]

use libfuzzer_sys::fuzz_target;

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

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

初始化和运行:

cargo fuzz init
# 在 fuzz/fuzz_targets/fuzz_target_1.rs 中编辑您的harness
cargo +nightly fuzz run fuzz_target_1

安装

cargo-fuzz 需要夜间Rust工具链,因为它使用仅在夜间可用的功能。

先决条件

  • 通过 rustup 安装的Rust和Cargo
  • 夜间工具链

Linux/macOS

# 安装夜间工具链
rustup install nightly

# 安装 cargo-fuzz
cargo install cargo-fuzz

验证

cargo +nightly --version
cargo fuzz --version

编写Harness

项目结构

cargo-fuzz 在您的代码结构为库crate时效果最佳。如果您有二进制项目,拆分您的 main.rs 为:

src/main.rs  # 入口点(主函数)
src/lib.rs   # 要模糊测试的代码(公共函数)
Cargo.toml

初始化模糊测试:

cargo fuzz init

这会创建:

fuzz/
├── Cargo.toml
└── fuzz_targets/
    └── fuzz_target_1.rs

Harness结构

#![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);
});

Harness规则

不要
将代码结构为库crate 将所有内容保留在main.rs中
使用 fuzz_target! 编写自定义主函数
优雅处理 Result::Err 对预期错误恐慌
保持harness确定性 使用随机数生成器

另请参阅: 关于详细harness编写技术和使用 arbitrary crate进行结构感知模糊测试,参见 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

不使用消毒器(安全Rust)

如果您的项目不使用不安全Rust,禁用消毒器以获得2倍性能提升:

cargo +nightly fuzz run --sanitizer none fuzz_target_1

检查您的项目是否使用不安全代码:

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/

消毒器集成

AddressSanitizer (ASan)

ASan默认启用并检测内存错误:

cargo +nightly fuzz run fuzz_target_1

禁用消毒器

对于纯安全Rust(您的代码或依赖中无不安全块):

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 "错误:需要模糊测试目标名称。"
    echo "用法:$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倍性能提升
定期检查覆盖率 识别harness或种子语料库中的空白
对解析器使用字典 帮助克服魔术值检查
将代码结构为库 cargo-fuzz集成所必需

libFuzzer选项

-- 后传递选项给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 crate 解析Ogg媒体容器文件。解析器是优秀的模糊测试目标,因为它们处理不受信任的数据。

# 克隆和初始化
git clone https://github.com/RustAudio/ogg.git
cd ogg/
cargo fuzz init

Harness在 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

故障排除

问题 原因 解决方案
“需要夜间” 错误 使用稳定工具链 使用 cargo +nightly fuzz
模糊测试性能慢 对安全Rust启用ASan 添加 --sanitizer none 标志
“找不到二进制” 无库crate 将代码从 main.rs 移动到 lib.rs
消毒器编译问题 错误的夜间版本 尝试不同夜间: 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 documentation 使用Rust类型的自动派生进行结构感知模糊测试的指南。

cargo-fuzz GitHub Repository cargo-fuzz的源代码、问题跟踪器和示例。