cargo-fuzz
cargo-fuzz copied to clipboard
Generalize fuzz macro
Currently a fuzz target looks like
#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate thing;
fuzz_target!(|data: Type| {
//stuff
});
Ideally, it would instead look like
extern crate thing;
#[macro_use] extern crate arbitrary_macros;
target!(|data: Type| {
// stuff
});
where the macro introduces the no_main and the libfuzzer_sys.
This means we could use the same script for a quickcheck
, or for running with seer
The exact code it expands to can be controlled by a cfg that is a part of the macro expansion. This way we can have cargo-fuzz also do things like cargo fuzz seer name_of_script
or cargo fuzz quickcheck name_of_script
, which will pass different cfg args to the fuzzer script and do a completely different thing.
Having a common API would be pretty neat, overall. Also makes it easier to be agnostic over the fuzzer.
cc @nagisa @frewsxcv @dwrensha
@PaulGrandperrin, even after seeing https://github.com/rust-fuzz/libfuzzer-sys/pull/33 and https://github.com/rust-fuzz/afl.rs/pull/137, I don't think this should be closed or at least that we can go one step further. If you don't agree, feel free to close it again.
Is there any reason to not also put the extern crate and fn main
stuff into a macro that the other fuzzers might also use to present a truly uniform interface?
Let's compare the code you write for the three fuzzers right now:
/// AFL
extern crate afl;
fn main() {
// … setup …
afl::read_stdio_bytes(|data|{
// … your code …
});
}
/// honggfuzz
#[macro_use] extern crate honggfuzz;
fn main() {
// … setup …
loop {
fuzz!(|data|{
// … your code …
})
}
}
/// libfuzzer after this https://github.com/rust-fuzz/libfuzzer-sys/pull/33
#[macro_use] extern crate libfuzzer_sys;
fn main() {
// … setup …
fuzz!(|data: &[u8]| {
// … your code …
});
}
This looks all very similar to me, except for the extern crate and the way you separate your fuzz code from your setup code. In an ideal world, cargo-fuzz and the code in fuzz/
should be agnostic to the actual fuzzer used. Imagine:
#[macro_use] extern crate fuzz;
fuzz!(
optional_name_if_you_want_it_to_differ_from_the_binary_name,
setup { /* setup is optional */ },
|data: Type| { /* actual fuzzer code */ }
);
and invoking it with cargo fuzz run name --fuzzer honggfuzz
. This is what the issue description also mentions.