diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index 23717cb7c3..d74811fe97 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -1,19 +1,18 @@ //! The engine is the core piece of every good fuzzer use alloc::boxed::Box; -use alloc::vec::Vec; use core::fmt::Debug; use core::marker::PhantomData; use hashbrown::HashMap; use crate::corpus::{Corpus, Testcase}; use crate::events::{Event, EventManager}; -use crate::executors::{HasObservers, Executor}; -use crate::feedbacks::{FeedbacksTuple}; -use crate::observers::ObserversTuple; +use crate::executors::{Executor, HasObservers}; +use crate::feedbacks::FeedbacksTuple; use crate::generators::Generator; use crate::inputs::Input; -use crate::stages::Stage; +use crate::observers::ObserversTuple; +use crate::stages::StagesTuple; use crate::utils::{current_milliseconds, Rand}; use crate::AflError; @@ -27,7 +26,7 @@ pub struct State where I: Input, R: Rand, - FT: FeedbacksTuple + FT: FeedbacksTuple, { /// How many times the executor ran the harness/target executions: usize, @@ -37,14 +36,14 @@ where metadatas: HashMap<&'static str, Box>, // additional_corpuses: HashMap<&'static str, Box>, feedbacks: FT, - phantom: PhantomData, + phantom: PhantomData<(I, R)>, } impl State where I: Input, R: Rand, - FT: FeedbacksTuple + FT: FeedbacksTuple, { /// Get executions #[inline] @@ -117,7 +116,7 @@ where pub fn evaluate_input(&mut self, input: &I, executor: &mut E) -> Result where E: Executor + HasObservers, - OT: ObserversTuple + OT: ObserversTuple, { executor.reset_observers()?; executor.run_target(&input)?; @@ -216,12 +215,12 @@ where Ok(()) } - pub fn new() -> Self { + pub fn new(feedbacks: FT) -> Self { Self { executions: 0, start_time: current_milliseconds(), metadatas: HashMap::default(), - feedbacks: vec![], + feedbacks: feedbacks, phantom: PhantomData, } } @@ -263,8 +262,9 @@ where } } -pub trait Fuzzer +pub trait Fuzzer where + ST: StagesTuple, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, @@ -273,13 +273,9 @@ where I: Input, R: Rand, { - fn stages(&self) -> &[Box>]; + fn stages(&self) -> &ST; - fn stages_mut(&mut self) -> &mut Vec>>; - - fn add_stage(&mut self, stage: Box>) { - self.stages_mut().push(stage); - } + fn stages_mut(&mut self) -> &mut ST; fn fuzz_one( &mut self, @@ -288,13 +284,11 @@ where corpus: &mut C, engine: &mut Engine, manager: &mut EM, - ) -> Result - { + ) -> Result { let (_, idx) = corpus.next(rand)?; - for stage in self.stages_mut() { - stage.perform(rand, state, corpus, engine, manager, idx)?; - } + self.stages_mut() + .perform_all(rand, state, corpus, engine, manager, idx)?; manager.process(state, corpus)?; Ok(idx) @@ -307,8 +301,7 @@ where corpus: &mut C, engine: &mut Engine, manager: &mut EM, - ) -> Result<(), AflError> - { + ) -> Result<(), AflError> { let mut last = current_milliseconds(); loop { self.fuzz_one(rand, state, corpus, engine, manager)?; @@ -324,8 +317,9 @@ where } } -pub struct StdFuzzer +pub struct StdFuzzer where + ST: StagesTuple, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, @@ -334,11 +328,14 @@ where I: Input, R: Rand, { - stages: Vec>>, + stages: ST, + phantom: PhantomData<(EM, E, OT, FT, C, I, R)>, } -impl Fuzzer for StdFuzzer +impl Fuzzer + for StdFuzzer where + ST: StagesTuple, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, @@ -347,17 +344,18 @@ where I: Input, R: Rand, { - fn stages(&self) -> &[Box>] { + fn stages(&self) -> &ST { &self.stages } - fn stages_mut(&mut self) -> &mut Vec>> { + fn stages_mut(&mut self) -> &mut ST { &mut self.stages } } -impl StdFuzzer +impl StdFuzzer where + ST: StagesTuple, EM: EventManager, E: Executor + HasObservers, OT: ObserversTuple, @@ -366,8 +364,11 @@ where I: Input, R: Rand, { - pub fn new() -> Self { - Self { stages: vec![] } + pub fn new(stages: ST) -> Self { + Self { + stages: stages, + phantom: PhantomData, + } } } @@ -376,8 +377,6 @@ where #[cfg(test)] mod tests { - use alloc::boxed::Box; - #[cfg(feature = "std")] use std::io::stderr; @@ -405,18 +404,15 @@ 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(tuple_list!()); let mut events_manager = LoggerEventManager::new(stderr()); let mut engine = Engine::new(executor); let mut mutator = StdScheduledMutator::new(); mutator.add_mutation(mutation_bitflip); let stage = StdMutationalStage::new(mutator); - let mut fuzzer = StdFuzzer::new(); - fuzzer.add_stage(Box::new(stage)); - - // + let mut fuzzer = StdFuzzer::new(tuple_list!(stage)); for i in 0..1000 { fuzzer diff --git a/afl/src/events/mod.rs b/afl/src/events/mod.rs index ac1c5ccc5a..a65b6a5347 100644 --- a/afl/src/events/mod.rs +++ b/afl/src/events/mod.rs @@ -14,15 +14,15 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use std::io::Write; +use crate::corpus::Corpus; use crate::engines::State; use crate::executors::Executor; -use crate::observers::ObserversTuple; use crate::feedbacks::FeedbacksTuple; use crate::inputs::Input; -use crate::serde_anymap::{SerdeAny, Ptr, PtrMut}; +use crate::observers::ObserversTuple; +use crate::serde_anymap::{Ptr, PtrMut, SerdeAny}; use crate::utils::Rand; use crate::AflError; -use crate::corpus::Corpus; /// Indicate if an event worked or not pub enum BrokerEventResult { @@ -53,7 +53,7 @@ where pub enum Event<'a, I, OT> where I: Input, - OT: ObserversTuple + OT: ObserversTuple, { LoadInitial { sender_id: u64, @@ -100,8 +100,7 @@ where impl<'a, I, OT> Event<'a, I, OT> where I: Input, - OT: ObserversTuple - //CE: CustomEvent, + OT: ObserversTuple, //CE: CustomEvent, { pub fn name(&self) -> &str { match self { @@ -304,7 +303,8 @@ where } #[cfg(feature = "std")] -impl EventManager for LoggerEventManager +impl EventManager + for LoggerEventManager where C: Corpus, E: Executor, @@ -325,7 +325,11 @@ 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) @@ -457,7 +461,8 @@ where } #[cfg(feature = "std")] -impl EventManager for LlmpBrokerEventManager +impl EventManager + for LlmpBrokerEventManager where C: Corpus, E: Executor, @@ -474,7 +479,11 @@ where 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![]; @@ -594,15 +603,14 @@ mod tests { use crate::events::Event; use crate::inputs::bytes::BytesInput; - use crate::observers::{Observer, StdMapObserver, ObserversTuple}; - use crate::tuples::{MatchNameAndType, Named, tuple_list, tuple_list_type}; + use crate::observers::{Observer, ObserversTuple, StdMapObserver}; use crate::serde_anymap::{Ptr, PtrMut}; + use crate::tuples::{tuple_list, tuple_list_type, MatchNameAndType, Named}; static mut MAP: [u32; 4] = [0; 4]; #[test] fn test_event_serde() { - let obv = StdMapObserver::new("test", unsafe { &mut MAP }); let mut map = tuple_list!(obv); @@ -616,7 +624,8 @@ 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: _, @@ -624,7 +633,10 @@ mod tests { observers, corpus_count: _, } => { - let o = observers.as_ref().match_name_type::>("test").unwrap(); + let o = observers + .as_ref() + .match_name_type::>("test") + .unwrap(); assert_eq!("test", o.name()); } _ => panic!("mistmatch".to_string()), diff --git a/afl/src/executors/inmemory.rs b/afl/src/executors/inmemory.rs index 93f617a0b0..eb9989b5dd 100644 --- a/afl/src/executors/inmemory.rs +++ b/afl/src/executors/inmemory.rs @@ -1,9 +1,9 @@ use core::ffi::c_void; use core::ptr; -use crate::executors::{Executor, HasObservers, ExitKind}; +use crate::executors::{Executor, ExitKind, HasObservers}; use crate::inputs::{HasTargetBytes, Input}; -use crate::observers::{ObserversTuple}; +use crate::observers::ObserversTuple; use crate::AflError; /// The (unsafe) pointer to the current inmem executor, for the current run. @@ -17,7 +17,7 @@ type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; pub struct InMemoryExecutor where I: Input + HasTargetBytes, - OT: ObserversTuple + OT: ObserversTuple, { harness: HarnessFunction, observers: OT, @@ -26,7 +26,7 @@ where impl Executor for InMemoryExecutor where I: Input + HasTargetBytes, - OT: ObserversTuple + OT: ObserversTuple, { #[inline] fn run_target(&mut self, input: &I) -> Result { @@ -42,9 +42,11 @@ where } } -impl HasObservers for InMemoryExecutor where -I: Input + HasTargetBytes, -OT: ObserversTuple { +impl HasObservers for InMemoryExecutor +where + I: Input + HasTargetBytes, + OT: ObserversTuple, +{ #[inline] fn observers(&self) -> &OT { &self.observers @@ -59,7 +61,7 @@ OT: ObserversTuple { impl InMemoryExecutor where I: Input + HasTargetBytes, - OT: ObserversTuple + OT: ObserversTuple, { pub fn new(harness_fn: HarnessFunction, observers: OT) -> Self { #[cfg(feature = "std")] @@ -190,7 +192,7 @@ mod tests { } #[cfg(feature = "std")] - fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { + fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { println!("Fake exec with buf of len {}", buf.len()); ExitKind::Ok } diff --git a/afl/src/executors/mod.rs b/afl/src/executors/mod.rs index 2f0a28d890..ea209b8dd0 100644 --- a/afl/src/executors/mod.rs +++ b/afl/src/executors/mod.rs @@ -1,7 +1,7 @@ pub mod inmemory; use crate::inputs::Input; -use crate::observers::{ObserversTuple}; +use crate::observers::ObserversTuple; use crate::AflError; /// How an execution finished. @@ -12,7 +12,10 @@ pub enum ExitKind { Timeout, } -pub trait HasObservers where OT: ObserversTuple { +pub trait HasObservers +where + OT: ObserversTuple, +{ /// Get the linked observers fn observers(&self) -> &OT; diff --git a/afl/src/feedbacks/mod.rs b/afl/src/feedbacks/mod.rs index 9897d71459..4356e53b03 100644 --- a/afl/src/feedbacks/mod.rs +++ b/afl/src/feedbacks/mod.rs @@ -4,10 +4,10 @@ use alloc::vec::Vec; use core::marker::PhantomData; use num::Integer; -use crate::inputs::Input; -use crate::observers::{ObserversTuple, Observer, MapObserver}; use crate::corpus::Testcase; -use crate::tuples::{Named, TupleList, MatchNameAndType, MatchType}; +use crate::inputs::Input; +use crate::observers::{MapObserver, Observer, ObserversTuple}; +use crate::tuples::{MatchNameAndType, MatchType, Named, TupleList}; use crate::AflError; pub type MaxMapFeedback = MapFeedback, O>; @@ -24,7 +24,11 @@ where I: Input, { /// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55) - fn is_interesting(&mut self, input: &I, observers: &OT) -> Result; + fn is_interesting( + &mut self, + input: &I, + observers: &OT, + ) -> Result; /// Append to the testcase the generated metadata in case of a new corpus item #[inline] @@ -41,41 +45,63 @@ where pub trait FeedbacksTuple: MatchType + MatchNameAndType where - I: Input + I: Input, { - fn is_interesting_all(&mut self, input: &I, observers: &OT) -> Result; + fn is_interesting_all( + &mut self, + input: &I, + observers: &OT, + ) -> Result; fn append_metadata_all(&mut self, testcase: &mut Testcase) -> Result<(), AflError>; fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError>; //fn for_each(&self, f: fn(&dyn Feedback)); //fn for_each_mut(&mut self, f: fn(&mut dyn Feedback)); } -impl FeedbacksTuple for () where -I: Input{ - fn is_interesting_all(&mut self, input: &I, observers: &OT) -> Result { Ok(0) } - fn append_metadata_all(&mut self, testcase: &mut Testcase) -> Result<(), AflError> { Ok(())} - fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError> { Ok(())} +impl FeedbacksTuple for () +where + I: Input, +{ + fn is_interesting_all( + &mut self, + input: &I, + observers: &OT, + ) -> Result { + Ok(0) + } + fn append_metadata_all(&mut self, testcase: &mut Testcase) -> Result<(), AflError> { + Ok(()) + } + fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError> { + Ok(()) + } //fn for_each(&self, f: fn(&dyn Feedback)) {} //fn for_each_mut(&mut self, f: fn(&mut dyn Feedback)) {} } -impl FeedbacksTuple for (Head, Tail) where +impl FeedbacksTuple for (Head, Tail) +where Head: Feedback, Tail: FeedbacksTuple + TupleList, - I: Input + I: Input, { - fn is_interesting_all(&mut self, input: &I, observers: &OT) -> Result { - Ok(self.0.is_interesting(input, observers)? + self.1.is_interesting_all(input, observers)?) + fn is_interesting_all( + &mut self, + input: &I, + observers: &OT, + ) -> Result { + Ok(self.0.is_interesting(input, observers)? + + self.1.is_interesting_all(input, observers)?) } - fn append_metadata_all(&mut self, testcase: &mut Testcase) -> Result<(), AflError>{ + fn append_metadata_all(&mut self, testcase: &mut Testcase) -> Result<(), AflError> { self.0.append_metadata(testcase)?; - self.1.append_metadata_all(testcase) + self.1.append_metadata_all(testcase) } - fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError>{ + fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError> { self.0.discard_metadata(input)?; - self.1.discard_metadata_all(input) + self.1.discard_metadata_all(input) } /*fn for_each(&self, f: fn(&dyn Feedback)) { @@ -191,7 +217,7 @@ where O: MapObserver + 'static, { #[inline] - fn name(&self) -> &'static str { + fn name(&self) -> &str { self.name } } @@ -211,13 +237,13 @@ where } } - pub fn new_with_observer(map_observer: &O) -> Self { + /*pub fn new_with_observer(map_observer: &O) -> Self { Self { history_map: vec![T::default(); map_observer.map().len()], name: map_observer.name(), phantom: PhantomData, } - } + }*/ } impl MapFeedback diff --git a/afl/src/observers/mod.rs b/afl/src/observers/mod.rs index b9326fb8a4..a6be37e922 100644 --- a/afl/src/observers/mod.rs +++ b/afl/src/observers/mod.rs @@ -3,12 +3,12 @@ extern crate num; use serde::{Deserialize, Serialize}; use crate::serde_anymap::ArrayMut; -use crate::tuples::{TupleList, MatchNameAndType, MatchType, Named}; +use crate::tuples::{MatchNameAndType, MatchType, Named, TupleList}; use crate::AflError; /// Observers observe different information about the target. /// They can then be used by various sorts of feedback. -pub trait Observer: Named + 'static { +pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned + 'static { /// The testcase finished execution, calculate any changes. #[inline] fn flush(&mut self) -> Result<(), AflError> { @@ -23,7 +23,9 @@ pub trait Observer: Named + 'static { } } -pub trait ObserversTuple: 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)); @@ -31,24 +33,29 @@ pub trait ObserversTuple: MatchNameAndType + MatchType + serde::Serialize + serd } impl ObserversTuple for () { - fn reset_all(&mut self) -> Result<(), AflError> { Ok(()) } - fn post_exec_all(&mut self) -> Result<(), AflError> { Ok(()) } + 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_mut(&mut self, f: fn(&mut dyn Observer)) { } } -impl ObserversTuple for (Head, Tail) where - Head: Observer + serde::Serialize + serde::de::DeserializeOwned, +impl ObserversTuple for (Head, Tail) +where + Head: Observer, Tail: ObserversTuple + TupleList, { fn reset_all(&mut self) -> Result<(), AflError> { self.0.reset()?; - self.1.reset_all() + self.1.reset_all() } fn post_exec_all(&mut self) -> Result<(), AflError> { self.0.post_exec()?; - self.1.post_exec_all() + self.1.post_exec_all() } /*fn for_each(&self, f: fn(&dyn Observer)) { @@ -105,7 +112,7 @@ where { map: ArrayMut, initial: T, - name: &'static str, + name: String, } impl Observer for StdMapObserver @@ -118,12 +125,13 @@ where } } -impl Named for StdMapObserver where -T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, +impl Named for StdMapObserver +where + T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, { #[inline] - fn name(&self) -> &'static str { - self.name + fn name(&self) -> &str { + self.name.as_str() } } @@ -202,4 +210,4 @@ mod tests { assert_eq!(d.name(), o.name()); } } -*/ \ No newline at end of file +*/ diff --git a/afl/src/stages/mod.rs b/afl/src/stages/mod.rs index efe81d5e2d..f63dc2b855 100644 --- a/afl/src/stages/mod.rs +++ b/afl/src/stages/mod.rs @@ -4,11 +4,11 @@ pub use mutational::StdMutationalStage; use crate::corpus::Corpus; use crate::engines::{Engine, State}; use crate::events::EventManager; -use crate::executors::{HasObservers, Executor}; -use crate::observers::ObserversTuple; +use crate::executors::{Executor, HasObservers}; use crate::feedbacks::FeedbacksTuple; -use crate::tuples::{TupleList, MatchType}; use crate::inputs::Input; +use crate::observers::ObserversTuple; +use crate::tuples::{MatchType, TupleList}; use crate::utils::Rand; use crate::AflError; @@ -77,12 +77,15 @@ where 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)) { } + ) -> 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 +impl StagesTuple for (Head, Tail) +where Head: Stage, Tail: StagesTuple + TupleList, EM: EventManager, @@ -102,8 +105,10 @@ impl StagesTuple for 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) + 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)) { @@ -115,4 +120,4 @@ impl StagesTuple for 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 2f80e59aea..804326e020 100644 --- a/afl/src/stages/mutational.rs +++ b/afl/src/stages/mutational.rs @@ -1,11 +1,11 @@ use core::marker::PhantomData; use crate::events::EventManager; -use crate::executors::{HasObservers, Executor}; -use crate::observers::ObserversTuple; +use crate::executors::{Executor, HasObservers}; use crate::feedbacks::FeedbacksTuple; use crate::inputs::Input; use crate::mutators::Mutator; +use crate::observers::ObserversTuple; use crate::stages::Corpus; use crate::stages::{Engine, Stage}; use crate::utils::Rand; @@ -101,7 +101,8 @@ where phantom: PhantomData<(EM, E, OT, FT, C, I, R)>, } -impl MutationalStage for StdMutationalStage +impl MutationalStage + for StdMutationalStage where M: Mutator, EM: EventManager, @@ -125,7 +126,8 @@ where } } -impl Stage for StdMutationalStage +impl Stage + for StdMutationalStage where M: Mutator, EM: EventManager, diff --git a/afl/src/tuples.rs b/afl/src/tuples.rs index daf00d98dd..d7209b8bab 100644 --- a/afl/src/tuples.rs +++ b/afl/src/tuples.rs @@ -1,6 +1,6 @@ -pub use tuple_list::TupleList; pub use tuple_list::tuple_list; pub use tuple_list::tuple_list_type; +pub use tuple_list::TupleList; use core::any::TypeId; @@ -9,10 +9,13 @@ pub trait HasLen { } impl HasLen for () { - fn len(&self) -> usize { 0 } + fn len(&self) -> usize { + 0 + } } - -impl HasLen for (Head, Tail) where + +impl HasLen for (Head, Tail) +where Tail: TupleList + HasLen, { fn len(&self) -> usize { @@ -26,11 +29,16 @@ pub trait MatchFirstType { } impl MatchFirstType for () { - fn match_first_type(&self) -> Option<&T> { None } - fn match_first_type_mut(&mut self) -> Option<&mut T> { None } + fn match_first_type(&self) -> Option<&T> { + None + } + fn match_first_type_mut(&mut self) -> Option<&mut T> { + None + } } - -impl MatchFirstType for (Head, Tail) where + +impl MatchFirstType for (Head, Tail) +where Head: 'static, Tail: TupleList + MatchFirstType, { @@ -57,11 +65,16 @@ pub trait MatchType { } impl MatchType for () { - fn match_type(&self, f: fn(t: &T)) { () } - fn match_type_mut(&mut self, f: fn(t: &mut T)) { () } + fn match_type(&self, f: fn(t: &T)) { + () + } + fn match_type_mut(&mut self, f: fn(t: &mut T)) { + () + } } - -impl MatchType for (Head, Tail) where + +impl MatchType for (Head, Tail) +where Head: 'static, Tail: TupleList + MatchType, { @@ -81,7 +94,7 @@ impl MatchType for (Head, Tail) where } pub trait Named { - fn name(&self) -> &'static str; + fn name(&self) -> &str; } pub trait MatchNameAndType { @@ -90,11 +103,16 @@ pub trait MatchNameAndType { } impl MatchNameAndType for () { - fn match_name_type(&self, name: &'static str) -> Option<&T> { None } - fn match_name_type_mut(&mut self, name: &'static str) -> Option<&mut T> { None } + fn match_name_type(&self, name: &'static str) -> Option<&T> { + None + } + fn match_name_type_mut(&mut self, name: &'static str) -> Option<&mut T> { + None + } } - -impl MatchNameAndType for (Head, Tail) where + +impl MatchNameAndType for (Head, Tail) +where Head: 'static + Named, Tail: TupleList + MatchNameAndType, { @@ -122,35 +140,41 @@ pub trait Prepend: TupleList { } /// Implement prepend for tuple list. -impl Prepend for Tail where Tail: TupleList { +impl Prepend for Tail +where + Tail: TupleList, +{ type PreprendResult = Self; fn prepend(self, value: T) -> (T, Self::PreprendResult) { (value, self) } } - + pub trait Append: TupleList { type AppendResult: TupleList; - + fn append(self, value: T) -> Self::AppendResult; } - + /// Implement append for an empty tuple list. impl Append for () { type AppendResult = (T, ()); - - fn append(self, value: T) -> Self::AppendResult { (value, ()) } + + fn append(self, value: T) -> Self::AppendResult { + (value, ()) + } } - + /// Implement append for non-empty tuple list. -impl Append for (Head, Tail) where +impl Append for (Head, Tail) +where Self: TupleList, Tail: Append, (Head, Tail::AppendResult): TupleList, { type AppendResult = (Head, Tail::AppendResult); - + fn append(self, value: T) -> Self::AppendResult { let (head, tail) = self; return (head, tail.append(value)); @@ -165,13 +189,13 @@ trait PlusOne { } impl PlusOne for i32 { fn plus_one(&mut self) { *self += 1; } } impl PlusOne for String { fn plus_one(&mut self) { self.push('1'); } } - + // Now we have to implement trait for an empty tuple, // thus defining initial condition. impl PlusOne for () { fn plus_one(&mut self) {} } - + // Now we can implement trait for a non-empty tuple list, // thus defining recursion and supporting tuple lists of arbitrary length. impl PlusOne for (Head, Tail) where diff --git a/fuzzers/libfuzzer/src/lib.rs b/fuzzers/libfuzzer/src/lib.rs index c4e17e4923..70c020a273 100644 --- a/fuzzers/libfuzzer/src/lib.rs +++ b/fuzzers/libfuzzer/src/lib.rs @@ -22,8 +22,9 @@ use afl::mutators::HasMaxSize; use afl::observers::StdMapObserver; use afl::stages::mutational::StdMutationalStage; use afl::utils::StdRand; +use afl::tuples::tuple_list; -// const MAP_SIZE: usize = 65536; +const MAP_SIZE: usize = 65536; #[no_mangle] extern "C" { @@ -59,18 +60,12 @@ pub extern "C" fn afl_libfuzzer_main() { StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { __lafl_edges_map }, unsafe { __lafl_max_edges_size as usize }); - let edges_feedback = MaxMapFeedback::new_with_observer(&edges_observer); - - let mut executor = InMemoryExecutor::new(harness); - let mut state = State::new(); - executor.add_observer(Box::new(edges_observer)); - state.add_feedback(Box::new(edges_feedback)); + let edges_feedback = MaxMapFeedback::>::new(&NAME_COV_MAP, MAP_SIZE); + let executor = InMemoryExecutor::new(harness, tuple_list!(edges_observer)); + let mut state = State::new(tuple_list!(edges_feedback)); + let mut engine = Engine::new(executor); - let mut mutator = HavocBytesMutator::new_default(); - mutator.set_max_size(4096); - - let stage = StdMutationalStage::new(mutator); state .generate_initial_inputs( @@ -83,9 +78,11 @@ pub extern "C" fn afl_libfuzzer_main() { ) .expect("Failed to load initial inputs"); - let mut fuzzer = StdFuzzer::new(); + let mut mutator = HavocBytesMutator::new_default(); + mutator.set_max_size(4096); - fuzzer.add_stage(Box::new(stage)); + let stage = StdMutationalStage::new(mutator); + let mut fuzzer = StdFuzzer::new(tuple_list!(stage)); fuzzer .fuzz_loop(&mut rand, &mut state, &mut corpus, &mut engine, &mut events)