libFuzzer repeatedly calls a function with generated inputs and records a test case when an input triggers an error. In Rust, cargo-fuzz provides the integration and generates the boilerplate, avoiding direct FFI. section 7.5
Listing 7.10 String-parsing function with a bug
pub fn parse_integer(s: &str) -> Option<i32> { #1
use regex::Regex;
let re = Regex::new(r"^-?\d{1,10}$").expect("Parsing regex failed"); #2
if re.is_match(s) {
Some(s.parse().expect("Parsing failed"))
} else {
None
}
}
The parser accepts up to ten decimal digits, then calls `expect` on an `i32` parse. A matching string can exceed the `i32` range and cause a panic. section 7.5
Listing 7.11 Fuzz test
#![no_main]
use arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
#[derive(Arbitrary, Debug)] #1
struct Input {
s: String, #2
}
fuzz_target!(|input: Input| { #3
use fuzzme::parse_integer;
parse_integer(&input.s); #4
});
The fuzz target derives `Arbitrary` for its input structure and passes each generated string to the parser through `fuzz_target!`. section 7.5
Install the tool with `cargo install cargo-fuzz`, then run the target with `cargo fuzz run fuzz_target_1`. Inspect the reported failing-input artifact to reproduce the error; fuzzing can find edge cases without exhausting every possible input. section 7.5
