diff --git a/src/corpus/mod.rs b/src/corpus/mod.rs index 22e88c0c23..90ebe8f297 100644 --- a/src/corpus/mod.rs +++ b/src/corpus/mod.rs @@ -24,6 +24,7 @@ pub trait Corpus : HasEntriesVec + HasRand where I: Input { } /// Add an entry to the corpus + #[allow(unused_mut)] fn add(&mut self, mut entry: Box>) { self.entries_mut().push(entry); } diff --git a/src/engines/aflengine.rs b/src/engines/aflengine.rs index bf8fa0080c..28635e72f6 100644 --- a/src/engines/aflengine.rs +++ b/src/engines/aflengine.rs @@ -8,14 +8,14 @@ use crate::monitors::Monitor; use crate::stages::Stage; use crate::utils::Rand; -pub struct AflEngine<'a, InputT: Input> { +pub struct AflEngine<'a, I: Input> { pub rand: &'a mut dyn Rand, - pub feedbacks: Vec>>, + pub feedbacks: Vec>>, - pub stages: Vec>>, - pub current_stage: &'a Box>, + pub stages: Vec>>, + pub current_stage: &'a Box>, - pub executor: Box, + pub executor: Box>, pub executions: u64, @@ -26,4 +26,4 @@ pub struct AflEngine<'a, InputT: Input> { pub monitors: Vec>, } -impl Engine<'_> for AflEngine<'_, InputT> {} +impl Engine<'_> for AflEngine<'_, I> {} diff --git a/src/executors/inmemory.rs b/src/executors/inmemory.rs index 84a8b0fce9..a2c092bedc 100644 --- a/src/executors/inmemory.rs +++ b/src/executors/inmemory.rs @@ -2,20 +2,89 @@ use crate::inputs::Input; use crate::observers::Observer; use crate::AflError; -use crate::executors::{Executor, ExitKind, ExecutorBase}; +use crate::executors::{Executor, ExitKind}; use std::ptr; +use std::os::raw::c_void; -type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; +type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; -pub struct InMemoryExecutor { - base: ExecutorBase, - harness: HarnessFunction, +pub struct InMemoryExecutor where I: Input { + cur_input: Option>, + observers: Vec>, + harness: HarnessFunction, } -static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const InMemoryExecutor = ptr::null(); +static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null(); + +impl Executor for InMemoryExecutor where I: Input { + fn run_target(&mut self) -> Result { + let bytes = match self.cur_input.as_ref() { + Some(i) => i.serialize(), + None => return Err(AflError::Empty("cur_input".to_string())), + }; + unsafe { + CURRENT_INMEMORY_EXECUTOR_PTR = self as *const InMemoryExecutor as *const c_void; + } + let ret = match bytes { + Ok(b) => Ok((self.harness)(self, b)), + Err(e) => Err(e), + }; + unsafe { + CURRENT_INMEMORY_EXECUTOR_PTR = ptr::null(); + } + ret + } + + fn place_input(&mut self, input: Box) -> Result<(), AflError> { + self.cur_input = Some(input); + Ok(()) + } + + fn cur_input(&self) -> &Option> { + &self.cur_input + } + + fn cur_input_mut(&mut self) -> &mut Option> { + &mut self.cur_input + } + + fn reset_observers(&mut self) -> Result<(), AflError> { + for observer in &mut self.observers { + observer.reset()?; + } + Ok(()) + } + + fn post_exec_observers(&mut self) -> Result<(), AflError> { + self.observers + .iter_mut() + .map(|x| x.post_exec()) + .fold(Ok(()), |acc, x| if x.is_err() { x } else { acc }) + } + + fn add_observer(&mut self, observer: Box) { + self.observers.push(observer); + } + + fn observers(&self) -> &Vec> { + &self.observers + } +} + +impl InMemoryExecutor where I: Input { + pub fn new(harness_fn: HarnessFunction) -> Self { + unsafe { + os_signals::setup_crash_handlers::(); + } + InMemoryExecutor { + cur_input: None, + observers: vec![], + harness: harness_fn, + } + } +} -/// TODO move in platform/ #[cfg(unix)] pub mod unix_signals { @@ -29,12 +98,14 @@ pub mod unix_signals { use std::{mem, process, ptr}; use crate::executors::inmemory::CURRENT_INMEMORY_EXECUTOR_PTR; + use crate::inputs::Input; + use crate::executors::Executor; - pub extern "C" fn libaflrs_executor_inmem_handle_crash( + pub extern "C" fn libaflrs_executor_inmem_handle_crash( _sig: c_int, info: siginfo_t, _void: c_void, - ) { + ) where I: Input, E: Executor { unsafe { if CURRENT_INMEMORY_EXECUTOR_PTR == ptr::null() { println!( @@ -48,11 +119,11 @@ pub mod unix_signals { let _ = stdout().flush(); } - pub extern "C" fn libaflrs_executor_inmem_handle_timeout( + pub extern "C" fn libaflrs_executor_inmem_handle_timeout( _sig: c_int, _info: siginfo_t, _void: c_void, - ) { + ) where I: Input, E: Executor { dbg!("TIMEOUT/SIGUSR2 received"); unsafe { if CURRENT_INMEMORY_EXECUTOR_PTR == ptr::null() { @@ -66,11 +137,11 @@ pub mod unix_signals { process::abort(); } - pub unsafe fn setup_crash_handlers() { + pub unsafe fn setup_crash_handlers() where I: Input, E: Executor { let mut sa: sigaction = mem::zeroed(); libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t); sa.sa_flags = SA_NODEFER | SA_SIGINFO; - sa.sa_sigaction = libaflrs_executor_inmem_handle_crash as usize; + sa.sa_sigaction = libaflrs_executor_inmem_handle_crash:: as usize; for (sig, msg) in &[ (SIGSEGV, "segfault"), (SIGBUS, "sigbus"), @@ -84,7 +155,7 @@ pub mod unix_signals { } } - sa.sa_sigaction = libaflrs_executor_inmem_handle_timeout as usize; + sa.sa_sigaction = libaflrs_executor_inmem_handle_timeout:: as usize; if sigaction(SIGUSR2, &mut sa as *mut sigaction, ptr::null_mut()) < 0 { panic!("Could not set up sigusr2 handler for timeouts"); } @@ -96,72 +167,6 @@ use unix_signals as os_signals; #[cfg(not(unix))] compile_error!("InMemoryExecutor not yet supported on this OS"); -impl Executor for InMemoryExecutor { - fn run_target(&mut self) -> Result { - let bytes = match self.base.cur_input.as_ref() { - Some(i) => i.serialize(), - None => return Err(AflError::Empty("cur_input".to_string())), - }; - unsafe { - CURRENT_INMEMORY_EXECUTOR_PTR = self as *const InMemoryExecutor; - } - let ret = match bytes { - Ok(b) => Ok((self.harness)(self, b)), - Err(e) => Err(e), - }; - unsafe { - CURRENT_INMEMORY_EXECUTOR_PTR = ptr::null(); - } - ret - } - - fn place_input(&mut self, input: Box) -> Result<(), AflError> { - self.base.cur_input = Some(input); - Ok(()) - } - - fn get_input(&self) -> Option<& Box> { - self.base.cur_input.as_ref() - } - - fn reset_observers(&mut self) -> Result<(), AflError> { - for observer in &mut self.base.observers { - observer.reset()?; - } - Ok(()) - } - - fn post_exec_observers(&mut self) -> Result<(), AflError> { - self.base - .observers - .iter_mut() - .map(|x| x.post_exec()) - .fold(Ok(()), |acc, x| if x.is_err() { x } else { acc }) - } - - fn add_observer(&mut self, observer: Box) { - self.base.observers.push(observer); - } - - fn get_observers(&self) -> &Vec> { - &self.base.observers - } -} - -impl InMemoryExecutor { - pub fn new(harness_fn: HarnessFunction) -> InMemoryExecutor { - unsafe { - os_signals::setup_crash_handlers(); - } - InMemoryExecutor { - base: ExecutorBase { - observers: vec![], - cur_input: Option::None, - }, - harness: harness_fn, - } - } -} #[cfg(test)] mod tests { @@ -197,7 +202,7 @@ mod tests { } } - fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { + fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { println! {"Fake exec with buf of len {}", buf.len()}; ExitKind::Ok } diff --git a/src/executors/mod.rs b/src/executors/mod.rs index d0f484054b..a99b92f967 100644 --- a/src/executors/mod.rs +++ b/src/executors/mod.rs @@ -12,24 +12,30 @@ pub enum ExitKind { Timeout, } -pub trait Executor { +// TODO unbox input + +pub trait Executor where I: Input { + /// Run the target fn run_target(&mut self) -> Result; - fn place_input(&mut self, input: Box) -> Result<(), AflError>; + /// Instruct the target about the input before the run + fn place_input(&mut self, input: Box) -> Result<(), AflError>; - fn get_input(&self) -> Option<& Box>; + /// Get the current input, if any + fn cur_input(&self) -> &Option>; + /// Get the current input, if any (mutable) + fn cur_input_mut(&mut self) -> &mut Option>; + + /// Reset the state of all the observes linked to this executor fn reset_observers(&mut self) -> Result<(), AflError>; + /// Run the post exec hook for all the observes linked to this executor fn post_exec_observers(&mut self) -> Result<(), AflError>; + /// Add a linked observer fn add_observer(&mut self, observer: Box); - fn get_observers(&self) -> &Vec>; -} - -// TODO abstract classes? how? -pub struct ExecutorBase { - observers: Vec>, - cur_input: Option>, -} + /// Get the linked observers + fn observers(&self) -> &Vec>; +} \ No newline at end of file diff --git a/src/feedbacks/mod.rs b/src/feedbacks/mod.rs index 6aaf394287..48f636fd20 100644 --- a/src/feedbacks/mod.rs +++ b/src/feedbacks/mod.rs @@ -8,9 +8,9 @@ use crate::observers::MapObserver; use num::Integer; use std::marker::PhantomData; -pub trait Feedback { +pub trait Feedback where I: Input { /// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55) - fn is_interesting(&mut self, executor: &dyn Executor, entry: &Testcase) -> u8; + fn is_interesting(&mut self, executor: &dyn Executor, entry: &Testcase) -> u8; } /*