diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index 3685543e56..b6afb8ffa9 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -19,167 +19,12 @@ use crate::stages::Stage; use crate::utils::{current_milliseconds, Rand}; use crate::AflError; -// TODO FeedbackMetadata to store histroy_map - pub trait StateMetadata: Debug { /// The name of this metadata - used to find it in the list of avaliable metadatas fn name(&self) -> &'static str; } -pub trait State -where - C: Corpus, - E: Executor, - I: Input, - R: Rand, -{ - /// Get executions - fn executions(&self) -> usize; - - /// Set executions - fn set_executions(&mut self, executions: usize); - - fn start_time(&self) -> u64; - fn set_start_time(&mut self, ms: u64); - - fn executions_over_seconds(&self) -> u64 { - let elapsed = current_milliseconds() - self.start_time(); - if elapsed == 0 { - return 0; - } - let elapsed = elapsed / 1000; - if elapsed == 0 { - 0 - } else { - (self.executions() as u64) / elapsed - } - } - - /// Get all the metadatas into an HashMap - fn metadatas(&self) -> &HashMap<&'static str, Box>; - - /// Get all the metadatas into an HashMap (mutable) - fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box>; - - /// Add a metadata - fn add_metadata(&mut self, meta: Box) { - self.metadatas_mut().insert(meta.name(), meta); - } - - /// Returns vector of feebacks - fn feedbacks(&self) -> &[Box>]; - - /// Returns vector of feebacks (mutable) - fn feedbacks_mut(&mut self) -> &mut Vec>>; - - /// Adds a feedback - fn add_feedback(&mut self, feedback: Box>) { - self.feedbacks_mut().push(feedback); - } - - /// Return the executor - fn executor(&self) -> &E; - - /// Return the executor (mutable) - fn executor_mut(&mut self) -> &mut E; - - /// Runs the input and triggers observers and feedback - fn evaluate_input(&mut self, input: &I) -> Result { - self.executor_mut().reset_observers()?; - self.executor_mut().run_target(&input)?; - self.set_executions(self.executions() + 1); - self.executor_mut().post_exec_observers()?; - - let mut fitness = 0; - let observers = self.executor().observers(); - for feedback in self.feedbacks_mut() { - fitness += feedback.is_interesting(&input, observers)?; - } - Ok(fitness) - } - - /// Resets all current feedbacks - fn discard_input(&mut self, input: &I) -> Result<(), AflError> { - // TODO: This could probably be automatic in the feedback somehow? - for feedback in self.feedbacks_mut() { - feedback.discard_metadata(input)?; - } - Ok(()) - } - - /// Creates a new testcase, appending the metadata from each feedback - fn input_to_testcase(&mut self, input: I, fitness: u32) -> Result, AflError> { - let mut testcase = Testcase::new(input); - testcase.set_fitness(fitness); - for feedback in self.feedbacks_mut() { - feedback.append_metadata(&mut testcase)?; - } - - Ok(testcase) - } - - /// Create a testcase from this input, if it's intersting - fn testcase_if_interesting( - &mut self, - input: I, - fitness: u32, - ) -> Result>, AflError> { - if fitness > 0 { - Ok(Some(self.input_to_testcase(input, fitness)?)) - } else { - self.discard_input(&input)?; - Ok(None) - } - } - - /// Adds this input to the corpus, if it's intersting - fn add_if_interesting( - &mut self, - corpus: &mut C, - input: I, - fitness: u32, - ) -> Result, AflError> { - if fitness > 0 { - let testcase = self.input_to_testcase(input, fitness)?; - Ok(Some(corpus.add(testcase))) - } else { - self.discard_input(&input)?; - Ok(None) - } - } -} - -pub fn generate_initial_inputs( - rand: &mut R, - state: &mut S, - corpus: &mut C, - generator: &mut G, - events: &mut EM, - num: usize, -) -> Result<(), AflError> -where - S: State, - G: Generator, - C: Corpus, - E: Executor, - I: Input, - R: Rand, - EM: EventManager, -{ - for _ in 0..num { - let input = generator.generate(rand)?; - let fitness = state.evaluate_input(&input)?; - state.add_if_interesting(corpus, input, fitness)?; - events.fire(Event::LoadInitial { - sender_id: 0, - phantom: PhantomData, - })?; - } - events.process(state, corpus)?; - Ok(()) -} - -pub struct StdState +pub struct State where C: Corpus, E: Executor, @@ -196,60 +41,167 @@ where phantom: PhantomData<(C, R)>, } -impl State for StdState +impl State where C: Corpus, E: Executor, I: Input, R: Rand, { - fn executions(&self) -> usize { + /// Get executions + pub fn executions(&self) -> usize { self.executions } - fn set_executions(&mut self, executions: usize) { + /// Set executions + pub fn set_executions(&mut self, executions: usize){ self.executions = executions } - fn start_time(&self) -> u64 { + pub fn start_time(&self) -> u64{ self.start_time } - fn set_start_time(&mut self, ms: u64) { + pub fn set_start_time(&mut self, ms: u64) { self.start_time = ms } - fn metadatas(&self) -> &HashMap<&'static str, Box> { + pub fn executions_over_seconds(&self) -> u64 { + let elapsed = current_milliseconds() - self.start_time(); + if elapsed == 0 { + return 0; + } + let elapsed = elapsed / 1000; + if elapsed == 0 { + 0 + } else { + (self.executions() as u64) / elapsed + } + } + + /// Get all the metadatas into an HashMap + pub fn metadatas(&self) -> &HashMap<&'static str, Box>{ &self.metadatas } - fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box> { + /// Get all the metadatas into an HashMap (mutable) + pub fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box>{ &mut self.metadatas } - fn feedbacks(&self) -> &[Box>] { + /// Add a metadata + pub fn add_metadata(&mut self, meta: Box) { + self.metadatas_mut().insert(meta.name(), meta); + } + + /// Returns vector of feebacks + pub fn feedbacks(&self) -> &[Box>]{ &self.feedbacks } - fn feedbacks_mut(&mut self) -> &mut Vec>> { + /// Returns vector of feebacks (mutable) + pub fn feedbacks_mut(&mut self) -> &mut Vec>>{ &mut self.feedbacks } - fn executor(&self) -> &E { - &self.executor + /// Adds a feedback + pub fn add_feedback(&mut self, feedback: Box>) { + self.feedbacks_mut().push(feedback); } - fn executor_mut(&mut self) -> &mut E { - &mut self.executor - } -} + /// Runs the input and triggers observers and feedback + pub fn evaluate_input(&mut self, input: &I, engine: &FE) -> Result + where + FE: FuzzingEngine, + EM: EventManager, + { + engine.executor_mut().reset_observers()?; + engine.executor_mut().run_target(&input)?; + self.set_executions(self.executions() + 1); + engine.executor_mut().post_exec_observers()?; + + let mut fitness = 0; + let observers = self.executor().observers(); + for feedback in self.feedbacks_mut() { + fitness += feedback.is_interesting(&input, observers)?; + } + Ok(fitness) + } + + /// Resets all current feedbacks + pub fn discard_input(&mut self, input: &I) -> Result<(), AflError> { + // TODO: This could probably be automatic in the feedback somehow? + for feedback in self.feedbacks_mut() { + feedback.discard_metadata(input)?; + } + Ok(()) + } + + /// Creates a new testcase, appending the metadata from each feedback + pub fn input_to_testcase(&mut self, input: I, fitness: u32) -> Result, AflError> { + let mut testcase = Testcase::new(input); + testcase.set_fitness(fitness); + for feedback in self.feedbacks_mut() { + feedback.append_metadata(&mut testcase)?; + } + + Ok(testcase) + } + + /// Create a testcase from this input, if it's intersting + pub fn testcase_if_interesting( + &mut self, + input: I, + fitness: u32, + ) -> Result>, AflError> { + if fitness > 0 { + Ok(Some(self.input_to_testcase(input, fitness)?)) + } else { + self.discard_input(&input)?; + Ok(None) + } + } + + /// Adds this input to the corpus, if it's intersting + pub fn add_if_interesting( + &mut self, + corpus: &mut C, + input: I, + fitness: u32, + ) -> Result, AflError> { + if fitness > 0 { + let testcase = self.input_to_testcase(input, fitness)?; + Ok(Some(corpus.add(testcase))) + } else { + self.discard_input(&input)?; + Ok(None) + } + } + + pub fn generate_initial_inputs( + &mut self, + rand: &mut R, + corpus: &mut C, + generator: &mut G, + events: &mut EM, + num: usize, + ) -> Result<(), AflError> + where + G: Generator, + EM: EventManager, + { + for _ in 0..num { + let input = generator.generate(rand)?; + let fitness = self.evaluate_input(&input)?; + self.add_if_interesting(corpus, input, fitness)?; + events.fire(Event::LoadInitial { + sender_id: 0, + phantom: PhantomData, + })?; + } + events.process(self, corpus)?; + Ok(()) + } -impl StdState -where - C: Corpus, - E: Executor, - I: Input, - R: Rand, -{ pub fn new(executor: E) -> Self { Self { executions: 0, @@ -263,27 +215,38 @@ where } } -pub trait Engine +pub trait FuzzingEngine where - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, R: Rand, { - fn stages(&self) -> &[Box>]; + fn stages(&self) -> &[Box>]; - fn stages_mut(&mut self) -> &mut Vec>>; + fn stages_mut(&mut self) -> &mut Vec>>; - fn add_stage(&mut self, stage: Box>) { + fn add_stage(&mut self, stage: Box>) { 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 S, + state: &mut State, corpus: &mut C, events: &mut EM, ) -> Result { @@ -309,7 +272,7 @@ where fn fuzz_loop( &mut self, rand: &mut R, - state: &mut S, + state: &mut State, corpus: &mut C, events: &mut EM, ) -> Result<(), AflError> { @@ -329,41 +292,38 @@ where } } -pub struct StdEngine +pub struct StdFuzzingEngine where - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, R: Rand, { - stages: Vec>>, + stages: Vec>>, phantom: PhantomData, } -impl Engine for StdEngine +impl FuzzingEngine for StdFuzzingEngine where - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, R: Rand, { - fn stages(&self) -> &[Box>] { + fn stages(&self) -> &[Box>] { &self.stages } - fn stages_mut(&mut self) -> &mut Vec>> { + fn stages_mut(&mut self) -> &mut Vec>> { &mut self.stages } } -impl StdEngine +impl StdFuzzingEngine where - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, diff --git a/afl/src/stages/mod.rs b/afl/src/stages/mod.rs index fe16267980..833edeabcd 100644 --- a/afl/src/stages/mod.rs +++ b/afl/src/stages/mod.rs @@ -9,10 +9,9 @@ use crate::inputs::Input; use crate::utils::Rand; use crate::AflError; -pub trait Stage +pub trait Stage where - S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -22,7 +21,7 @@ where fn perform( &mut self, rand: &mut R, - state: &mut S, + state: &mut State, corpus: &C, events: &mut EM, input: &I,