on crash callback in inmem executor

This commit is contained in:
Andrea Fioraldi 2021-01-05 13:13:19 +01:00
parent fde6201d74
commit cf7c9cd571
5 changed files with 135 additions and 115 deletions

View File

@ -33,12 +33,11 @@ pub trait StateMetadata: Debug {
/// The state a fuzz run. /// The state a fuzz run.
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "FT: serde::de::DeserializeOwned")] #[serde(bound = "FT: serde::de::DeserializeOwned")]
pub struct State<I, R, FT, OT> pub struct State<I, R, FT>
where where
I: Input, I: Input,
R: Rand, R: Rand,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
OT: ObserversTuple,
{ {
/// How many times the executor ran the harness/target /// How many times the executor ran the harness/target
executions: usize, executions: usize,
@ -49,17 +48,16 @@ where
// additional_corpuses, maybe another TupleList? // additional_corpuses, maybe another TupleList?
// Feedbacks used to evaluate an input // Feedbacks used to evaluate an input
feedbacks: FT, feedbacks: FT,
phantom: PhantomData<(I, R, OT)>, phantom: PhantomData<(I, R)>,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<R, FT, OT> State<BytesInput, R, FT, OT> impl<R, FT> State<BytesInput, R, FT>
where where
R: Rand, R: Rand,
FT: FeedbacksTuple<BytesInput>, FT: FeedbacksTuple<BytesInput>,
OT: ObserversTuple,
{ {
pub fn load_from_directory<G, C, E, ET, EM>( pub fn load_from_directory<G, C, E, OT, ET, EM>(
&mut self, &mut self,
corpus: &mut C, corpus: &mut C,
generator: &mut G, generator: &mut G,
@ -71,8 +69,9 @@ where
G: Generator<BytesInput, R>, G: Generator<BytesInput, R>,
C: Corpus<BytesInput, R>, C: Corpus<BytesInput, R>,
E: Executor<BytesInput> + HasObservers<OT>, E: Executor<BytesInput> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<BytesInput>, ET: ExecutorsTuple<BytesInput>,
EM: EventManager<C, E, OT, FT, BytesInput, R>, EM: EventManager<C, E, FT, BytesInput, R>,
{ {
for entry in fs::read_dir(in_dir)? { for entry in fs::read_dir(in_dir)? {
let entry = entry?; let entry = entry?;
@ -101,7 +100,7 @@ where
Ok(()) Ok(())
} }
pub fn load_initial_inputs<G, C, E, ET, EM>( pub fn load_initial_inputs<G, C, E, OT, ET, EM>(
&mut self, &mut self,
corpus: &mut C, corpus: &mut C,
generator: &mut G, generator: &mut G,
@ -113,8 +112,9 @@ where
G: Generator<BytesInput, R>, G: Generator<BytesInput, R>,
C: Corpus<BytesInput, R>, C: Corpus<BytesInput, R>,
E: Executor<BytesInput> + HasObservers<OT>, E: Executor<BytesInput> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<BytesInput>, ET: ExecutorsTuple<BytesInput>,
EM: EventManager<C, E, OT, FT, BytesInput, R>, EM: EventManager<C, E, FT, BytesInput, R>,
{ {
for in_dir in in_dirs { for in_dir in in_dirs {
self.load_from_directory(corpus, generator, engine, manager, in_dir)?; self.load_from_directory(corpus, generator, engine, manager, in_dir)?;
@ -128,12 +128,11 @@ where
} }
} }
impl<I, R, FT, OT> State<I, R, FT, OT> impl<I, R, FT> State<I, R, FT>
where where
I: Input, I: Input,
R: Rand, R: Rand,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
OT: ObserversTuple,
{ {
/// Get executions /// Get executions
#[inline] #[inline]
@ -206,7 +205,7 @@ where
// TODO move some of these, like evaluate_input, to FuzzingEngine // TODO move some of these, like evaluate_input, to FuzzingEngine
#[inline] #[inline]
pub fn is_interesting(&mut self, input: &I, observers: &OT) -> Result<u32, AflError> pub fn is_interesting<OT>(&mut self, input: &I, observers: &OT) -> Result<u32, AflError>
where where
OT: ObserversTuple, OT: ObserversTuple,
{ {
@ -214,9 +213,10 @@ where
} }
/// Runs the input and triggers observers and feedback /// Runs the input and triggers observers and feedback
pub fn evaluate_input<E>(&mut self, input: &I, executor: &mut E) -> Result<u32, AflError> pub fn evaluate_input<E, OT>(&mut self, input: &I, executor: &mut E) -> Result<u32, AflError>
where where
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
{ {
executor.reset_observers()?; executor.reset_observers()?;
executor.run_target(&input)?; executor.run_target(&input)?;
@ -279,7 +279,7 @@ where
} }
} }
pub fn generate_initial_inputs<G, C, E, ET, EM>( pub fn generate_initial_inputs<G, C, E, OT, ET, EM>(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
corpus: &mut C, corpus: &mut C,
@ -292,8 +292,9 @@ where
G: Generator<I, R>, G: Generator<I, R>,
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<I>, ET: ExecutorsTuple<I>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
{ {
let mut added = 0; let mut added = 0;
for _ in 0..num { for _ in 0..num {
@ -383,7 +384,7 @@ where
pub trait Fuzzer<ST, EM, E, OT, FT, ET, C, I, R> pub trait Fuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where where
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>, ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -399,7 +400,7 @@ where
fn fuzz_one( fn fuzz_one(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>, engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM, manager: &mut EM,
@ -416,7 +417,7 @@ where
fn fuzz_loop( fn fuzz_loop(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>, engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM, manager: &mut EM,
@ -437,7 +438,7 @@ where
pub struct StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R> pub struct StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where where
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>, ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -454,7 +455,7 @@ impl<ST, EM, E, OT, FT, ET, C, I, R> Fuzzer<ST, EM, E, OT, FT, ET, C, I, R>
for StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R> for StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where where
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>, ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -475,7 +476,7 @@ where
impl<ST, EM, E, OT, FT, ET, C, I, R> StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R> impl<ST, EM, E, OT, FT, ET, C, I, R> StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where where
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>, ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,

View File

@ -211,23 +211,21 @@ where
where where
ST: Stats; ST: Stats;
/// This method will be called in the clients after handle_in_broker (unless BrokerEventResult::Handled) was returned in handle_in_broker /// This method will be called in the clients after handle_in_broker (unless BrokerEventResult::Handled) was returned in handle_in_broker
fn handle_in_client<C, OT, FT, R>( fn handle_in_client<C, FT, R>(
self, self,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
) -> Result<(), AflError> ) -> Result<(), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
R: Rand; R: Rand;
} }
pub trait EventManager<C, E, OT, FT, I, R> pub trait EventManager<C, E, FT, I, R>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -239,25 +237,25 @@ where
/// Return the number of processes events or an error /// Return the number of processes events or an error
fn process( fn process(
&mut self, &mut self,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
) -> Result<usize, AflError>; ) -> Result<usize, AflError>;
fn serialize_observers(&mut self, observers: &OT) -> Result<Vec<u8>, AflError> { fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Vec<u8>, AflError> where OT: ObserversTuple {
Ok(postcard::to_allocvec(observers)?) Ok(postcard::to_allocvec(observers)?)
} }
fn deserialize_observers(&mut self, observers_buf: &[u8]) -> Result<OT, AflError> { fn deserialize_observers<OT>(&mut self, observers_buf: &[u8]) -> Result<OT, AflError> where OT: ObserversTuple {
Ok(postcard::from_bytes(observers_buf)?) Ok(postcard::from_bytes(observers_buf)?)
} }
fn new_testcase( fn new_testcase<OT>(
&mut self, &mut self,
_input: &I, _input: &I,
_observers: &OT, _observers: &OT,
_corpus_size: usize, _corpus_size: usize,
_config: String, _config: String,
) -> Result<(), AflError> { ) -> Result<(), AflError> where OT: ObserversTuple {
Ok(()) Ok(())
} }
@ -384,14 +382,13 @@ where
} }
#[inline] #[inline]
fn handle_in_client<C, OT, FT, R>( fn handle_in_client<C, FT, R>(
self, self,
_state: &mut State<I, R, FT, OT>, _state: &mut State<I, R, FT>,
_corpus: &mut C, _corpus: &mut C,
) -> Result<(), AflError> ) -> Result<(), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
R: Rand, R: Rand,
{ {
@ -405,11 +402,10 @@ where
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct LoggerEventManager<C, E, OT, FT, I, R, ST> pub struct LoggerEventManager<C, E, FT, I, R, ST>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -419,15 +415,14 @@ where
stats: ST, stats: ST,
events: Vec<LoggerEvent<I>>, events: Vec<LoggerEvent<I>>,
// stats (maybe we need a separated struct?) // stats (maybe we need a separated struct?)
phantom: PhantomData<(C, E, I, R, OT, FT)>, phantom: PhantomData<(C, E, I, R, FT)>,
} }
impl<C, E, OT, FT, I, R, ST> EventManager<C, E, OT, FT, I, R> impl<C, E, FT, I, R, ST> EventManager<C, E, FT, I, R>
for LoggerEventManager<C, E, OT, FT, I, R, ST> for LoggerEventManager<C, E, FT, I, R, ST>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -436,7 +431,7 @@ where
{ {
fn process( fn process(
&mut self, &mut self,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
) -> Result<usize, AflError> { ) -> Result<usize, AflError> {
let count = self.events.len(); let count = self.events.len();
@ -446,13 +441,13 @@ where
Ok(count) Ok(count)
} }
fn new_testcase( fn new_testcase<OT>(
&mut self, &mut self,
_input: &I, _input: &I,
_observers: &OT, _observers: &OT,
corpus_size: usize, corpus_size: usize,
_config: String, _config: String,
) -> Result<(), AflError> { ) -> Result<(), AflError> where OT: ObserversTuple {
let event = LoggerEvent::NewTestcase { let event = LoggerEvent::NewTestcase {
corpus_size: corpus_size, corpus_size: corpus_size,
phantom: PhantomData, phantom: PhantomData,
@ -513,12 +508,11 @@ where
} }
} }
impl<C, E, OT, FT, I, R, ST> LoggerEventManager<C, E, OT, FT, I, R, ST> impl<C, E, FT, I, R, ST> LoggerEventManager<C, E, FT, I, R, ST>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
R: Rand, R: Rand,
ST: Stats, ST: Stats,
@ -658,14 +652,13 @@ where
} }
#[inline] #[inline]
fn handle_in_client<C, OT, FT, R>( fn handle_in_client<C, FT, R>(
self, self,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
) -> Result<(), AflError> ) -> Result<(), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
R: Rand, R: Rand,
{ {
@ -706,11 +699,10 @@ const _LLMP_TAG_EVENT_TO_BROKER: llmp::Tag = 0x2B80438;
const LLMP_TAG_EVENT_TO_BOTH: llmp::Tag = 0x2B0741; const LLMP_TAG_EVENT_TO_BOTH: llmp::Tag = 0x2B0741;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct LlmpEventManager<C, E, OT, FT, I, R, SH, ST> pub struct LlmpEventManager<C, E, FT, I, R, SH, ST>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -720,15 +712,14 @@ where
{ {
llmp: llmp::LlmpConnection<SH>, llmp: llmp::LlmpConnection<SH>,
stats: ST, stats: ST,
phantom: PhantomData<(C, E, OT, FT, I, R)>, phantom: PhantomData<(C, E, FT, I, R)>,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<C, E, OT, FT, I, R, ST> LlmpEventManager<C, E, OT, FT, I, R, AflShmem, ST> impl<C, E, FT, I, R, ST> LlmpEventManager<C, E, FT, I, R, AflShmem, ST>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -754,11 +745,10 @@ where
} }
} }
impl<C, E, OT, FT, I, R, SH, ST> LlmpEventManager<C, E, OT, FT, I, R, SH, ST> impl<C, E, FT, I, R, SH, ST> LlmpEventManager<C, E, FT, I, R, SH, ST>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -859,13 +849,12 @@ where
} }
} }
impl<C, E, OT, FT, I, R, SH, ST> EventManager<C, E, OT, FT, I, R> impl<C, E, FT, I, R, SH, ST> EventManager<C, E, FT, I, R>
for LlmpEventManager<C, E, OT, FT, I, R, SH, ST> for LlmpEventManager<C, E, FT, I, R, SH, ST>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
OT: ObserversTuple,
I: Input, I: Input,
R: Rand, R: Rand,
SH: ShMem, SH: ShMem,
@ -874,7 +863,7 @@ where
{ {
fn process( fn process(
&mut self, &mut self,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
) -> Result<usize, AflError> { ) -> Result<usize, AflError> {
// TODO: Get around local event copy by moving handle_in_client // TODO: Get around local event copy by moving handle_in_client
@ -907,13 +896,13 @@ where
}) })
} }
fn new_testcase( fn new_testcase<OT>(
&mut self, &mut self,
input: &I, input: &I,
observers: &OT, observers: &OT,
corpus_size: usize, corpus_size: usize,
config: String, config: String,
) -> Result<(), AflError> { ) -> Result<(), AflError> where OT: ObserversTuple {
let kind = LLMPEventKind::NewTestcase { let kind = LLMPEventKind::NewTestcase {
input: Ptr::Ref(input), input: Ptr::Ref(input),
observers_buf: postcard::to_allocvec(observers)?, observers_buf: postcard::to_allocvec(observers)?,

View File

@ -1,5 +1,5 @@
use alloc::{boxed::Box, string::ToString, vec::Vec}; use alloc::{boxed::Box, string::ToString, vec::Vec};
use core::{ffi::c_void, ptr}; use core::{marker::PhantomData, ffi::c_void, ptr};
use crate::{ use crate::{
corpus::Corpus, corpus::Corpus,
@ -20,16 +20,26 @@ use self::unix_signals::setup_crash_handlers;
/// The (unsafe) pointer to the current inmem input, for the current run. /// The (unsafe) pointer to the current inmem input, for the current run.
/// This is neede for certain non-rust side effects, as well as unix signal handling. /// This is neede for certain non-rust side effects, as well as unix signal handling.
static mut CURRENT_INPUT_PTR: *const c_void = ptr::null(); static mut CURRENT_INPUT_PTR: *const c_void = ptr::null();
static mut CURRENT_ON_CRASH_FN: *mut Box<dyn FnMut(ExitKind, &[u8])> = ptr::null_mut(); static mut CURRENT_ON_CRASH_FN: *mut c_void = ptr::null_mut();
static mut CORPUS_PTR: *const c_void = ptr::null_mut();
static mut STATE_PTR: *const c_void = ptr::null_mut();
static mut EVENT_MANAGER_PTR: *mut c_void = ptr::null_mut();
/// The inmem executor harness /// The inmem executor harness
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind; type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
type OnCrashFunction<I, C, EM, FT, R> = fn(ExitKind, &State<I, R, FT>, &C, &mut EM);
/// The inmem executor simply calls a target function, then returns afterwards. /// The inmem executor simply calls a target function, then returns afterwards.
pub struct InMemoryExecutor<I, OT> pub struct InMemoryExecutor<I, OT, C, E, EM, FT, R>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
E: Executor<I>,
EM: EventManager<C, E, FT, I, R>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
/// The name of this executor instance, to address it from other components /// The name of this executor instance, to address it from other components
name: &'static str, name: &'static str,
@ -38,19 +48,26 @@ where
/// The observers, observing each run /// The observers, observing each run
observers: OT, observers: OT,
/// A special function being called right before the process crashes. It may save state to restore fuzzing after respawn. /// A special function being called right before the process crashes. It may save state to restore fuzzing after respawn.
on_crash_fn: Box<dyn FnMut(ExitKind, &[u8])>, on_crash_fn: OnCrashFunction<I, C, EM, FT, R>,
phantom: PhantomData<E>
} }
impl<I, OT> Executor<I> for InMemoryExecutor<I, OT> impl<I, OT, C, E, EM, FT, R> Executor<I> for InMemoryExecutor<I, OT, C, E, EM, FT, R>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
E: Executor<I>,
EM: EventManager<C, E, FT, I, R>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
#[inline] #[inline]
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> { fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> {
let bytes = input.target_bytes(); let bytes = input.target_bytes();
unsafe { unsafe {
CURRENT_ON_CRASH_FN = &mut self.on_crash_fn as *mut _; CURRENT_ON_CRASH_FN = &mut self.on_crash_fn as *mut _ as *mut c_void;
CURRENT_INPUT_PTR = input as *const _ as *const c_void; CURRENT_INPUT_PTR = input as *const _ as *const c_void;
} }
let ret = (self.harness)(self, bytes.as_slice()); let ret = (self.harness)(self, bytes.as_slice());
@ -62,20 +79,30 @@ where
} }
} }
impl<I, OT> Named for InMemoryExecutor<I, OT> impl<I, OT, C, E, EM, FT, R> Named for InMemoryExecutor<I, OT, C, E, EM, FT, R>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
E: Executor<I>,
EM: EventManager<C, E, FT, I, R>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
fn name(&self) -> &str { fn name(&self) -> &str {
self.name self.name
} }
} }
impl<I, OT> HasObservers<OT> for InMemoryExecutor<I, OT> impl<I, OT, C, E, EM, FT, R> HasObservers<OT> for InMemoryExecutor<I, OT, C, E, EM, FT, R>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
E: Executor<I>,
EM: EventManager<C, E, FT, I, R>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
#[inline] #[inline]
fn observers(&self) -> &OT { fn observers(&self) -> &OT {
@ -88,10 +115,15 @@ where
} }
} }
impl<I, OT> InMemoryExecutor<I, OT> impl<I, OT, C, E, EM, FT, R> InMemoryExecutor<I, OT, C, E, EM, FT, R>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
E: Executor<I>,
EM: EventManager<C, E, FT, I, R>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
/// Create a new in mem executor. /// Create a new in mem executor.
/// Caution: crash and restart in one of them will lead to odd behavior if multiple are used, /// Caution: crash and restart in one of them will lead to odd behavior if multiple are used,
@ -101,42 +133,31 @@ where
/// * `on_crash_fn` - When an in-mem harness crashes, it may safe some state to continue fuzzing later. /// * `on_crash_fn` - When an in-mem harness crashes, it may safe some state to continue fuzzing later.
/// Do that that in this function. The program will crash afterwards. /// Do that that in this function. The program will crash afterwards.
/// * `observers` - the observers observing the target during execution /// * `observers` - the observers observing the target during execution
pub fn new<C, E, EM, FT, R>( pub fn new(
name: &'static str, name: &'static str,
harness_fn: HarnessFunction<I>, harness_fn: HarnessFunction<I>,
observers: OT, observers: OT,
on_crash_fn: Box<dyn FnMut(ExitKind, &[u8])>, on_crash_fn: OnCrashFunction<I, C, EM, FT, R>,
_state: &State<I, R, FT, OT>,
_corpus: &C,
_event_manager: &mut EM,
) -> Self ) -> Self
where
C: Corpus<I, R>,
E: Executor<I>,
EM: EventManager<C, E, OT, FT, I, R>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
#[cfg(feature = "std")] /*#[cfg(feature = "std")]
unsafe { unsafe {
CORPUS_PTR = _corpus as *const _ as *const c_void; CORPUS_PTR = _corpus as *const _ as *const c_void;
STATE_PTR = _state as *const _ as *const c_void; STATE_PTR = _state as *const _ as *const c_void;
setup_crash_handlers(_event_manager); setup_crash_handlers(_event_manager);
} }*/
Self { Self {
harness: harness_fn, harness: harness_fn,
on_crash_fn, on_crash_fn,
observers, observers,
name, name,
phantom: PhantomData
} }
} }
} }
static mut CORPUS_PTR: *const c_void = ptr::null_mut();
static mut STATE_PTR: *const c_void = ptr::null_mut();
/// Serialize the current state and corpus during an executiont to bytes. /// Serialize the current state and corpus during an executiont to bytes.
/// This method is needed when the fuzzer run crashes and has to restart. /// This method is needed when the fuzzer run crashes and has to restart.
pub unsafe fn serialize_state_corpus<C, FT, I, OT, R>() -> Result<Vec<u8>, AflError> pub unsafe fn serialize_state_corpus<C, FT, I, OT, R>() -> Result<Vec<u8>, AflError>
@ -153,7 +174,7 @@ where
.to_string(), .to_string(),
)); ));
} }
let state: &State<I, R, FT, OT> = (STATE_PTR as *const State<I, R, FT, OT>).as_ref().unwrap(); let state: &State<I, R, FT> = (STATE_PTR as *const State<I, R, FT>).as_ref().unwrap();
let corpus = (CORPUS_PTR as *mut C).as_ref().unwrap(); let corpus = (CORPUS_PTR as *mut C).as_ref().unwrap();
let state_bytes = postcard::to_allocvec(&state)?; let state_bytes = postcard::to_allocvec(&state)?;
let corpus_bytes = postcard::to_allocvec(&corpus)?; let corpus_bytes = postcard::to_allocvec(&corpus)?;
@ -163,7 +184,7 @@ where
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` /// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
pub fn deserialize_state_corpus<C, FT, I, OT, R>( pub fn deserialize_state_corpus<C, FT, I, OT, R>(
state_corpus_serialized: &[u8], state_corpus_serialized: &[u8],
) -> Result<(State<I, R, FT, OT>, C), AflError> ) -> Result<(State<I, R, FT>, C), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -201,23 +222,22 @@ pub mod unix_signals {
corpus::Corpus, corpus::Corpus,
events::EventManager, events::EventManager,
executors::{ executors::{
inmemory::{serialize_state_corpus, ExitKind, CURRENT_INPUT_PTR, CURRENT_ON_CRASH_FN}, inmemory::{OnCrashFunction, ExitKind, CURRENT_INPUT_PTR, CURRENT_ON_CRASH_FN, CORPUS_PTR, STATE_PTR, EVENT_MANAGER_PTR},
Executor, Executor,
}, },
engines::State,
feedbacks::FeedbacksTuple, feedbacks::FeedbacksTuple,
inputs::Input, inputs::Input,
observers::ObserversTuple, observers::ObserversTuple,
utils::Rand, utils::Rand,
}; };
static mut EVENT_MANAGER_PTR: *mut c_void = ptr::null_mut();
pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash<EM, C, E, OT, FT, I, R>( pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash<EM, C, E, OT, FT, I, R>(
_sig: c_int, _sig: c_int,
info: siginfo_t, info: siginfo_t,
_void: c_void, _void: c_void,
) where ) where
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple, OT: ObserversTuple,
@ -238,14 +258,18 @@ pub mod unix_signals {
let _ = stdout().flush(); let _ = stdout().flush();
let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap();
let corpus = (CORPUS_PTR as *const C).as_ref().unwrap();
let state = (EVENT_MANAGER_PTR as *const State<I, R, FT>).as_ref().unwrap();
let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap(); let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap();
manager.crash(input).expect("Error in sending Crash event"); manager.crash(input).expect("Error in sending Crash event");
if !CURRENT_ON_CRASH_FN.is_null() { if !CURRENT_ON_CRASH_FN.is_null() {
(*CURRENT_ON_CRASH_FN)( (*(CURRENT_ON_CRASH_FN as *mut OnCrashFunction<I, C, EM, FT, R>))(
ExitKind::Crash, ExitKind::Crash,
&serialize_state_corpus::<C, FT, I, OT, R>().unwrap(), state,
corpus,
manager
); );
} }
@ -257,7 +281,7 @@ pub mod unix_signals {
_info: siginfo_t, _info: siginfo_t,
_void: c_void, _void: c_void,
) where ) where
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple, OT: ObserversTuple,
@ -272,6 +296,8 @@ pub mod unix_signals {
} }
let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap();
let corpus = (CORPUS_PTR as *const C).as_ref().unwrap();
let state = (EVENT_MANAGER_PTR as *const State<I, R, FT>).as_ref().unwrap();
let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap(); let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap();
manager manager
@ -279,9 +305,11 @@ pub mod unix_signals {
.expect("Error in sending Timeout event"); .expect("Error in sending Timeout event");
if !CURRENT_ON_CRASH_FN.is_null() { if !CURRENT_ON_CRASH_FN.is_null() {
(*CURRENT_ON_CRASH_FN)( (*(CURRENT_ON_CRASH_FN as *mut OnCrashFunction<I, C, EM, FT, R>))(
ExitKind::Timeout, ExitKind::Timeout,
&serialize_state_corpus::<C, FT, I, OT, R>().unwrap(), state,
corpus,
manager
); );
} }
@ -292,9 +320,9 @@ pub mod unix_signals {
} }
// TODO clearly state that manager should be static (maybe put the 'static lifetime?) // TODO clearly state that manager should be static (maybe put the 'static lifetime?)
pub unsafe fn setup_crash_handlers<EM, C, E, OT, FT, I, R>(manager: &mut EM) pub unsafe fn setup_crash_handlers<EM, C, E, OT, FT, I, R>(state: &State<I, R, FT>, corpus: &C, manager: &mut EM)
where where
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple, OT: ObserversTuple,
@ -302,6 +330,8 @@ pub mod unix_signals {
I: Input, I: Input,
R: Rand, R: Rand,
{ {
CORPUS_PTR = corpus as *const _ as *const c_void;
STATE_PTR = state as *const _ as *const c_void;
EVENT_MANAGER_PTR = manager as *mut _ as *mut c_void; EVENT_MANAGER_PTR = manager as *mut _ as *mut c_void;
let mut sa: sigaction = mem::zeroed(); let mut sa: sigaction = mem::zeroed();

View File

@ -16,7 +16,7 @@ use crate::AflError;
/// Multiple stages will be scheduled one by one for each input. /// Multiple stages will be scheduled one by one for each input.
pub trait Stage<EM, E, OT, FT, ET, C, I, R> pub trait Stage<EM, E, OT, FT, ET, C, I, R>
where where
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -29,7 +29,7 @@ where
fn perform( fn perform(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>, engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM, manager: &mut EM,
@ -39,7 +39,7 @@ where
pub trait StagesTuple<EM, E, OT, FT, ET, C, I, R> pub trait StagesTuple<EM, E, OT, FT, ET, C, I, R>
where where
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -51,7 +51,7 @@ where
fn perform_all( fn perform_all(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>, engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM, manager: &mut EM,
@ -63,7 +63,7 @@ where
impl<EM, E, OT, FT, ET, C, I, R> StagesTuple<EM, E, OT, FT, ET, C, I, R> for () impl<EM, E, OT, FT, ET, C, I, R> StagesTuple<EM, E, OT, FT, ET, C, I, R> for ()
where where
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -75,7 +75,7 @@ where
fn perform_all( fn perform_all(
&mut self, &mut self,
_rand: &mut R, _rand: &mut R,
_state: &mut State<I, R, FT, OT>, _state: &mut State<I, R, FT>,
_corpus: &mut C, _corpus: &mut C,
_engine: &mut Engine<E, OT, ET, I>, _engine: &mut Engine<E, OT, ET, I>,
_manager: &mut EM, _manager: &mut EM,
@ -92,7 +92,7 @@ impl<Head, Tail, EM, E, OT, FT, ET, C, I, R> StagesTuple<EM, E, OT, FT, ET, C, I
where where
Head: Stage<EM, E, OT, FT, ET, C, I, R>, Head: Stage<EM, E, OT, FT, ET, C, I, R>,
Tail: StagesTuple<EM, E, OT, FT, ET, C, I, R> + TupleList, Tail: StagesTuple<EM, E, OT, FT, ET, C, I, R> + TupleList,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -104,7 +104,7 @@ where
fn perform_all( fn perform_all(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>, engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM, manager: &mut EM,

View File

@ -21,7 +21,7 @@ pub trait MutationalStage<M, EM, E, OT, FT, ET, C, I, R>:
Stage<EM, E, OT, FT, ET, C, I, R> Stage<EM, E, OT, FT, ET, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -47,7 +47,7 @@ where
fn perform_mutational( fn perform_mutational(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>, engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM, manager: &mut EM,
@ -89,7 +89,7 @@ where
pub struct StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R> pub struct StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -106,7 +106,7 @@ impl<M, EM, E, OT, FT, ET, C, I, R> MutationalStage<M, EM, E, OT, FT, ET, C, I,
for StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R> for StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -132,7 +132,7 @@ impl<M, EM, E, OT, FT, ET, C, I, R> Stage<EM, E, OT, FT, ET, C, I, R>
for StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R> for StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -145,7 +145,7 @@ where
fn perform( fn perform(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT, OT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>, engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM, manager: &mut EM,
@ -158,7 +158,7 @@ where
impl<M, EM, E, OT, FT, ET, C, I, R> StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R> impl<M, EM, E, OT, FT, ET, C, I, R> StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,