Skip to content

Commit abe2b4c

Browse files
Important fix: make fuzzer able to tell different bugs appart (again)
**Context:** For the fuzzer to be able to "understand" that something went wrong, like a panic, the process must terminate in an abnormal fashion. The default panic hook will unwind the stack, run destructors, optionally print a backtrace and exit with code 101. The fuzzer will not be able to "understand" that something went particuliarly wrong. One way to stop a process in a way that the fuzzer understands as abnormal is to call `std::process::abort()`. **Possible solutions:** - build with "-C panic=abort": incompatible with compiler plugins rust-lang/cargo#2738 (comment) rust-fuzz/afl.rs#120 - use `panic::catch_unwind()` to catch unwinding stacks and call `std::process::abort()`: all kind of bugs will then unwind their stack up to the code calling this function and therefore render different bugs indistinguishable from the fuzzer's point of view. - use a custom panic hook and call `std::process::abort()` here. **Implemented solution** We implemented both solution 2 and 3. Solution 3 has no drawbacks that I know of, but could potentially be missed if the fuzzed code modifies the panic hook. In this case, we fall back to solution 2 as a last resort.
1 parent c848c31 commit abe2b4c

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

src/lib.rs

+14
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ pub fn fuzz<F>(closure: F) where F: Fn(&[u8]) {
236236

237237
#[cfg(all(fuzzing, not(fuzzing_debug)))]
238238
pub fn fuzz<F>(closure: F) where F: Fn(&[u8]) + std::panic::RefUnwindSafe {
239+
// get buffer from honggfuzz runtime
239240
let buf;
240241
unsafe {
241242
let mut buf_ptr: *const u8 = std::mem::uninitialized();
@@ -244,11 +245,24 @@ pub fn fuzz<F>(closure: F) where F: Fn(&[u8]) + std::panic::RefUnwindSafe {
244245
buf = ::std::slice::from_raw_parts(buf_ptr, len_ptr);
245246
}
246247

248+
// Registers a panic hook that aborts the process before unwinding.
249+
// It is useful to abort before unwinding so that the fuzzer will then be
250+
// able to analyse the process stack frames to tell different bugs appart.
251+
std::panic::set_hook(Box::new(|_| {
252+
std::process::abort();
253+
}));
254+
255+
// We still catch unwinding panics just in case the fuzzed code modifies
256+
// the panic hook.
257+
// If so, the fuzzer will be unable to tell different bugs appart and you will
258+
// only be able to find one bug at a time before fixing it to then find a new one.
247259
let did_panic = std::panic::catch_unwind(|| {
248260
closure(buf);
249261
}).is_err();
250262

251263
if did_panic {
264+
// hopefully the custom panic hook will be called before and abort the
265+
// process with instact stack frames.
252266
std::process::abort();
253267
}
254268
}

0 commit comments

Comments
 (0)