From 55c043ec73bd658bd8eb3d147ea9dfc54b5258bf Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 11 Dec 2020 17:08:50 +0100 Subject: [PATCH] doh --- afl/src/engines/mod.rs | 50 ++++++++------- afl/src/events/mod.rs | 117 ++++++++++++++++++++--------------- afl/src/feedbacks/mod.rs | 8 +-- afl/src/observers/mod.rs | 24 ++++--- afl/src/stages/mod.rs | 86 ++++++++++++++++++++++++- afl/src/stages/mutational.rs | 48 +++++++------- 6 files changed, 223 insertions(+), 110 deletions(-) diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index 2ad0cca4ae..23717cb7c3 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -194,7 +194,7 @@ where C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, - EM: EventManager, + EM: EventManager, { let mut added = 0; for _ in 0..num { @@ -234,7 +234,7 @@ where I: Input, { executor: E, - phantom: PhantomData, + phantom: PhantomData<(OT, I)>, } impl Engine @@ -263,24 +263,25 @@ where } } -pub trait Fuzzer +pub trait Fuzzer where - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, 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 fuzz_one( + fn fuzz_one( &mut self, rand: &mut R, state: &mut State, @@ -288,8 +289,6 @@ where engine: &mut Engine, manager: &mut EM, ) -> Result - where - FT: FeedbacksTuple { let (_, idx) = corpus.next(rand)?; @@ -301,15 +300,15 @@ where Ok(idx) } - fn fuzz_loop( + fn fuzz_loop( &mut self, rand: &mut R, state: &mut State, corpus: &mut C, engine: &mut Engine, manager: &mut EM, - ) -> Result<(), AflError> where - FT: FeedbacksTuple{ + ) -> Result<(), AflError> + { let mut last = current_milliseconds(); loop { self.fuzz_one(rand, state, corpus, engine, manager)?; @@ -325,41 +324,44 @@ where } } -pub struct StdFuzzer +pub struct StdFuzzer where - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, C: Corpus, I: Input, R: Rand, { - stages: Vec>>, + stages: Vec>>, } -impl Fuzzer for StdFuzzer +impl Fuzzer for StdFuzzer where - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, 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 StdFuzzer +impl StdFuzzer where - EM: EventManager, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, C: Corpus, I: Input, R: Rand, @@ -403,8 +405,8 @@ mod tests { let testcase = Testcase::new(vec![0; 4]).into(); corpus.add(testcase); - let executor = InMemoryExecutor::::new(harness, tuple_list!()); - let mut state = State::new(); + let executor = InMemoryExecutor::new(harness, tuple_list!()); + let mut state = State::::new(); let mut events_manager = LoggerEventManager::new(stderr()); let mut engine = Engine::new(executor); diff --git a/afl/src/events/mod.rs b/afl/src/events/mod.rs index 3c1752023a..ac1c5ccc5a 100644 --- a/afl/src/events/mod.rs +++ b/afl/src/events/mod.rs @@ -16,11 +16,13 @@ use std::io::Write; use crate::engines::State; use crate::executors::Executor; +use crate::observers::ObserversTuple; +use crate::feedbacks::FeedbacksTuple; use crate::inputs::Input; -use crate::serde_anymap::{Ptr, PtrMut}; +use crate::serde_anymap::{SerdeAny, Ptr, PtrMut}; use crate::utils::Rand; use crate::AflError; -use crate::{corpus::Corpus, serde_anymap::SerdeAny}; +use crate::corpus::Corpus; /// Indicate if an event worked or not pub enum BrokerEventResult { @@ -33,7 +35,7 @@ pub enum BrokerEventResult { pub trait ShowStats {} /// A custom event, for own messages, with own handler. -pub trait CustomEvent: SerdeAny + Serialize +pub trait CustomEvent: SerdeAny + Serialize where I: Input, { @@ -48,9 +50,10 @@ where /// Events sent around in the library #[derive(Serialize, Deserialize)] #[serde(bound = "I: serde::de::DeserializeOwned")] -pub enum Event<'a, I> +pub enum Event<'a, I, OT> where I: Input, + OT: ObserversTuple { LoadInitial { sender_id: u64, @@ -59,7 +62,7 @@ where NewTestcase { sender_id: u64, input: Ptr<'a, I>, - observers: PtrMut<'a, crate::observers::observer_serde::NamedSerdeAnyMap>, + observers: PtrMut<'a, OT>, corpus_count: usize, }, UpdateStats { @@ -90,14 +93,15 @@ where Custom { sender_id: u64, // TODO: Allow custom events - // custom_event: Box>, + // custom_event: Box>, }, } -impl<'a, I> Event<'a, I> +impl<'a, I, OT> Event<'a, I, OT> where I: Input, - //CE: CustomEvent, + OT: ObserversTuple + //CE: CustomEvent, { pub fn name(&self) -> &str { match self { @@ -159,29 +163,31 @@ where } } -pub trait EventManager +pub trait EventManager where C: Corpus, E: Executor, + OT: ObserversTuple, + FT: FeedbacksTuple, I: Input, R: Rand, { /// Fire an Event - fn fire<'a>(&mut self, event: Event<'a, I>) -> Result<(), AflError>; + fn fire<'a>(&mut self, event: Event<'a, I, OT>) -> Result<(), AflError>; /// Lookup for incoming events and process them. /// Return the number of processes events or an error - fn process(&mut self, state: &mut State, corpus: &mut C) -> Result; + fn process(&mut self, state: &mut State, corpus: &mut C) -> Result; #[inline] - fn on_recv(&self, _state: &mut State, _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(()) } // TODO the broker has a state? do we need to pass state and corpus? - fn handle_in_broker(&mut self, event: &Event) -> Result { + fn handle_in_broker(&mut self, event: &Event) -> Result { match event { Event::LoadInitial { sender_id: _, @@ -238,8 +244,8 @@ where fn handle_in_client( &mut self, - event: Event, - _state: &mut State, + event: Event, + _state: &mut State, _corpus: &mut C, ) -> Result<(), AflError> { match event { @@ -263,7 +269,7 @@ where } /*TODO - fn on_recv(&self, state: &mut State, _corpus: &mut C) -> Result<(), AflError> { + fn on_recv(&self, state: &mut State, _corpus: &mut C) -> Result<(), AflError> { println!( "#{}\t exec/s: {}", state.executions(), @@ -275,10 +281,16 @@ where */ #[cfg(feature = "std")] -pub struct LoggerEventManager +pub struct LoggerEventManager where + C: Corpus, + E: Executor, + OT: ObserversTuple, + FT: FeedbacksTuple, + I: Input, + R: Rand, W: Write, - //CE: CustomEvent, + //CE: CustomEvent, { writer: W, count: usize, @@ -288,21 +300,23 @@ where execs_over_sec: u64, corpus_count: usize, - phantom: PhantomData<(C, E, I, R)>, + phantom: PhantomData<(C, E, OT, FT, I, R)>, } #[cfg(feature = "std")] -impl EventManager for LoggerEventManager +impl EventManager for LoggerEventManager where C: Corpus, E: Executor, + OT: ObserversTuple, + FT: FeedbacksTuple, I: Input, R: Rand, W: Write, - //CE: CustomEvent, + //CE: CustomEvent, { #[inline] - fn fire<'a>(&mut self, event: Event<'a, I>) -> Result<(), AflError> { + fn fire<'a>(&mut self, event: Event<'a, I, OT>) -> Result<(), AflError> { match self.handle_in_broker(&event)? { BrokerEventResult::Forward => (), //self.handle_in_client(event, state, corpus)?, // Ignore broker-only events @@ -311,13 +325,13 @@ where Ok(()) } - fn process(&mut self, _state: &mut State, _corpus: &mut C) -> Result { + fn process(&mut self, _state: &mut State, _corpus: &mut C) -> Result { let c = self.count; self.count = 0; Ok(c) } - fn handle_in_broker(&mut self, event: &Event) -> Result { + fn handle_in_broker(&mut self, event: &Event) -> Result { match event { Event::NewTestcase { sender_id: _, @@ -377,11 +391,13 @@ where } #[cfg(feature = "std")] -impl LoggerEventManager +impl LoggerEventManager where C: Corpus, I: Input, E: Executor, + OT: ObserversTuple, + FT: FeedbacksTuple, R: Rand, W: Write, //TODO CE: CustomEvent, @@ -400,16 +416,18 @@ where /// Eventmanager for multi-processed application #[cfg(feature = "std")] -pub struct LlmpBrokerEventManager +pub struct LlmpBrokerEventManager where C: Corpus, I: Input, E: Executor, + OT: ObserversTuple, + FT: FeedbacksTuple, R: Rand, - //CE: CustomEvent, + //CE: CustomEvent, { llmp_broker: llmp::LlmpBroker, - phantom: PhantomData<(C, E, I, R)>, + phantom: PhantomData<(C, E, OT, FT, I, R)>, } #[cfg(feature = "std")] @@ -424,35 +442,39 @@ const _LLMP_TAG_EVENT_TO_BOTH: llmp::Tag = 0x2B0741; /// Eventmanager for multi-processed application #[cfg(feature = "std")] -pub struct LlmpClientEventManager +pub struct LlmpClientEventManager where C: Corpus, I: Input, E: Executor, + OT: ObserversTuple, + FT: FeedbacksTuple, R: Rand, - //CE: CustomEvent, + //CE: CustomEvent, { _llmp_client: llmp::LlmpClient, - phantom: PhantomData<(C, E, I, R)>, + phantom: PhantomData<(C, E, OT, FT, I, R)>, } #[cfg(feature = "std")] -impl EventManager for LlmpBrokerEventManager +impl EventManager for LlmpBrokerEventManager where C: Corpus, E: Executor, + OT: ObserversTuple, + FT: FeedbacksTuple, I: Input, R: Rand, { /// Fire an Event - fn fire<'a>(&mut self, event: Event<'a, I>) -> Result<(), AflError> { + fn fire<'a>(&mut self, event: Event<'a, I, OT>) -> Result<(), AflError> { let serialized = postcard::to_allocvec(&event)?; self.llmp_broker .send_buf(LLMP_TAG_EVENT_TO_CLIENT, &serialized)?; Ok(()) } - fn process(&mut self, _state: &mut State, _corpus: &mut C) -> Result { + fn process(&mut self, _state: &mut State, _corpus: &mut C) -> Result { // TODO: iterators /* let mut handled = vec![]; @@ -481,13 +503,13 @@ where Ok(0) } - fn on_recv(&self, _state: &mut State, _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(()) } - fn handle_in_broker(&mut self, event: &Event) -> Result { + fn handle_in_broker(&mut self, event: &Event) -> Result { match event { Event::LoadInitial { sender_id: _, @@ -542,8 +564,8 @@ where fn handle_in_client( &mut self, - event: Event, - /*client: &dyn EventManager,*/ _state: &mut State, + event: Event, + _state: &mut State, _corpus: &mut C, ) -> Result<(), AflError> { match event { @@ -572,17 +594,17 @@ mod tests { use crate::events::Event; use crate::inputs::bytes::BytesInput; - use crate::observers::observer_serde::NamedSerdeAnyMap; - use crate::observers::{Observer, StdMapObserver}; + use crate::observers::{Observer, StdMapObserver, ObserversTuple}; + use crate::tuples::{MatchNameAndType, Named, tuple_list, tuple_list_type}; use crate::serde_anymap::{Ptr, PtrMut}; static mut MAP: [u32; 4] = [0; 4]; #[test] fn test_event_serde() { - let mut map = NamedSerdeAnyMap::new(); + let obv = StdMapObserver::new("test", unsafe { &mut MAP }); - map.insert(Box::new(obv), &"key".to_string()); + let mut map = tuple_list!(obv); let i = BytesInput::new(vec![0]); let e = Event::NewTestcase { @@ -594,19 +616,16 @@ mod tests { let j = serde_json::to_string(&e).unwrap(); - let d: Event = serde_json::from_str(&j).unwrap(); + let d: Event)> = serde_json::from_str(&j).unwrap(); match d { Event::NewTestcase { sender_id: _, input: _, - observers: obs, + observers, corpus_count: _, } => { - let o = obs - .as_ref() - .get::>(&"key".to_string()) - .unwrap(); - assert_eq!("test".to_string(), *o.name()); + let o = observers.as_ref().match_name_type::>("test").unwrap(); + assert_eq!("test", o.name()); } _ => panic!("mistmatch".to_string()), }; diff --git a/afl/src/feedbacks/mod.rs b/afl/src/feedbacks/mod.rs index 5783469891..9897d71459 100644 --- a/afl/src/feedbacks/mod.rs +++ b/afl/src/feedbacks/mod.rs @@ -19,7 +19,7 @@ pub type MinMapFeedback = MapFeedback, O>; /// Feedbacks evaluate the observers. /// Basically, they reduce the information provided by an observer to a value, /// indicating the "interestingness" of the last run. -pub trait Feedback: Named +pub trait Feedback: Named + 'static where I: Input, { @@ -39,7 +39,7 @@ where } } -pub trait FeedbacksTuple: TupleList + MatchType + MatchNameAndType +pub trait FeedbacksTuple: MatchType + MatchNameAndType where I: Input { @@ -61,7 +61,7 @@ I: Input{ impl FeedbacksTuple for (Head, Tail) where Head: Feedback, - Tail: FeedbacksTuple, + Tail: FeedbacksTuple + TupleList, I: Input { fn is_interesting_all(&mut self, input: &I, observers: &OT) -> Result { @@ -90,7 +90,7 @@ impl FeedbacksTuple for (Head, Tail) where } /// A Reducer function is used to aggregate values for the novelty search -pub trait Reducer +pub trait Reducer: 'static where T: Integer + Copy + 'static, { diff --git a/afl/src/observers/mod.rs b/afl/src/observers/mod.rs index 73d77d231c..b9326fb8a4 100644 --- a/afl/src/observers/mod.rs +++ b/afl/src/observers/mod.rs @@ -1,8 +1,5 @@ extern crate num; -use alloc::boxed::Box; -use alloc::string::String; -use core::any::Any; use serde::{Deserialize, Serialize}; use crate::serde_anymap::ArrayMut; @@ -26,21 +23,23 @@ pub trait Observer: Named + 'static { } } -pub trait ObserversTuple: TupleList + MatchNameAndType + MatchType + serde::Serialize + serde::de::DeserializeOwned { +pub trait ObserversTuple: MatchNameAndType + MatchType + serde::Serialize + serde::de::DeserializeOwned { fn reset_all(&mut self) -> Result<(), AflError>; fn post_exec_all(&mut self) -> Result<(), AflError>; - fn for_each(&self, f: fn(&dyn Observer)); + //fn for_each(&self, f: fn(&dyn Observer)); + //fn for_each_mut(&mut self, f: fn(&mut dyn Observer)); } impl ObserversTuple for () { fn reset_all(&mut self) -> Result<(), AflError> { Ok(()) } fn post_exec_all(&mut self) -> Result<(), AflError> { Ok(()) } - fn for_each(&self, f: fn(&dyn Observer)) { } + //fn for_each(&self, f: fn(&dyn Observer)) { } + //fn for_each_mut(&mut self, f: fn(&mut dyn Observer)) { } } impl ObserversTuple for (Head, Tail) where - Head: Observer, - Tail: ObserversTuple, + Head: Observer + serde::Serialize + serde::de::DeserializeOwned, + Tail: ObserversTuple + TupleList, { fn reset_all(&mut self) -> Result<(), AflError> { self.0.reset()?; @@ -52,10 +51,15 @@ impl ObserversTuple for (Head, Tail) where self.1.post_exec_all() } - fn for_each(&self, f: fn(&dyn Observer)) { - f(self.0); + /*fn for_each(&self, f: fn(&dyn Observer)) { + f(&self.0); self.1.for_each(f) } + + fn for_each_mut(&mut self, f: fn(&mut dyn Observer)) { + f(&mut self.0); + self.1.for_each_mut(f) + }*/ } /// A MapObserver observes the static map, as oftentimes used for afl-like coverage information diff --git a/afl/src/stages/mod.rs b/afl/src/stages/mod.rs index a1b9829ba3..efe81d5e2d 100644 --- a/afl/src/stages/mod.rs +++ b/afl/src/stages/mod.rs @@ -7,15 +7,16 @@ use crate::events::EventManager; use crate::executors::{HasObservers, Executor}; use crate::observers::ObserversTuple; use crate::feedbacks::FeedbacksTuple; +use crate::tuples::{TupleList, MatchType}; use crate::inputs::Input; 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, + EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, FT: FeedbacksTuple, @@ -34,3 +35,84 @@ where corpus_idx: usize, ) -> Result<(), AflError>; } + +pub trait StagesTuple +where + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, + FT: FeedbacksTuple, + 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, + ) -> Result<(), AflError>; + fn for_each(&self, f: fn(&dyn Stage)); + fn for_each_mut(&mut self, f: fn(&mut dyn Stage)); +} + +impl StagesTuple for () +where + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, + FT: FeedbacksTuple, + 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, + ) -> Result<(), AflError> { Ok(()) } + fn for_each(&self, f: fn(&dyn Stage)) { } + fn for_each_mut(&mut self, f: fn(&mut dyn Stage)) { } +} + +impl StagesTuple for (Head, Tail) where + Head: Stage, + Tail: StagesTuple + TupleList, + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, + FT: FeedbacksTuple, + 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, + ) -> Result<(), AflError> { + self.0.perform(rand, state, corpus, engine, manager, corpus_idx)?; + self.1.perform_all(rand, state, corpus, engine, manager, corpus_idx) + } + + 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)) { + f(&mut self.0); + self.1.for_each_mut(f) + } +} \ No newline at end of file diff --git a/afl/src/stages/mutational.rs b/afl/src/stages/mutational.rs index 7f3ea6f203..2f80e59aea 100644 --- a/afl/src/stages/mutational.rs +++ b/afl/src/stages/mutational.rs @@ -1,8 +1,9 @@ use core::marker::PhantomData; use crate::events::EventManager; -use crate::executors::Executor; +use crate::executors::{HasObservers, Executor}; use crate::observers::ObserversTuple; +use crate::feedbacks::FeedbacksTuple; use crate::inputs::Input; use crate::mutators::Mutator; use crate::stages::Corpus; @@ -18,12 +19,13 @@ 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, + EM: EventManager, + E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, C: Corpus, I: Input, R: Rand, @@ -45,9 +47,9 @@ where fn perform_mutational( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, corpus_idx: usize, ) -> Result<(), AflError> { @@ -84,26 +86,28 @@ where } /// The default mutational stage -pub struct StdMutationalStage +pub struct StdMutationalStage where M: Mutator, - EM: EventManager, - E: Executor, + EM: EventManager, + E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, C: Corpus, I: Input, R: Rand, { mutator: M, - phantom: PhantomData<(EM, E, OT, C, I, R)>, + phantom: PhantomData<(EM, E, OT, FT, C, I, R)>, } -impl MutationalStage for StdMutationalStage +impl MutationalStage for StdMutationalStage where M: Mutator, - EM: EventManager, - E: Executor, + EM: EventManager, + E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, C: Corpus, I: Input, R: Rand, @@ -121,12 +125,13 @@ where } } -impl Stage for StdMutationalStage +impl Stage for StdMutationalStage where M: Mutator, - EM: EventManager, - E: Executor, + EM: EventManager, + E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, C: Corpus, I: Input, R: Rand, @@ -135,9 +140,9 @@ where fn perform( &mut self, rand: &mut R, - state: &mut State, + state: &mut State, corpus: &mut C, - engine: &mut Engine, + engine: &mut Engine, manager: &mut EM, corpus_idx: usize, ) -> Result<(), AflError> { @@ -145,12 +150,13 @@ where } } -impl StdMutationalStage +impl StdMutationalStage where M: Mutator, - EM: EventManager, - E: Executor, + EM: EventManager, + E: Executor + HasObservers, OT: ObserversTuple, + FT: FeedbacksTuple, C: Corpus, I: Input, R: Rand,