use std::io::{self, Read};
use std::{panic, process};
#[deprecated(
since = "0.3.3",
note = "This function does not use the `persistent mode` and `defered forkserver mode` and is therefore very slow.
Please use fuzz() or fuzz!() instead."
)]
pub fn read_stdio_bytes<F>(closure: F)
where
F: Fn(Vec<u8>) + panic::RefUnwindSafe,
{
let mut input = vec![];
let result = io::stdin().read_to_end(&mut input);
if result.is_err() {
return;
}
let was_panic = panic::catch_unwind(|| {
closure(input);
});
if was_panic.is_err() {
process::abort();
}
}
#[deprecated(
since = "0.3.3",
note = "This function does not use the `persistent mode` and `defered forkserver mode` and is therefore very slow.
Please use fuzz() or fuzz!() instead."
)]
pub fn read_stdio_string<F>(closure: F)
where
F: Fn(String) + panic::RefUnwindSafe,
{
let mut input = String::new();
let result = io::stdin().read_to_string(&mut input);
if result.is_err() {
return;
}
let was_panic = panic::catch_unwind(|| {
closure(input);
});
if was_panic.is_err() {
process::abort();
}
}
extern "C" {
fn __afl_persistent_loop(counter: usize) -> isize;
fn __afl_manual_init();
}
pub fn fuzz<F>(closure: F)
where
F: Fn(&[u8]) + std::panic::RefUnwindSafe,
{
static PERSIST_MARKER: &'static str = "##SIG_AFL_PERSISTENT##\0";
static DEFERED_MARKER: &'static str = "##SIG_AFL_DEFER_FORKSRV##\0";
unsafe { std::ptr::read_volatile(&PERSIST_MARKER) }; unsafe { std::ptr::read_volatile(&DEFERED_MARKER) };
std::panic::set_hook(Box::new(|_| {
std::process::abort();
}));
let mut input = vec![];
unsafe { __afl_manual_init() };
while unsafe { __afl_persistent_loop(1000) } != 0 {
let result = io::stdin().read_to_end(&mut input);
if result.is_err() {
return;
}
let did_panic = std::panic::catch_unwind(|| {
closure(&input);
})
.is_err();
if did_panic {
std::process::abort();
}
input.clear();
}
}
#[macro_export]
macro_rules! fuzz {
(|$buf:ident| $body:block) => {
afl::fuzz(|$buf| $body);
};
(|$buf:ident: &[u8]| $body:block) => {
afl::fuzz(|$buf| $body);
};
(|$buf:ident: $dty: ty| $body:block) => {
afl::fuzz(|$buf| {
let $buf: $dty = {
use arbitrary::{Arbitrary, RingBuffer};
if let Ok(d) = RingBuffer::new($buf, $buf.len())
.and_then(|mut b| Arbitrary::arbitrary(&mut b).map_err(|_| ""))
{
d
} else {
return;
}
};
$body
});
};
}
#[cfg(test)]
mod test {
}