lib compiles

This commit is contained in:
Andrea Fioraldi 2021-01-17 10:58:16 +01:00
parent c9174ecb38
commit db12506e2d
4 changed files with 125 additions and 93 deletions

View File

@ -89,7 +89,7 @@ where
println!("Loading file {:?} ...", &path); println!("Loading file {:?} ...", &path);
let bytes = std::fs::read(&path)?; let bytes = std::fs::read(&path)?;
let input = BytesInput::new(bytes); let input = BytesInput::new(bytes);
let fitness = self.evaluate_input(&input, engine.executor_mut())?; let fitness = self.evaluate_input(&input, engine.executor_mut(), corpus, manager)?;
if self.add_if_interesting(corpus, input, fitness)?.is_none() { if self.add_if_interesting(corpus, input, fitness)?.is_none() {
println!("File {:?} was not interesting, skipped.", &path); println!("File {:?} was not interesting, skipped.", &path);
} }
@ -224,10 +224,15 @@ where
where where
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
EM: EventManager<I>,
{ {
executor.pre_exec_observers()?; executor.pre_exec_observers()?;
executor.run_target(&input, &self, &corpus, &mut event_mgr)?; executor.pre_exec(&self, corpus, event_mgr, input)?;
executor.run_target(input)?;
executor.post_exec(&self, corpus, event_mgr, input)?;
self.set_executions(self.executions() + 1); self.set_executions(self.executions() + 1);
executor.post_exec_observers()?; executor.post_exec_observers()?;
@ -307,7 +312,7 @@ where
let mut added = 0; let mut added = 0;
for _ in 0..num { for _ in 0..num {
let input = generator.generate(rand)?; let input = generator.generate(rand)?;
let fitness = self.evaluate_input(&input, engine.executor_mut())?; let fitness = self.evaluate_input(&input, engine.executor_mut(), corpus, manager)?;
if !self.add_if_interesting(corpus, input, fitness)?.is_none() { if !self.add_if_interesting(corpus, input, fitness)?.is_none() {
added += 1; added += 1;
} }

View File

@ -1,6 +1,5 @@
use alloc::boxed::Box;
use core::{ffi::c_void, ptr};
use os_signals::set_oncrash_ptrs; use os_signals::set_oncrash_ptrs;
use core::marker::PhantomData;
use crate::{ use crate::{
corpus::Corpus, corpus::Corpus,
@ -24,88 +23,96 @@ use self::os_signals::reset_oncrash_ptrs;
use self::os_signals::setup_crash_handlers; use self::os_signals::setup_crash_handlers;
/// The inmem executor harness /// The inmem executor harness
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind; type HarnessFunction<E> = fn(&E, &[u8]) -> ExitKind;
type OnCrashFunction<I, C, EM, FT, R> = dyn FnMut(ExitKind, &I, &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, C, EM, FT, R> pub struct InMemoryExecutor<I, OT>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
EM: EventManager<I>,
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,
/// The harness function, being executed for each fuzzing loop execution /// The harness function, being executed for each fuzzing loop execution
harness_fn: HarnessFunction<I>, harness_fn: HarnessFunction<Self>,
/// 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. phantom: PhantomData<I>,
on_crash_fn: Box<OnCrashFunction<I, C, EM, FT, R>>,
} }
impl<I, OT, C, EM, FT, R> Executor<I> for InMemoryExecutor<I, OT, C, EM, FT, R> impl<I, OT> Executor<I> for InMemoryExecutor<I, OT>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
EM: EventManager<I>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
#[inline]
fn run_target( fn pre_exec<R, FT, C, EM>(
&mut self, &mut self,
input: &I, state: &State<I, R, FT>,
state: State<I, R, FT>,
corpus: &C, corpus: &C,
event_mgr: &EM, event_mgr: &mut EM,
) -> Result<ExitKind, AflError> { input: &I,
#[cfg(unix)] ) -> Result<(), AflError> where
R: Rand ,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>,
EM: EventManager<I>,
{
#[cfg(unix)]
unsafe { unsafe {
set_oncrash_ptrs::<EM, C, OT, FT, I, R>( set_oncrash_ptrs::<EM, C, OT, FT, I, R>(
state, state,
corpus, corpus,
event_mgr, event_mgr,
input, input,
&mut self.on_crash_fn,
); );
} }
let bytes = input.target_bytes(); Ok(())
let ret = (self.harness_fn)(self, bytes.as_slice()); }
fn post_exec<R, FT, C, EM>(
&mut self,
_state: &State<I, R, FT>,
_corpus: &C,
_event_mgr: &mut EM,
_input: &I,
) -> Result<(), AflError> where
R: Rand ,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>,
EM: EventManager<I>, {
#[cfg(unix)] #[cfg(unix)]
unsafe { unsafe {
reset_oncrash_ptrs::<EM, C, OT, FT, I, R>(); reset_oncrash_ptrs::<EM, C, OT, FT, I, R>();
} }
Ok(())
}
#[inline]
fn run_target(
&mut self,
input: &I,
) -> Result<ExitKind, AflError> {
let bytes = input.target_bytes();
let ret = (self.harness_fn)(self, bytes.as_slice());
Ok(ret) Ok(ret)
} }
} }
impl<I, OT, C, EM, FT, R> Named for InMemoryExecutor<I, OT, C, EM, FT, R> impl<I, OT> Named for InMemoryExecutor<I, OT>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
EM: EventManager<I>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
fn name(&self) -> &str { fn name(&self) -> &str {
self.name self.name
} }
} }
impl<I, OT, C, EM, FT, R> HasObservers<OT> for InMemoryExecutor<I, OT, C, EM, FT, R> impl<I, OT> HasObservers<OT> for InMemoryExecutor<I, OT>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
EM: EventManager<I>,
FT: FeedbacksTuple<I>,
R: Rand,
{ {
#[inline] #[inline]
fn observers(&self) -> &OT { fn observers(&self) -> &OT {
@ -118,14 +125,10 @@ where
} }
} }
impl<I, OT, C, EM, FT, R> InMemoryExecutor<I, OT, C, EM, FT, R> impl<I, OT> InMemoryExecutor<I, OT>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I, R>,
EM: EventManager<I>,
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,
@ -135,15 +138,18 @@ 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( pub fn new<R, FT, C, EM>(
name: &'static str, name: &'static str,
harness_fn: HarnessFunction<I>, harness_fn: HarnessFunction<Self>,
observers: OT, observers: OT,
on_crash_fn: Box<OnCrashFunction<I, C, EM, FT, R>>,
_state: &State<I, R, FT>, _state: &State<I, R, FT>,
_corpus: &C, _corpus: &C,
_event_mgr: &mut EM, _event_mgr: &mut EM,
) -> Self { ) -> Self where
R: Rand ,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>,
EM: EventManager<I>, {
#[cfg(feature = "std")] #[cfg(feature = "std")]
unsafe { unsafe {
setup_crash_handlers::<EM, C, OT, FT, I, R>(); setup_crash_handlers::<EM, C, OT, FT, I, R>();
@ -151,9 +157,9 @@ where
Self { Self {
harness_fn, harness_fn,
on_crash_fn,
observers, observers,
name, name,
phantom: PhantomData
} }
} }
} }
@ -200,7 +206,6 @@ pub mod unix_signals {
corpus::Corpus, corpus::Corpus,
engines::State, engines::State,
events::EventManager, events::EventManager,
executors::inmemory::{ExitKind, OnCrashFunction},
feedbacks::FeedbacksTuple, feedbacks::FeedbacksTuple,
inputs::Input, inputs::Input,
observers::ObserversTuple, observers::ObserversTuple,
@ -209,13 +214,12 @@ pub mod unix_signals {
/// Pointers to values only needed on crash. As the program will not continue after a crash, /// Pointers to values only needed on crash. As the program will not continue after a crash,
/// we should (tm) be okay with raw pointers here, /// we should (tm) be okay with raw pointers here,
static mut corpus_ptr: *const 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 STATE_PTR: *const c_void = ptr::null_mut();
static mut event_mgr_ptr: *mut c_void = ptr::null_mut(); static mut EVENT_MGR_PTR: *mut c_void = ptr::null_mut();
/// 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 on_crash_fn_ptr: *mut c_void = ptr::null_mut();
pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash<EM, C, OT, FT, I, R>( pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash<EM, C, OT, FT, I, R>(
_sig: c_int, _sig: c_int,
@ -229,7 +233,7 @@ pub mod unix_signals {
I: Input, I: Input,
R: Rand, R: Rand,
{ {
if current_input_ptr == ptr::null() { if CURRENT_INPUT_PTR == ptr::null() {
println!( println!(
"We died accessing addr {}, but are not in client... Exiting.", "We died accessing addr {}, but are not in client... Exiting.",
info.si_addr() as usize info.si_addr() as usize
@ -243,10 +247,10 @@ pub mod unix_signals {
#[cfg(feature = "std")] #[cfg(feature = "std")]
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 corpus = (CORPUS_PTR as *const C).as_ref().unwrap();
let state = (event_mgr_ptr as *const State<I, R, FT>).as_ref().unwrap(); let state = (EVENT_MGR_PTR as *const State<I, R, FT>).as_ref().unwrap();
let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap(); let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap();
if !on_crash_fn_ptr.is_null() { if !on_crash_fn_ptr.is_null() {
(*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))( (*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
@ -256,7 +260,7 @@ pub mod unix_signals {
corpus, corpus,
manager, manager,
); );
} }*/
std::process::exit(139); std::process::exit(139);
} }
@ -274,15 +278,15 @@ pub mod unix_signals {
R: Rand, R: Rand,
{ {
dbg!("TIMEOUT/SIGUSR2 received"); dbg!("TIMEOUT/SIGUSR2 received");
if current_input_ptr.is_null() { if CURRENT_INPUT_PTR.is_null() {
dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting"); dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting");
return; return;
} }
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 corpus = (CORPUS_PTR as *const C).as_ref().unwrap();
let state = (event_mgr_ptr as *const State<I, R, FT>).as_ref().unwrap(); let state = (EVENT_MGR_PTR as *const State<I, R, FT>).as_ref().unwrap();
let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap(); let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap();
if !on_crash_fn_ptr.is_null() { if !on_crash_fn_ptr.is_null() {
(*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))( (*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
@ -292,7 +296,7 @@ pub mod unix_signals {
corpus, corpus,
manager, manager,
); );
} }*/
/* TODO: If we want to be on the safe side, we really need to do this: /* TODO: If we want to be on the safe side, we really need to do this:
match manager.llmp { match manager.llmp {
@ -317,8 +321,7 @@ pub mod unix_signals {
state: &State<I, R, FT>, state: &State<I, R, FT>,
corpus: &C, corpus: &C,
event_mgr: &mut EM, event_mgr: &mut EM,
input: I, input: &I,
on_crash_handler: &mut Box<OnCrashFunction<I, C, EM, FT, R>>,
) where ) where
EM: EventManager<I>, EM: EventManager<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
@ -327,20 +330,18 @@ pub mod unix_signals {
I: Input, I: Input,
R: Rand, R: Rand,
{ {
current_input_ptr = input as *const _ as *const c_void; CURRENT_INPUT_PTR = input as *const _ as *const c_void;
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;
event_mgr_ptr = event_mgr as *mut _ as *mut c_void; EVENT_MGR_PTR = event_mgr as *mut _ as *mut c_void;
on_crash_fn_ptr = on_crash_handler as *mut _ as *mut c_void;
} }
#[inline] #[inline]
pub unsafe fn reset_oncrash_ptrs<EM, C, OT, FT, I, R>() { pub unsafe fn reset_oncrash_ptrs<EM, C, OT, FT, I, R>() {
current_input_ptr = ptr::null(); CURRENT_INPUT_PTR = ptr::null();
corpus_ptr = ptr::null(); CORPUS_PTR = ptr::null();
state_ptr = ptr::null(); STATE_PTR = ptr::null();
event_mgr_ptr = ptr::null_mut(); EVENT_MGR_PTR = ptr::null_mut();
on_crash_fn_ptr = ptr::null_mut();
} }
// 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?)

View File

@ -7,6 +7,10 @@ use core::marker::PhantomData;
use crate::{ use crate::{
engines::State, engines::State,
corpus::Corpus,
feedbacks::FeedbacksTuple,
events::EventManager,
utils::Rand,
inputs::{HasTargetBytes, Input}, inputs::{HasTargetBytes, Input},
observers::ObserversTuple, observers::ObserversTuple,
tuples::{MatchNameAndType, MatchType, Named, TupleList}, tuples::{MatchNameAndType, MatchType, Named, TupleList},
@ -74,30 +78,52 @@ pub trait Executor<I>: Named
where where
I: Input, I: Input,
{ {
/// Instruct the target about the input and run fn pre_exec<R, FT, C, EM>(
fn run_target<R, FT, C, EM>(
&mut self, &mut self,
input: &I, _state: &State<I, R, FT>,
state: &State<I, R, FT>, _corpus: &C,
corpus: &C, _event_mgr: &mut EM,
event_mgr: &EM, _input: &I,
) -> Result<(), AflError> where
R: Rand ,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>,
EM: EventManager<I>, { Ok(()) }
fn post_exec<R, FT, C, EM>(
&mut self,
_state: &State<I, R, FT>,
_corpus: &C,
_event_mgr: &mut EM,
_input: &I,
) -> Result<(), AflError> where
R: Rand ,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>,
EM: EventManager<I>, { Ok(()) }
/// Instruct the target about the input and run
fn run_target(
&mut self,
input: &I
) -> Result<ExitKind, AflError>; ) -> Result<ExitKind, AflError>;
} }
pub trait ExecutorsTuple<I>: MatchType + MatchNameAndType pub trait ExecutorsTuple<I>: MatchType + MatchNameAndType
where where
I: Input, I: Input,
{ {
fn for_each(&self, f: fn(&dyn Executor<I>)); //fn for_each(&self, f: fn(&dyn Executor<I>));
fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>)); //fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>));
} }
impl<I> ExecutorsTuple<I> for () impl<I> ExecutorsTuple<I> for ()
where where
I: Input, I: Input,
{ {
fn for_each(&self, _f: fn(&dyn Executor<I>)) {} //fn for_each(&self, _f: fn(&dyn Executor<I>)) {}
fn for_each_mut(&mut self, _f: fn(&mut dyn Executor<I>)) {} //fn for_each_mut(&mut self, _f: fn(&mut dyn Executor<I>)) {}
} }
impl<Head, Tail, I> ExecutorsTuple<I> for (Head, Tail) impl<Head, Tail, I> ExecutorsTuple<I> for (Head, Tail)
@ -106,7 +132,7 @@ where
Tail: ExecutorsTuple<I> + TupleList, Tail: ExecutorsTuple<I> + TupleList,
I: Input, I: Input,
{ {
fn for_each(&self, f: fn(&dyn Executor<I>)) { /*fn for_each(&self, f: fn(&dyn Executor<I>)) {
f(&self.0); f(&self.0);
self.1.for_each(f) self.1.for_each(f)
} }
@ -114,7 +140,7 @@ where
fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>)) { fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>)) {
f(&mut self.0); f(&mut self.0);
self.1.for_each_mut(f) self.1.for_each_mut(f)
} }*/
} }
#[cfg(test)] #[cfg(test)]

View File

@ -61,7 +61,7 @@ where
self.mutator_mut() self.mutator_mut()
.mutate(rand, corpus, &mut input_mut, i as i32)?; .mutate(rand, corpus, &mut input_mut, i as i32)?;
let fitness = state.evaluate_input(&input_mut, engine.executor_mut())?; let fitness = state.evaluate_input(&input_mut, engine.executor_mut(), corpus, manager)?;
self.mutator_mut() self.mutator_mut()
.post_exec(fitness, &input_mut, i as i32)?; .post_exec(fitness, &input_mut, i as i32)?;