cargo-fuzz tutorial
一.安装
一.安装
github: https://github.com/rust-fuzz/cargo-fuzz
安装: cargo install cargo-fuzz
➜ fuzzing cargo install cargo-fuzz Updating https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git index Downloaded cargo-fuzz v0.10.0 (registry https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git) Downloaded 1 crate (30.5 KB) in 2.33s Installing cargo-fuzz v0.10.0 … Finished release [optimized] target(s) in 47.02s Replacing /root/.cargo/bin/cargo-fuzz Replaced package cargo-fuzz v0.8.0 with cargo-fuzz v0.10.0 (executable cargo-fuzz)
➜ fuzzing cargo-fuzz cargo-fuzz 0.10.0 A cargo subcommand for using libFuzzer! Easy to use! No need to recompile LLVM!
USAGE: cargo-fuzz
FLAGS: -h, —help Prints help information -V, —version Prints version information
SUBCOMMANDS: add Add a new fuzz target build Build fuzz targets cmin Minify a corpus coverage Run program on the generated corpus and generate coverage information fmt Print the std::fmt::Debug output for an input help Prints this message or the help of the given subcommand(s) init Initialize the fuzz directory list List all the existing fuzz targets run Run a fuzz target tmin Minify a test case
注意: cargo-fuzz 是集成了libfuzzer,libFuzzer依赖LLVM的,所以只能是x86-64的linux或者macos才可以,而且还需要C++编译器和C++11的支持。
用法
- 初始化: cargo fuzz init
- 添加目标: cargo fuzz add
- 运行: cargo fuzz run
- 打印测试用户输出 :cargo fuzz fmt
- 缩小到最小输出:cargo fuzz tmin
- 缩小输入数据: cargo fuzz cmin
- 生成覆盖范围信息: cargo fuzz coverage
官方文档: https://rust-fuzz.github.io/book/cargo-fuzz.html
二.实战
我们随机选了一个好fuzzing的库,Human Time, 一个parser 时间的这种库。
crate: https://crates.io/crates/humantime
github: https://github.com/tailhook/humantime
文档: https://docs.rs/humantime/2.1.0/humantime/
第一步: 把项目clone到本地
git clone https://github.com/tailhook/humantime
我们可以看到,这个库自己是没有fuzz文件夹的,说明并没有做fuzzing
➜ humantime git:(master) ls benches bulk.yaml Cargo.toml LICENSE-APACHE LICENSE-MIT README.md src vagga.yaml
第二步 : 项目初始化
进行项目文件夹执行
cargo fuzz init
可以看到,多了一个fuzz的文件夹
fuzz的文件夹结构:
➜ fuzz git:(master) ✗ tree
.
├── Cargo.toml
└── fuzz_targets
└── fuzz_target_1.rs
1 directory, 2 files
fuzz_target_1.rs的代码:
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
// fuzzed code goes here
});
第三步,开始编写测试用例
我们查看文档,看看这个库的具体用法
https://docs.rs/humantime/2.1.0/humantime/fn.format_duration.html
#![no_main]
use libfuzzer_sys::fuzz_target;
use humantime::parse_duration;
fuzz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let _ = parse_duration(s);
};
});
我们把data变成字符串,看看parse_duration是怎么解析的。
第四步,运行
cargo fuzz list 可以列出所有的测试用例
➜ fuzz_targets git:(master) ✗ cargo fuzz list
fuzz_target_1
我们继续添加测试用例
#![no_main]
use libfuzzer_sys::fuzz_target;
use humantime::{parse_duration, parse_rfc3339, parse_rfc3339_weak};
fuzz_target!(|data: &[u8]| {
// fuzzed code goes here
if let Ok(s) = std::str::from_utf8(data) {
let _ = parse_duration(s);
let _ = parse_rfc3339(s);
let _ = parse_rfc3339_weak(s);
};
});