From 299634ccce5f3083ee86b38c1e828bfd5bab7f9e Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 11 Dec 2020 21:57:29 +0100 Subject: [PATCH] additional executors --- afl/src/engines/mod.rs | 75 ++++++++++++++++++++++++----------- afl/src/events/mod.rs | 2 +- afl/src/executors/inmemory.rs | 19 +++++++-- afl/src/executors/mod.rs | 36 ++++++++++++++++- afl/src/feedbacks/mod.rs | 10 ++--- afl/src/stages/mod.rs | 51 +++++++++++++----------- afl/src/stages/mutational.rs | 28 ++++++++----- afl/src/tuples.rs | 8 ++-- 8 files changed, 156 insertions(+), 73 deletions(-) diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index d74811fe97..26c8874345 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -7,12 +7,13 @@ use hashbrown::HashMap; use crate::corpus::{Corpus, Testcase}; use crate::events::{Event, EventManager}; -use crate::executors::{Executor, HasObservers}; +use crate::executors::{Executor, ExecutorsTuple, HasObservers}; use crate::feedbacks::FeedbacksTuple; use crate::generators::Generator; use crate::inputs::Input; use crate::observers::ObserversTuple; use crate::stages::StagesTuple; +use crate::tuples::{tuple_list, tuple_list_type}; use crate::utils::{current_milliseconds, Rand}; use crate::AflError; @@ -179,12 +180,12 @@ where } } - pub fn generate_initial_inputs( + pub fn generate_initial_inputs( &mut self, rand: &mut R, corpus: &mut C, generator: &mut G, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, num: usize, ) -> Result<(), AflError> @@ -193,6 +194,7 @@ where C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, + ET: ExecutorsTuple, EM: EventManager, { let mut added = 0; @@ -226,49 +228,71 @@ where } } -pub struct Engine +pub struct Engine where E: Executor + HasObservers, OT: ObserversTuple, + ET: ExecutorsTuple, I: Input, { - executor: E, + main_executor: E, + additional_executors: ET, phantom: PhantomData<(OT, I)>, } -impl Engine +impl Engine where E: Executor + HasObservers, OT: ObserversTuple, + ET: ExecutorsTuple, I: Input, { /// Return the executor pub fn executor(&self) -> &E { - &self.executor + &self.main_executor } /// Return the executor (mutable) pub fn executor_mut(&mut self) -> &mut E { - &mut self.executor + &mut self.main_executor } - // TODO additional executors, Vec>> + pub fn additional_executors(&self) -> &ET { + &self.additional_executors + } - pub fn new(executor: E) -> Self { + pub fn additional_executors_mut(&mut self) -> &mut ET { + &mut self.additional_executors + } + + pub fn with_executors(main_executor: E, additional_executors: ET) -> Self { Self { - executor: executor, + main_executor: main_executor, + additional_executors: additional_executors, phantom: PhantomData, } } } -pub trait Fuzzer +impl Engine where - ST: StagesTuple, + E: Executor + HasObservers, + OT: ObserversTuple, + I: Input, +{ + pub fn new(main_executor: E) -> Self { + Self::with_executors(main_executor, tuple_list!()) + } +} + +pub trait Fuzzer +where + ST: StagesTuple, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -282,7 +306,7 @@ where rand: &mut R, state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, ) -> Result { let (_, idx) = corpus.next(rand)?; @@ -299,7 +323,7 @@ where rand: &mut R, state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, ) -> Result<(), AflError> { let mut last = current_milliseconds(); @@ -317,29 +341,31 @@ where } } -pub struct StdFuzzer +pub struct StdFuzzer where - ST: StagesTuple, + ST: StagesTuple, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, { stages: ST, - phantom: PhantomData<(EM, E, OT, FT, C, I, R)>, + phantom: PhantomData<(EM, E, OT, FT, ET, C, I, R)>, } -impl Fuzzer - for StdFuzzer +impl Fuzzer + for StdFuzzer where - ST: StagesTuple, + ST: StagesTuple, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -353,13 +379,14 @@ where } } -impl StdFuzzer +impl StdFuzzer where - ST: StagesTuple, + ST: StagesTuple, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -404,7 +431,7 @@ mod tests { let testcase = Testcase::new(vec![0; 4]).into(); corpus.add(testcase); - let executor = InMemoryExecutor::::new(harness, tuple_list!()); + let executor = InMemoryExecutor::::new("main", harness, tuple_list!()); let mut state = State::new(tuple_list!()); let mut events_manager = LoggerEventManager::new(stderr()); diff --git a/afl/src/events/mod.rs b/afl/src/events/mod.rs index a65b6a5347..eef412b909 100644 --- a/afl/src/events/mod.rs +++ b/afl/src/events/mod.rs @@ -603,7 +603,7 @@ mod tests { use crate::events::Event; use crate::inputs::bytes::BytesInput; - use crate::observers::{Observer, ObserversTuple, StdMapObserver}; + use crate::observers::StdMapObserver; use crate::serde_anymap::{Ptr, PtrMut}; use crate::tuples::{tuple_list, tuple_list_type, MatchNameAndType, Named}; diff --git a/afl/src/executors/inmemory.rs b/afl/src/executors/inmemory.rs index eb9989b5dd..bb47c01824 100644 --- a/afl/src/executors/inmemory.rs +++ b/afl/src/executors/inmemory.rs @@ -4,6 +4,7 @@ use core::ptr; use crate::executors::{Executor, ExitKind, HasObservers}; use crate::inputs::{HasTargetBytes, Input}; use crate::observers::ObserversTuple; +use crate::tuples::Named; use crate::AflError; /// The (unsafe) pointer to the current inmem executor, for the current run. @@ -21,6 +22,7 @@ where { harness: HarnessFunction, observers: OT, + name: &'static str, } impl Executor for InMemoryExecutor @@ -42,6 +44,16 @@ where } } +impl Named for InMemoryExecutor +where + I: Input + HasTargetBytes, + OT: ObserversTuple, +{ + fn name(&self) -> &str { + self.name + } +} + impl HasObservers for InMemoryExecutor where I: Input + HasTargetBytes, @@ -63,7 +75,7 @@ where I: Input + HasTargetBytes, OT: ObserversTuple, { - pub fn new(harness_fn: HarnessFunction, observers: OT) -> Self { + pub fn new(name: &'static str, harness_fn: HarnessFunction, observers: OT) -> Self { #[cfg(feature = "std")] unsafe { os_signals::setup_crash_handlers::(); @@ -71,6 +83,7 @@ where Self { harness: harness_fn, observers: observers, + name: name, } } } @@ -178,7 +191,7 @@ mod tests { use crate::executors::inmemory::InMemoryExecutor; use crate::executors::{Executor, ExitKind}; use crate::inputs::{HasTargetBytes, Input, TargetBytes}; - use crate::tuples::{tuple_list, tuple_list_type}; + use crate::tuples::tuple_list; use serde::{Deserialize, Serialize}; @@ -204,7 +217,7 @@ mod tests { #[test] fn test_inmem_exec() { - let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop, tuple_list!()); + let mut in_mem_executor = InMemoryExecutor::new("main", test_harness_fn_nop, tuple_list!()); let mut input = NopInput {}; assert!(in_mem_executor.run_target(&mut input).is_ok()); } diff --git a/afl/src/executors/mod.rs b/afl/src/executors/mod.rs index ea209b8dd0..e519424d73 100644 --- a/afl/src/executors/mod.rs +++ b/afl/src/executors/mod.rs @@ -2,6 +2,7 @@ pub mod inmemory; use crate::inputs::Input; use crate::observers::ObserversTuple; +use crate::tuples::{MatchNameAndType, MatchType, Named, TupleList}; use crate::AflError; /// How an execution finished. @@ -36,10 +37,43 @@ where } /// An executor takes the given inputs, and runs the harness/target. -pub trait Executor +pub trait Executor: Named where I: Input, { /// Instruct the target about the input and run fn run_target(&mut self, input: &I) -> Result; } + +pub trait ExecutorsTuple: MatchType + MatchNameAndType +where + I: Input, +{ + fn for_each(&self, f: fn(&dyn Executor)); + fn for_each_mut(&mut self, f: fn(&mut dyn Executor)); +} + +impl ExecutorsTuple for () +where + I: Input, +{ + fn for_each(&self, _f: fn(&dyn Executor)) {} + fn for_each_mut(&mut self, _f: fn(&mut dyn Executor)) {} +} + +impl ExecutorsTuple for (Head, Tail) +where + Head: Executor + 'static, + Tail: ExecutorsTuple + TupleList, + I: Input, +{ + fn for_each(&self, f: fn(&dyn Executor)) { + f(&self.0); + self.1.for_each(f) + } + + fn for_each_mut(&mut self, f: fn(&mut dyn Executor)) { + f(&mut self.0); + self.1.for_each_mut(f) + } +} diff --git a/afl/src/feedbacks/mod.rs b/afl/src/feedbacks/mod.rs index 4356e53b03..05808efd79 100644 --- a/afl/src/feedbacks/mod.rs +++ b/afl/src/feedbacks/mod.rs @@ -1,5 +1,3 @@ -use alloc::string::String; -use alloc::string::ToString; use alloc::vec::Vec; use core::marker::PhantomData; use num::Integer; @@ -64,15 +62,15 @@ where { fn is_interesting_all( &mut self, - input: &I, - observers: &OT, + _input: &I, + _observers: &OT, ) -> Result { Ok(0) } - fn append_metadata_all(&mut self, testcase: &mut Testcase) -> Result<(), AflError> { + fn append_metadata_all(&mut self, _testcase: &mut Testcase) -> Result<(), AflError> { Ok(()) } - fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError> { + fn discard_metadata_all(&mut self, _input: &I) -> Result<(), AflError> { Ok(()) } //fn for_each(&self, f: fn(&dyn Feedback)) {} diff --git a/afl/src/stages/mod.rs b/afl/src/stages/mod.rs index f63dc2b855..c47ab9cd82 100644 --- a/afl/src/stages/mod.rs +++ b/afl/src/stages/mod.rs @@ -4,22 +4,23 @@ pub use mutational::StdMutationalStage; use crate::corpus::Corpus; use crate::engines::{Engine, State}; use crate::events::EventManager; -use crate::executors::{Executor, HasObservers}; +use crate::executors::{Executor, ExecutorsTuple, HasObservers}; use crate::feedbacks::FeedbacksTuple; use crate::inputs::Input; use crate::observers::ObserversTuple; -use crate::tuples::{MatchType, TupleList}; +use crate::tuples::TupleList; use crate::utils::Rand; use crate::AflError; /// A stage is one step in the fuzzing process. /// Multiple stages will be scheduled one by one for each input. -pub trait Stage +pub trait Stage where EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -30,18 +31,19 @@ where rand: &mut R, state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, corpus_idx: usize, ) -> Result<(), AflError>; } -pub trait StagesTuple +pub trait StagesTuple where EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -51,47 +53,50 @@ where rand: &mut R, state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, corpus_idx: usize, ) -> Result<(), AflError>; - fn for_each(&self, f: fn(&dyn Stage)); - fn for_each_mut(&mut self, f: fn(&mut dyn Stage)); + fn for_each(&self, f: fn(&dyn Stage)); + fn for_each_mut(&mut self, f: fn(&mut dyn Stage)); } -impl StagesTuple for () +impl StagesTuple for () where EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, { fn perform_all( &mut self, - rand: &mut R, - state: &mut State, - corpus: &mut C, - engine: &mut Engine, - manager: &mut EM, - corpus_idx: usize, + _rand: &mut R, + _state: &mut State, + _corpus: &mut C, + _engine: &mut Engine, + _manager: &mut EM, + _corpus_idx: usize, ) -> Result<(), AflError> { Ok(()) } - fn for_each(&self, f: fn(&dyn Stage)) {} - fn for_each_mut(&mut self, f: fn(&mut dyn Stage)) {} + fn for_each(&self, _f: fn(&dyn Stage)) {} + fn for_each_mut(&mut self, _f: fn(&mut dyn Stage)) {} } -impl StagesTuple for (Head, Tail) +impl StagesTuple + for (Head, Tail) where - Head: Stage, - Tail: StagesTuple + TupleList, + Head: Stage, + Tail: StagesTuple + TupleList, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -101,7 +106,7 @@ where rand: &mut R, state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, corpus_idx: usize, ) -> Result<(), AflError> { @@ -111,12 +116,12 @@ where .perform_all(rand, state, corpus, engine, manager, corpus_idx) } - fn for_each(&self, f: fn(&dyn Stage)) { + fn for_each(&self, f: fn(&dyn Stage)) { f(&self.0); self.1.for_each(f) } - fn for_each_mut(&mut self, f: fn(&mut dyn Stage)) { + fn for_each_mut(&mut self, f: fn(&mut dyn Stage)) { f(&mut self.0); self.1.for_each_mut(f) } diff --git a/afl/src/stages/mutational.rs b/afl/src/stages/mutational.rs index 804326e020..5fc0e1ee3c 100644 --- a/afl/src/stages/mutational.rs +++ b/afl/src/stages/mutational.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; use crate::events::EventManager; -use crate::executors::{Executor, HasObservers}; +use crate::executors::{Executor, ExecutorsTuple, HasObservers}; use crate::feedbacks::FeedbacksTuple; use crate::inputs::Input; use crate::mutators::Mutator; @@ -19,13 +19,15 @@ use crate::serde_anymap::{Ptr, PtrMut}; /// A Mutational stage is the stage in a fuzzing run that mutates inputs. /// Mutational stages will usually have a range of mutations that are /// being applied to the input one by one, between executions. -pub trait MutationalStage: Stage +pub trait MutationalStage: + Stage where M: Mutator, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -49,7 +51,7 @@ where rand: &mut R, state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, corpus_idx: usize, ) -> Result<(), AflError> { @@ -86,29 +88,31 @@ where } /// The default mutational stage -pub struct StdMutationalStage +pub struct StdMutationalStage where M: Mutator, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, { mutator: M, - phantom: PhantomData<(EM, E, OT, FT, C, I, R)>, + phantom: PhantomData<(EM, E, OT, FT, ET, C, I, R)>, } -impl MutationalStage - for StdMutationalStage +impl MutationalStage + for StdMutationalStage where M: Mutator, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -126,14 +130,15 @@ where } } -impl Stage - for StdMutationalStage +impl Stage + for StdMutationalStage where M: Mutator, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, @@ -144,7 +149,7 @@ where rand: &mut R, state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, corpus_idx: usize, ) -> Result<(), AflError> { @@ -152,13 +157,14 @@ where } } -impl StdMutationalStage +impl StdMutationalStage where M: Mutator, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, + ET: ExecutorsTuple, C: Corpus, I: Input, R: Rand, diff --git a/afl/src/tuples.rs b/afl/src/tuples.rs index d7209b8bab..4fae9ddfec 100644 --- a/afl/src/tuples.rs +++ b/afl/src/tuples.rs @@ -65,10 +65,10 @@ pub trait MatchType { } impl MatchType for () { - fn match_type(&self, f: fn(t: &T)) { + fn match_type(&self, _f: fn(t: &T)) { () } - fn match_type_mut(&mut self, f: fn(t: &mut T)) { + fn match_type_mut(&mut self, _f: fn(t: &mut T)) { () } } @@ -103,10 +103,10 @@ pub trait MatchNameAndType { } impl MatchNameAndType for () { - fn match_name_type(&self, name: &'static str) -> Option<&T> { + fn match_name_type(&self, _name: &'static str) -> Option<&T> { None } - fn match_name_type_mut(&mut self, name: &'static str) -> Option<&mut T> { + fn match_name_type_mut(&mut self, _name: &'static str) -> Option<&mut T> { None } }