diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index b6afb8ffa9..8559fd3037 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -24,10 +24,8 @@ pub trait StateMetadata: Debug { fn name(&self) -> &'static str; } -pub struct State +pub struct State where - C: Corpus, - E: Executor, I: Input, R: Rand, { @@ -35,16 +33,12 @@ where start_time: u64, metadatas: HashMap<&'static str, Box>, // additional_corpuses: HashMap<&'static str, Box>, - observers: Vec>>, feedbacks: Vec>>, - executor: E, - phantom: PhantomData<(C, R)>, + phantom: PhantomData, } -impl State +impl State where - C: Corpus, - E: Executor, I: Input, R: Rand, { @@ -108,10 +102,13 @@ where self.feedbacks_mut().push(feedback); } + // TODO move some of these, like evaluate_input, to FuzzingEngine + /// Runs the input and triggers observers and feedback - pub fn evaluate_input(&mut self, input: &I, engine: &FE) -> Result + pub fn evaluate_input(&mut self, input: &I, engine: &mut Engine) -> Result where - FE: FuzzingEngine, + C: Corpus, + E: Executor, EM: EventManager, { engine.executor_mut().reset_observers()?; @@ -120,7 +117,7 @@ where engine.executor_mut().post_exec_observers()?; let mut fitness = 0; - let observers = self.executor().observers(); + let observers = engine.executor().observers(); for feedback in self.feedbacks_mut() { fitness += feedback.is_interesting(&input, observers)?; } @@ -162,12 +159,15 @@ where } /// Adds this input to the corpus, if it's intersting - pub fn add_if_interesting( + pub fn add_if_interesting( &mut self, corpus: &mut C, input: I, fitness: u32, - ) -> Result, AflError> { + ) -> Result, AflError> + where + C: Corpus + { if fitness > 0 { let testcase = self.input_to_testcase(input, fitness)?; Ok(Some(corpus.add(testcase))) @@ -177,45 +177,95 @@ where } } - pub fn generate_initial_inputs( + pub fn generate_initial_inputs( &mut self, rand: &mut R, corpus: &mut C, generator: &mut G, - events: &mut EM, + engine: &mut Engine, num: usize, ) -> Result<(), AflError> where G: Generator, + C: Corpus, + E: Executor, EM: EventManager, { for _ in 0..num { let input = generator.generate(rand)?; - let fitness = self.evaluate_input(&input)?; + let fitness = self.evaluate_input(&input, engine)?; self.add_if_interesting(corpus, input, fitness)?; - events.fire(Event::LoadInitial { + engine.events_manager_mut().fire(Event::LoadInitial { sender_id: 0, phantom: PhantomData, })?; } - events.process(self, corpus)?; + engine.events_manager_mut().process(self, corpus)?; Ok(()) } - pub fn new(executor: E) -> Self { + pub fn new() -> Self { Self { executions: 0, start_time: current_milliseconds(), metadatas: HashMap::default(), - observers: vec![], feedbacks: vec![], - executor: executor, phantom: PhantomData, } } } -pub trait FuzzingEngine +pub struct Engine +where + EM: EventManager, + E: Executor, + C: Corpus, + I: Input, + R: Rand, +{ + manager: EM, + executor: E, + phantom: PhantomData<(C, I, R)> +} + +impl Engine +where + EM: EventManager, + E: Executor, + C: Corpus, + I: Input, + R: Rand, +{ + pub fn events_manager(&self) -> &EM { + &self.manager + } + + pub fn events_manager_mut(&mut self) -> &mut EM { + &mut self.manager + } + + /// Return the executor + pub fn executor(&self) -> &E { + &self.executor + } + + /// Return the executor (mutable) + pub fn executor_mut(&mut self) -> &mut E { + &mut self.executor + } + + // TODO additional executors, Vec>> + + pub fn new(executor: E, events_manager: EM) -> Self { + Self { + executor: executor, + manager: events_manager, + phantom: PhantomData + } + } +} + +pub trait Fuzzer where EM: EventManager, E: Executor, @@ -231,24 +281,12 @@ where self.stages_mut().push(stage); } - fn events_manager(&self) -> &EM; - - fn events_manager_mut(&mut self) -> &mut EM; - - /// Return the executor - fn executor(&self) -> &E; - - /// Return the executor (mutable) - fn executor_mut(&mut self) -> &mut E; - - // TODO additional executors, Vec>> - fn fuzz_one( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, - events: &mut EM, + engine: &mut Engine, ) -> Result { let (testcase, idx) = corpus.next(rand)?; match testcase.input() { @@ -262,27 +300,27 @@ where let input = corpus.get(idx).input().as_ref().unwrap(); for stage in self.stages_mut() { - stage.perform(rand, state, corpus, events, &input)?; + stage.perform(rand, state, corpus, engine, &input)?; } - events.process(state, corpus)?; + engine.events_manager_mut().process(state, corpus)?; Ok(idx) } fn fuzz_loop( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, - events: &mut EM, + engine: &mut Engine, ) -> Result<(), AflError> { let mut last = current_milliseconds(); loop { - self.fuzz_one(rand, state, corpus, events)?; + self.fuzz_one(rand, state, corpus, engine)?; let cur = current_milliseconds(); if cur - last > 60 * 100 { last = cur; - events.fire(Event::UpdateStats { + engine.events_manager_mut().fire(Event::UpdateStats { sender_id: 0, new_execs: 1, phantom: PhantomData, @@ -290,9 +328,10 @@ where } } } + } -pub struct StdFuzzingEngine +pub struct StdFuzzer where EM: EventManager, E: Executor, @@ -301,10 +340,9 @@ where R: Rand, { stages: Vec>>, - phantom: PhantomData, } -impl FuzzingEngine for StdFuzzingEngine +impl Fuzzer for StdFuzzer where EM: EventManager, E: Executor, @@ -321,7 +359,7 @@ where } } -impl StdFuzzingEngine +impl StdFuzzer where EM: EventManager, E: Executor, @@ -331,12 +369,12 @@ where { pub fn new() -> Self { Self { - stages: vec![], - phantom: PhantomData, + stages: vec![] } } } + // TODO: no_std test #[cfg(feature = "std")] #[cfg(test)] @@ -348,7 +386,7 @@ mod tests { use std::io::stderr; use crate::corpus::{Corpus, InMemoryCorpus, Testcase}; - use crate::engines::{Engine, StdEngine, StdState}; + use crate::engines::{Engine, Fuzzer, StdFuzzer, State}; #[cfg(feature = "std")] use crate::events::LoggerEventManager; use crate::executors::inmemory::InMemoryExecutor; @@ -371,21 +409,22 @@ mod tests { corpus.add(testcase); let executor = InMemoryExecutor::::new(harness); - let mut state = StdState::new(executor); + let mut state = State::new(); let mut events_manager = LoggerEventManager::new(stderr()); - let mut engine = StdEngine::new(); + let mut engine = Engine::new(executor, events_manager); let mut mutator = StdScheduledMutator::new(); mutator.add_mutation(mutation_bitflip); let stage = StdMutationalStage::new(mutator); - engine.add_stage(Box::new(stage)); + let mut fuzzer = StdFuzzer::new(); + fuzzer.add_stage(Box::new(stage)); // for i in 0..1000 { - engine - .fuzz_one(&mut rand, &mut state, &mut corpus, &mut events_manager) + fuzzer + .fuzz_one(&mut rand, &mut state, &mut corpus, &mut engine) .expect(&format!("Error in iter {}", i)); } } diff --git a/afl/src/events/llmp.rs b/afl/src/events/llmp.rs index f6adf68eab..66124b4689 100644 --- a/afl/src/events/llmp.rs +++ b/afl/src/events/llmp.rs @@ -60,35 +60,33 @@ pub unsafe fn llmp_tcp_server_clientloop(client: *mut LlmpClient, _data: *mut c_ /// Eventmanager for multi-processed application #[cfg(feature = "std")] -pub struct LLMPEventManager +pub struct LLMPEventManager where - S: State, C: Corpus, I: Input, E: Executor, R: Rand, - //CE: CustomEvent, + //CE: CustomEvent, { // TODO... - phantom: PhantomData<(S, C, E, I, R)>, + phantom: PhantomData<(C, E, I, R)>, is_broker: bool, } #[cfg(feature = "std")] -impl EventManager for LLMPEventManager +impl EventManager for LLMPEventManager where - S: State, C: Corpus, E: Executor, I: Input, R: Rand, - //CE: CustomEvent, + //CE: CustomEvent, { fn enabled(&self) -> bool { true } - fn fire(&mut self, _event: Event) -> Result<(), AflError> { + fn fire(&mut self, _event: Event) -> Result<(), AflError> { //self.events.push(event); // TODO: Serde serialize, llmp send @@ -96,7 +94,7 @@ where Ok(()) } - fn process(&mut self, _state: &mut S, _corpus: &mut C) -> Result { + fn process(&mut self, _state: &mut State, _corpus: &mut C) -> Result { // TODO: iterators /* let mut handled = vec![]; @@ -127,9 +125,8 @@ where } #[cfg(feature = "std")] -impl LLMPEventManager +impl LLMPEventManager where - S: State, C: Corpus, I: Input, E: Executor, diff --git a/afl/src/events/mod.rs b/afl/src/events/mod.rs index 42c104a693..94e9e57955 100644 --- a/afl/src/events/mod.rs +++ b/afl/src/events/mod.rs @@ -34,9 +34,9 @@ enum BrokerEventResult { /* /// A custom event, in case a user wants to extend the features (at compile time) -pub trait CustomEvent +pub trait CustomEvent where - S: State, + S: State, C: Corpus, E: Executor, I: Input, @@ -45,81 +45,79 @@ where /// Returns the name of this event fn name(&self) -> &str; /// This method will be called in the broker - fn handle_in_broker(&self, broker: &dyn EventManager, state: &mut S, corpus: &mut C) -> Result; + fn handle_in_broker(&self, broker: &dyn EventManager, state: &mut State, corpus: &mut C) -> Result; /// 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(&self, client: &dyn EventManager, state: &mut S, corpus: &mut C) -> Result<(), AflError>; + fn handle_in_client(&self, client: &dyn EventManager, state: &mut State, corpus: &mut C) -> Result<(), AflError>; } struct UnusedCustomEvent {} -impl CustomEvent for UnusedCustomEvent +impl CustomEvent for UnusedCustomEvent where - S: State, + S: State, C: Corpus, E: Executor, I: Input, R: Rand, { fn name(&self) -> &str {"No custom events"} - fn handle_in_broker(&self, broker: &dyn EventManager, state: &mut S, corpus: &mut C) {Ok(BrokerEventResult::Handled)} - fn handle_in_client(&self, client: &dyn EventManager, state: &mut S, corpus: &mut C) {Ok(())} + fn handle_in_broker(&self, broker: &dyn EventManager, state: &mut State, corpus: &mut C) {Ok(BrokerEventResult::Handled)} + fn handle_in_client(&self, client: &dyn EventManager, state: &mut State, corpus: &mut C) {Ok(())} } */ /// Events sent around in the library #[derive(Serialize, Deserialize)] -pub enum Event +pub enum Event where - S: State, C: Corpus, E: Executor, I: Input, R: Rand, - // CE: CustomEvent, + // CE: CustomEvent, { LoadInitial { sender_id: u64, - phantom: PhantomData<(S, C, E, I, R)>, + phantom: PhantomData<(C, E, I, R)>, }, NewTestcase { sender_id: u64, testcase: Testcase, - phantom: PhantomData<(S, C, E, I, R)>, + phantom: PhantomData<(C, E, I, R)>, }, UpdateStats { sender_id: u64, new_execs: usize, - phantom: PhantomData<(S, C, E, I, R)>, + phantom: PhantomData<(C, E, I, R)>, }, Crash { sender_id: u64, input: I, - phantom: PhantomData<(S, C, E, I, R)>, + phantom: PhantomData<(C, E, I, R)>, }, Timeout { sender_id: u64, input: I, - phantom: PhantomData<(S, C, E, I, R)>, + phantom: PhantomData<(C, E, I, R)>, }, Log { sender_id: u64, severity_level: u8, message: String, - phantom: PhantomData<(S, C, E, I, R)>, + phantom: PhantomData<(C, E, I, R)>, }, None { - phantom: PhantomData<(S, C, E, I, R)>, + phantom: PhantomData<(C, E, I, R)>, }, //Custom {sender_id: u64, custom_event: CE}, } -impl Event +impl Event where - S: State, C: Corpus, E: Executor, I: Input, R: Rand, - //CE: CustomEvent, + //CE: CustomEvent, { pub fn name(&self) -> &str { match self { @@ -160,7 +158,7 @@ where fn handle_in_broker( &self, - /*broker: &dyn EventManager,*/ _state: &mut S, + /*broker: &dyn EventManager,*/ _state: &mut State, _corpus: &mut C, ) -> Result { match self { @@ -215,7 +213,7 @@ where fn handle_in_client( self, - /*client: &dyn EventManager,*/ _state: &mut S, + /*client: &dyn EventManager,*/ _state: &mut State, corpus: &mut C, ) -> Result<(), AflError> { match self { @@ -236,9 +234,8 @@ where // TODO serialize and deserialize, defaults to serde } -pub trait EventManager +pub trait EventManager where - S: State, C: Corpus, E: Executor, I: Input, @@ -249,13 +246,13 @@ where fn enabled(&self) -> bool; /// Fire an Event - fn fire(&mut self, event: Event) -> Result<(), AflError>; + fn fire(&mut self, event: Event) -> Result<(), AflError>; /// Lookup for incoming events and process them. /// Return the number of processes events or an error - fn process(&mut self, state: &mut S, corpus: &mut C) -> Result; + fn process(&mut self, state: &mut State, corpus: &mut C) -> Result; - fn on_recv(&self, _state: &mut S, _corpus: &mut C) -> Result<(), AflError> { + fn on_recv(&self, _state: &mut State, _corpus: &mut C) -> Result<(), AflError> { // TODO: Better way to move out of testcase, or get ref //Ok(corpus.add(self.testcase.take().unwrap())) Ok(()) @@ -263,7 +260,7 @@ where } /*TODO - fn on_recv(&self, state: &mut S, _corpus: &mut C) -> Result<(), AflError> { + fn on_recv(&self, state: &mut State, _corpus: &mut C) -> Result<(), AflError> { println!( "#{}\t exec/s: {}", state.executions(), @@ -275,41 +272,39 @@ where */ #[cfg(feature = "std")] -pub struct LoggerEventManager +pub struct LoggerEventManager where - S: State, C: Corpus, I: Input, E: Executor, R: Rand, W: Write, - //CE: CustomEvent, + //CE: CustomEvent, { - events: Vec>, + events: Vec>, writer: W, } #[cfg(feature = "std")] -impl EventManager for LoggerEventManager +impl EventManager for LoggerEventManager where - S: State, C: Corpus, E: Executor, I: Input, R: Rand, W: Write, - //CE: CustomEvent, + //CE: CustomEvent, { fn enabled(&self) -> bool { true } - fn fire(&mut self, event: Event) -> Result<(), AflError> { + fn fire(&mut self, event: Event) -> Result<(), AflError> { self.events.push(event); Ok(()) } - fn process(&mut self, state: &mut S, corpus: &mut C) -> Result { + fn process(&mut self, state: &mut State, corpus: &mut C) -> Result { // TODO: iterators let mut handled = vec![]; for x in self.events.iter() { @@ -330,9 +325,8 @@ where } #[cfg(feature = "std")] -impl LoggerEventManager +impl LoggerEventManager where - S: State, C: Corpus, I: Input, E: Executor, diff --git a/afl/src/stages/mod.rs b/afl/src/stages/mod.rs index 833edeabcd..fa11984e90 100644 --- a/afl/src/stages/mod.rs +++ b/afl/src/stages/mod.rs @@ -2,7 +2,7 @@ pub mod mutational; pub use mutational::StdMutationalStage; use crate::corpus::Corpus; -use crate::engines::State; +use crate::engines::{Engine, State}; use crate::events::EventManager; use crate::executors::Executor; use crate::inputs::Input; @@ -21,9 +21,9 @@ where fn perform( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &C, - events: &mut EM, + engine: &mut Engine, input: &I, ) -> Result<(), AflError>; } diff --git a/afl/src/stages/mutational.rs b/afl/src/stages/mutational.rs index 9255e35714..5e323b4f20 100644 --- a/afl/src/stages/mutational.rs +++ b/afl/src/stages/mutational.rs @@ -5,18 +5,17 @@ use crate::executors::Executor; use crate::inputs::Input; use crate::mutators::Mutator; use crate::stages::Corpus; -use crate::stages::Stage; +use crate::stages::{Engine, Stage}; use crate::utils::Rand; use crate::AflError; use crate::{engines::State, events::Event}; // TODO multi mutators stage -pub trait MutationalStage: Stage +pub trait MutationalStage: Stage where M: Mutator, - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -38,9 +37,9 @@ where fn perform_mutational( &mut self, rand: &mut R, - state: &mut S, + state: &mut State, corpus: &C, - events: &mut EM, + engine: &mut Engine, input: &I, ) -> Result<(), AflError> { let num = self.iterations(rand); @@ -49,7 +48,7 @@ where self.mutator_mut() .mutate(rand, corpus, &mut input_mut, i as i32)?; - let fitness = state.evaluate_input(&input_mut)?; + let fitness = state.evaluate_input(&input_mut, engine)?; self.mutator_mut() .post_exec(fitness, &input_mut, i as i32)?; @@ -57,7 +56,7 @@ where let testcase_maybe = state.testcase_if_interesting(input_mut, fitness)?; if let Some(testcase) = testcase_maybe { //corpus.entries()[idx] - events.fire(Event::NewTestcase { + engine.events_manager_mut().fire(Event::NewTestcase { sender_id: 0, testcase: testcase, phantom: PhantomData, @@ -69,26 +68,24 @@ where } /// The default mutational stage -pub struct StdMutationalStage +pub struct StdMutationalStage where M: Mutator, - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, R: Rand, { mutator: M, - phantom: PhantomData<(S, EM, E, C, I, R)>, + phantom: PhantomData<(EM, E, C, I, R)>, } -impl MutationalStage - for StdMutationalStage +impl MutationalStage + for StdMutationalStage where M: Mutator, - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -105,11 +102,10 @@ where } } -impl Stage for StdMutationalStage +impl Stage for StdMutationalStage where M: Mutator, - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -118,20 +114,19 @@ where fn perform( &mut self, rand: &mut R, - state: &mut S, + state: &mut State, corpus: &C, - events: &mut EM, + engine: &mut Engine, input: &I, ) -> Result<(), AflError> { - self.perform_mutational(rand, state, corpus, events, input) + self.perform_mutational(rand, state, corpus, engine, input) } } -impl StdMutationalStage +impl StdMutationalStage where M: Mutator, - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input,