-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: make fuzzing a first class citizen #39916
Comments
So after some discussion the way to do it would probably be to create a new sanitizer option, fuzz, which runs @nagisa is currently looking into this (I'm using a mac right now so it's harder for me to hack on this) |
I think that there's a superior option for signatures of fuzz targets. In particular, QuickCheck's However, even beyond functions, there are closures. Last of all, As a result: fn fuzz_once<A: Arbitrary, F: FnOnce<A>>(target: F, data: &[u8])
-> <F as FnOnce<A>>::Target {
let mut g = FuzzGen::new(data);
target.call_once(<A as Arbitrary>::arbitrary(&mut g))
}
fn fuzz_mut<A: Arbitrary, F: FnMut<A>>(target: &mut F, data: &[u8])
-> <F as FnOnce<A>>::Target {
let mut g = FuzzGen::new(data);
target.call_mut(<A as Arbitrary>::arbitrary(&mut g))
}
fn fuzz<A: Arbitrary, F: Fn<A>>(target: &F, data: &[u8])
-> <F as FnOnce<A>>::Target {
let mut g = FuzzGen::new(data);
target.call(<A as Arbitrary>::arbitrary(&mut g))
} The rest follows naturally. |
Current work is in https://github.com/rust-fuzz. AFL has moved there too. @nagisa has working fuzzing via libfuzzer-sys, we just need to wrap it nicely. |
This is exciting, but it feels rather "big" to be an issue; should this not go through the RFC process? |
We now have https://github.com/rust-fuzz/cargo-fuzz Yeah, to make it actually part of the distribution it would have to be an rfc. But we can prototype it outside if we want. |
Closing. If someone wants to pursue this, please follow the RFC process here https://github.com/rust-lang/rfcs#before-creating-an-rfc. |
first class support for fuzzing was recently proposed for go https://go.googlesource.com/proposal/+/master/design/draft-fuzzing.md |
For completeness, Go support was proposed long long time ago: |
Proposal: make fuzzing a first class citizen
There were many successful attempts to use AFL with Rust programs, see e.g. @frewsxcv's afl.rs. We can go one step further and make guided fuzzing a common way to test Rust code.
Instrumentation
Guided fuzzing requires code instrumentation so that the fuzzing engines get feedback from the code execution and can guide a) mutations and b) corpus expansion. Since Rust is based on LLVM, there is such instrumentation available already:
https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards (control flow feedback)
https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow (data flow feedback)
We may need to make some LLVM flags available via the Rust frontend, that's it.
Fuzzing engines
This LLVM instrumentation is already supported by at least AFL, libFuzzer and honggfuzz. We expect more engines to appear in near future and it's important to keep them plug compatible. This way using a new engine on a vast body of code will be trivial.
And by fuzzing engine we should understand a wider class of tools, including e.g. concolic execution tools.
Interface
In C/C++ we use the following interface for things that need fuzzing (we call these things fuzz targets):
At least as a start I propose to have something similar in (safe) Rust.
The interface should not depend on any particular fuzzing engine -- engines should be interchangeable.
The interface should also allow for both in-process and out-of-process engines.
In-process fuzzing
With some rare exceptions fuzzing needs to be in-process, i.e. the code under test and the fuzzing engine should co-exist in the same process. This typically speeds up fuzzing by 1-2 orders of magnitude and often makes deployment simpler. libFuzzer is in-process, AFL has in-process (aka persistent) mode, same for hoggfuzz
Structured fuzzing
A frequent question about fuzzing is how to fuzz the input consisting of several chunks of data, or even tree-like data structures. One of the possible answers is fuzzing protobufs. This can be discussed later and separately from this proposal.
Fuzzing for equivalence
One interesting special case is fuzzing for equivalence (e.g. to compare Rust and C implementations of the same thing). See my recent write up. This might be especially interesting for projects that re-implement commonly used C libraries, such as https://github.com/briansmith/ring.
Continuous fuzzing
Fuzzing is often useful as a one-off effort, but it really shines if used continuously.
One of the services that provide infrastructure for continuous fuzzing is https://github.com/google/oss-fuzz and we'd like to see important Rust projects there.
See also
The text was updated successfully, but these errors were encountered: