Avoid the "replace main" trick
Manishearth opened this issue · 5 comments
The way libfuzzer works is that libfuzzer itself contains a main()
, and you link in a binary that contains a hook but not main()
.
This is kind of awkward, ideally we can get rid of this requirement and instead have a system where you define main()
and call libfuzzer::fuzz(|x: &[u8]| {...})
when ready.
Of course, this won't work without changes to libFuzzer itself. Ideally we can add a compile time flag that disables main()
and routes everything through FuzzerDriver.
This also lets us do things like add custom formatters to libFuzzer (https://github.com/rust-fuzz/libfuzzer-sys/issues/47), because last I checked we can't hook into any of the optional functions
That said, it seems like we're using LLVMFuzzerInitialize
so perhaps we can, now!
Update: this is no longer necessary to use optional functions.
Greetings from a year later 👋
How are you thinking this would work? We commit a .patch
file that renames (or removes) main
in FuzzerMain.cpp
? And apply the patch everytime we update LLVM? Or were you thinking something else?
Something like that, yeah
We could -Dmain=libfuzzer_main
or something along those lines. It can then also be made optional through build-time features.
I'll see about making a PR for this today.
I'm interested in this because when I run a fuzz target against an existing corpus, I'd like to gather statistics from inside the fuzz target and report them when the fuzzer exits.
I could do that instead by factoring out the fuzz target function so I can call it from a separate program that just feeds it the contents of every file in a directory. I could also use the libc
crate to set up an atexit
handler, but carefully, since I understand none of the Rust I/O machinery works at that point.
But I think it'd be nicer to be able to wrap logic like this around a simple library call to the fuzzer driver.