diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index 5200fa3c27..b8fac17e57 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -33,12 +33,11 @@ pub trait StateMetadata: Debug { /// The state a fuzz run. #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "FT: serde::de::DeserializeOwned")] -pub struct State +pub struct State where I: Input, R: Rand, FT: FeedbacksTuple, - OT: ObserversTuple, { /// How many times the executor ran the harness/target executions: usize, @@ -49,17 +48,16 @@ where // additional_corpuses, maybe another TupleList? // Feedbacks used to evaluate an input feedbacks: FT, - phantom: PhantomData<(I, R, OT)>, + phantom: PhantomData<(I, R)>, } #[cfg(feature = "std")] -impl State +impl State where R: Rand, FT: FeedbacksTuple, - OT: ObserversTuple, { - pub fn load_from_directory( + pub fn load_from_directory( &mut self, corpus: &mut C, generator: &mut G, @@ -71,8 +69,9 @@ where G: Generator, C: Corpus, E: Executor + HasObservers, + OT: ObserversTuple, ET: ExecutorsTuple, - EM: EventManager, + EM: EventManager, { for entry in fs::read_dir(in_dir)? { let entry = entry?; @@ -101,7 +100,7 @@ where Ok(()) } - pub fn load_initial_inputs( + pub fn load_initial_inputs( &mut self, corpus: &mut C, generator: &mut G, @@ -113,8 +112,9 @@ where G: Generator, C: Corpus, E: Executor + HasObservers, + OT: ObserversTuple, ET: ExecutorsTuple, - EM: EventManager, + EM: EventManager, { for in_dir in in_dirs { self.load_from_directory(corpus, generator, engine, manager, in_dir)?; @@ -128,12 +128,11 @@ where } } -impl State +impl State where I: Input, R: Rand, FT: FeedbacksTuple, - OT: ObserversTuple, { /// Get executions #[inline] @@ -206,7 +205,7 @@ where // TODO move some of these, like evaluate_input, to FuzzingEngine #[inline] - pub fn is_interesting(&mut self, input: &I, observers: &OT) -> Result + pub fn is_interesting(&mut self, input: &I, observers: &OT) -> Result where OT: ObserversTuple, { @@ -214,9 +213,10 @@ where } /// Runs the input and triggers observers and feedback - pub fn evaluate_input(&mut self, input: &I, executor: &mut E) -> Result + pub fn evaluate_input(&mut self, input: &I, executor: &mut E) -> Result where E: Executor + HasObservers, + OT: ObserversTuple, { executor.reset_observers()?; executor.run_target(&input)?; @@ -279,7 +279,7 @@ where } } - pub fn generate_initial_inputs( + pub fn generate_initial_inputs( &mut self, rand: &mut R, corpus: &mut C, @@ -292,8 +292,9 @@ where G: Generator, C: Corpus, E: Executor + HasObservers, + OT: ObserversTuple, ET: ExecutorsTuple, - EM: EventManager, + EM: EventManager, { let mut added = 0; for _ in 0..num { @@ -383,7 +384,7 @@ where pub trait Fuzzer where ST: StagesTuple, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -399,7 +400,7 @@ where fn fuzz_one( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, engine: &mut Engine, manager: &mut EM, @@ -416,7 +417,7 @@ where fn fuzz_loop( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, engine: &mut Engine, manager: &mut EM, @@ -437,7 +438,7 @@ where pub struct StdFuzzer where ST: StagesTuple, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -454,7 +455,7 @@ impl Fuzzer for StdFuzzer where ST: StagesTuple, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -475,7 +476,7 @@ where impl StdFuzzer where ST: StagesTuple, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, diff --git a/afl/src/events/mod.rs b/afl/src/events/mod.rs index 891260e0fd..b202d44c92 100644 --- a/afl/src/events/mod.rs +++ b/afl/src/events/mod.rs @@ -211,23 +211,21 @@ where where ST: Stats; /// 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( + fn handle_in_client( self, - state: &mut State, + state: &mut State, corpus: &mut C, ) -> Result<(), AflError> where C: Corpus, - OT: ObserversTuple, FT: FeedbacksTuple, R: Rand; } -pub trait EventManager +pub trait EventManager where C: Corpus, E: Executor, - OT: ObserversTuple, FT: FeedbacksTuple, I: Input, R: Rand, @@ -239,25 +237,25 @@ where /// Return the number of processes events or an error fn process( &mut self, - state: &mut State, + state: &mut State, corpus: &mut C, ) -> Result; - fn serialize_observers(&mut self, observers: &OT) -> Result, AflError> { + fn serialize_observers(&mut self, observers: &OT) -> Result, AflError> where OT: ObserversTuple { Ok(postcard::to_allocvec(observers)?) } - fn deserialize_observers(&mut self, observers_buf: &[u8]) -> Result { + fn deserialize_observers(&mut self, observers_buf: &[u8]) -> Result where OT: ObserversTuple { Ok(postcard::from_bytes(observers_buf)?) } - fn new_testcase( + fn new_testcase( &mut self, _input: &I, _observers: &OT, _corpus_size: usize, _config: String, - ) -> Result<(), AflError> { + ) -> Result<(), AflError> where OT: ObserversTuple { Ok(()) } @@ -384,14 +382,13 @@ where } #[inline] - fn handle_in_client( + fn handle_in_client( self, - _state: &mut State, + _state: &mut State, _corpus: &mut C, ) -> Result<(), AflError> where C: Corpus, - OT: ObserversTuple, FT: FeedbacksTuple, R: Rand, { @@ -405,11 +402,10 @@ where } #[derive(Clone, Debug)] -pub struct LoggerEventManager +pub struct LoggerEventManager where C: Corpus, E: Executor, - OT: ObserversTuple, FT: FeedbacksTuple, I: Input, R: Rand, @@ -419,15 +415,14 @@ where stats: ST, events: Vec>, // stats (maybe we need a separated struct?) - phantom: PhantomData<(C, E, I, R, OT, FT)>, + phantom: PhantomData<(C, E, I, R, FT)>, } -impl EventManager - for LoggerEventManager +impl EventManager + for LoggerEventManager where C: Corpus, E: Executor, - OT: ObserversTuple, FT: FeedbacksTuple, I: Input, R: Rand, @@ -436,7 +431,7 @@ where { fn process( &mut self, - state: &mut State, + state: &mut State, corpus: &mut C, ) -> Result { let count = self.events.len(); @@ -446,13 +441,13 @@ where Ok(count) } - fn new_testcase( + fn new_testcase( &mut self, _input: &I, _observers: &OT, corpus_size: usize, _config: String, - ) -> Result<(), AflError> { + ) -> Result<(), AflError> where OT: ObserversTuple { let event = LoggerEvent::NewTestcase { corpus_size: corpus_size, phantom: PhantomData, @@ -513,12 +508,11 @@ where } } -impl LoggerEventManager +impl LoggerEventManager where C: Corpus, I: Input, E: Executor, - OT: ObserversTuple, FT: FeedbacksTuple, R: Rand, ST: Stats, @@ -658,14 +652,13 @@ where } #[inline] - fn handle_in_client( + fn handle_in_client( self, - state: &mut State, + state: &mut State, corpus: &mut C, ) -> Result<(), AflError> where C: Corpus, - OT: ObserversTuple, FT: FeedbacksTuple, R: Rand, { @@ -706,11 +699,10 @@ const _LLMP_TAG_EVENT_TO_BROKER: llmp::Tag = 0x2B80438; const LLMP_TAG_EVENT_TO_BOTH: llmp::Tag = 0x2B0741; #[derive(Clone, Debug)] -pub struct LlmpEventManager +pub struct LlmpEventManager where C: Corpus, E: Executor, - OT: ObserversTuple, FT: FeedbacksTuple, I: Input, R: Rand, @@ -720,15 +712,14 @@ where { llmp: llmp::LlmpConnection, stats: ST, - phantom: PhantomData<(C, E, OT, FT, I, R)>, + phantom: PhantomData<(C, E, FT, I, R)>, } #[cfg(feature = "std")] -impl LlmpEventManager +impl LlmpEventManager where C: Corpus, E: Executor, - OT: ObserversTuple, FT: FeedbacksTuple, I: Input, R: Rand, @@ -754,11 +745,10 @@ where } } -impl LlmpEventManager +impl LlmpEventManager where C: Corpus, E: Executor, - OT: ObserversTuple, FT: FeedbacksTuple, I: Input, R: Rand, @@ -859,13 +849,12 @@ where } } -impl EventManager - for LlmpEventManager +impl EventManager + for LlmpEventManager where C: Corpus, E: Executor, FT: FeedbacksTuple, - OT: ObserversTuple, I: Input, R: Rand, SH: ShMem, @@ -874,7 +863,7 @@ where { fn process( &mut self, - state: &mut State, + state: &mut State, corpus: &mut C, ) -> Result { // TODO: Get around local event copy by moving handle_in_client @@ -907,13 +896,13 @@ where }) } - fn new_testcase( + fn new_testcase( &mut self, input: &I, observers: &OT, corpus_size: usize, config: String, - ) -> Result<(), AflError> { + ) -> Result<(), AflError> where OT: ObserversTuple { let kind = LLMPEventKind::NewTestcase { input: Ptr::Ref(input), observers_buf: postcard::to_allocvec(observers)?, diff --git a/afl/src/executors/inmemory.rs b/afl/src/executors/inmemory.rs index f7235acd3d..8fc6ae3378 100644 --- a/afl/src/executors/inmemory.rs +++ b/afl/src/executors/inmemory.rs @@ -1,5 +1,5 @@ use alloc::{boxed::Box, string::ToString, vec::Vec}; -use core::{ffi::c_void, ptr}; +use core::{marker::PhantomData, ffi::c_void, ptr}; use crate::{ 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. /// 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_ON_CRASH_FN: *mut Box = 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 type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; +type OnCrashFunction = fn(ExitKind, &State, &C, &mut EM); /// The inmem executor simply calls a target function, then returns afterwards. -pub struct InMemoryExecutor +pub struct InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, + C: Corpus, + E: Executor, + EM: EventManager, + FT: FeedbacksTuple, + R: Rand, { /// The name of this executor instance, to address it from other components name: &'static str, @@ -38,19 +48,26 @@ where /// The observers, observing each run observers: OT, /// A special function being called right before the process crashes. It may save state to restore fuzzing after respawn. - on_crash_fn: Box, + on_crash_fn: OnCrashFunction, + + phantom: PhantomData } -impl Executor for InMemoryExecutor +impl Executor for InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, + C: Corpus, + E: Executor, + EM: EventManager, + FT: FeedbacksTuple, + R: Rand, { #[inline] fn run_target(&mut self, input: &I) -> Result { let bytes = input.target_bytes(); 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; } let ret = (self.harness)(self, bytes.as_slice()); @@ -62,20 +79,30 @@ where } } -impl Named for InMemoryExecutor +impl Named for InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, + C: Corpus, + E: Executor, + EM: EventManager, + FT: FeedbacksTuple, + R: Rand, { fn name(&self) -> &str { self.name } } -impl HasObservers for InMemoryExecutor +impl HasObservers for InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, + C: Corpus, + E: Executor, + EM: EventManager, + FT: FeedbacksTuple, + R: Rand, { #[inline] fn observers(&self) -> &OT { @@ -88,10 +115,15 @@ where } } -impl InMemoryExecutor +impl InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, + C: Corpus, + E: Executor, + EM: EventManager, + FT: FeedbacksTuple, + R: Rand, { /// Create a new in mem executor. /// 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. /// Do that that in this function. The program will crash afterwards. /// * `observers` - the observers observing the target during execution - pub fn new( + pub fn new( name: &'static str, harness_fn: HarnessFunction, observers: OT, - on_crash_fn: Box, - _state: &State, - _corpus: &C, - _event_manager: &mut EM, + on_crash_fn: OnCrashFunction, ) -> Self - where - C: Corpus, - E: Executor, - EM: EventManager, - FT: FeedbacksTuple, - R: Rand, { - #[cfg(feature = "std")] + /*#[cfg(feature = "std")] unsafe { CORPUS_PTR = _corpus as *const _ as *const c_void; STATE_PTR = _state as *const _ as *const c_void; setup_crash_handlers(_event_manager); - } + }*/ Self { harness: harness_fn, on_crash_fn, observers, 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. /// This method is needed when the fuzzer run crashes and has to restart. pub unsafe fn serialize_state_corpus() -> Result, AflError> @@ -153,7 +174,7 @@ where .to_string(), )); } - let state: &State = (STATE_PTR as *const State).as_ref().unwrap(); + let state: &State = (STATE_PTR as *const State).as_ref().unwrap(); let corpus = (CORPUS_PTR as *mut C).as_ref().unwrap(); let state_bytes = postcard::to_allocvec(&state)?; let corpus_bytes = postcard::to_allocvec(&corpus)?; @@ -163,7 +184,7 @@ where /// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` pub fn deserialize_state_corpus( state_corpus_serialized: &[u8], -) -> Result<(State, C), AflError> +) -> Result<(State, C), AflError> where C: Corpus, FT: FeedbacksTuple, @@ -201,23 +222,22 @@ pub mod unix_signals { corpus::Corpus, events::EventManager, 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, }, + engines::State, feedbacks::FeedbacksTuple, inputs::Input, observers::ObserversTuple, utils::Rand, }; - static mut EVENT_MANAGER_PTR: *mut c_void = ptr::null_mut(); - pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash( _sig: c_int, info: siginfo_t, _void: c_void, ) where - EM: EventManager, + EM: EventManager, C: Corpus, E: Executor, OT: ObserversTuple, @@ -238,14 +258,18 @@ pub mod unix_signals { let _ = stdout().flush(); 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).as_ref().unwrap(); let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap(); manager.crash(input).expect("Error in sending Crash event"); if !CURRENT_ON_CRASH_FN.is_null() { - (*CURRENT_ON_CRASH_FN)( + (*(CURRENT_ON_CRASH_FN as *mut OnCrashFunction))( ExitKind::Crash, - &serialize_state_corpus::().unwrap(), + state, + corpus, + manager ); } @@ -257,7 +281,7 @@ pub mod unix_signals { _info: siginfo_t, _void: c_void, ) where - EM: EventManager, + EM: EventManager, C: Corpus, E: Executor, OT: ObserversTuple, @@ -272,6 +296,8 @@ pub mod unix_signals { } 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).as_ref().unwrap(); let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap(); manager @@ -279,9 +305,11 @@ pub mod unix_signals { .expect("Error in sending Timeout event"); if !CURRENT_ON_CRASH_FN.is_null() { - (*CURRENT_ON_CRASH_FN)( + (*(CURRENT_ON_CRASH_FN as *mut OnCrashFunction))( ExitKind::Timeout, - &serialize_state_corpus::().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?) - pub unsafe fn setup_crash_handlers(manager: &mut EM) + pub unsafe fn setup_crash_handlers(state: &State, corpus: &C, manager: &mut EM) where - EM: EventManager, + EM: EventManager, C: Corpus, E: Executor, OT: ObserversTuple, @@ -302,8 +330,10 @@ pub mod unix_signals { I: Input, 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; - + let mut sa: sigaction = mem::zeroed(); libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t); sa.sa_flags = SA_NODEFER | SA_SIGINFO; diff --git a/afl/src/stages/mod.rs b/afl/src/stages/mod.rs index 4c10a60b3b..2d25b8d3dc 100644 --- a/afl/src/stages/mod.rs +++ b/afl/src/stages/mod.rs @@ -16,7 +16,7 @@ use crate::AflError; /// Multiple stages will be scheduled one by one for each input. pub trait Stage where - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -29,7 +29,7 @@ where fn perform( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, engine: &mut Engine, manager: &mut EM, @@ -39,7 +39,7 @@ where pub trait StagesTuple where - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -51,7 +51,7 @@ where fn perform_all( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, engine: &mut Engine, manager: &mut EM, @@ -63,7 +63,7 @@ where impl StagesTuple for () where - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -75,7 +75,7 @@ where fn perform_all( &mut self, _rand: &mut R, - _state: &mut State, + _state: &mut State, _corpus: &mut C, _engine: &mut Engine, _manager: &mut EM, @@ -92,7 +92,7 @@ impl StagesTuple, Tail: StagesTuple + TupleList, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -104,7 +104,7 @@ where fn perform_all( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, engine: &mut Engine, manager: &mut EM, diff --git a/afl/src/stages/mutational.rs b/afl/src/stages/mutational.rs index 0ba30a8e37..946341c5f4 100644 --- a/afl/src/stages/mutational.rs +++ b/afl/src/stages/mutational.rs @@ -21,7 +21,7 @@ pub trait MutationalStage: Stage where M: Mutator, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -47,7 +47,7 @@ where fn perform_mutational( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, engine: &mut Engine, manager: &mut EM, @@ -89,7 +89,7 @@ where pub struct StdMutationalStage where M: Mutator, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -106,7 +106,7 @@ impl MutationalStage where M: Mutator, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -132,7 +132,7 @@ impl Stage for StdMutationalStage where M: Mutator, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -145,7 +145,7 @@ where fn perform( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, engine: &mut Engine, manager: &mut EM, @@ -158,7 +158,7 @@ where impl StdMutationalStage where M: Mutator, - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple,