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 {
}