diff --git a/afl/src/corpus/mod.rs b/afl/src/corpus/mod.rs index 9dce6960bf..b8a33d55c4 100644 --- a/afl/src/corpus/mod.rs +++ b/afl/src/corpus/mod.rs @@ -200,9 +200,9 @@ where R: Rand, { corpus: C, - phantom: PhantomData<(I, R)>, pos: usize, cycles: u64, + phantom: PhantomData<(I, R)>, } impl HasTestcaseVec for QueueCorpus diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index b1cc09a08e..e6adadc5af 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -5,6 +5,7 @@ use alloc::rc::Rc; use alloc::vec::Vec; use core::cell::RefCell; use core::fmt::Debug; +use core::marker::PhantomData; use hashbrown::HashMap; @@ -15,6 +16,7 @@ use crate::feedbacks::Feedback; use crate::inputs::Input; use crate::observers::Observer; use crate::stages::Stage; +use crate::utils::Rand; use crate::AflError; // TODO FeedbackMetadata to store histroy_map @@ -29,6 +31,7 @@ where C: Corpus, E: Executor, I: Input, + R: Rand, { /// Get executions fn executions(&self) -> usize; @@ -120,9 +123,10 @@ where pub struct StdState where - C: Corpus, + C: Corpus, E: Executor, I: Input, + R: Rand, { executions: usize, metadatas: HashMap<&'static str, Box>, @@ -131,9 +135,10 @@ where feedbacks: Vec>>, corpus: C, executor: E, + phantom: PhantomData, } -impl HasCorpus for DefaultState +impl HasCorpus for StdState where C: Corpus, E: Executor, @@ -152,9 +157,10 @@ where impl State for StdState where - C: Corpus, + C: Corpus, E: Executor, I: Input, + R: Rand, { fn executions(&self) -> usize { self.executions @@ -199,9 +205,10 @@ where impl StdState where - C: Corpus, + C: Corpus, E: Executor, I: Input, + R: Rand, { pub fn new(corpus: C, executor: E) -> Self { StdState { @@ -211,22 +218,25 @@ where feedbacks: vec![], corpus: corpus, executor: executor, + phantom: PhantomData, } } } -pub trait Engine +pub trait Engine where S: State, - C: Corpus, + 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); } @@ -234,52 +244,62 @@ where &mut self, rand: &mut R, state: &mut S, - events_manager: &mut EM, + events: &mut EM, ) -> Result { let (testcase, idx) = state.corpus_mut().next(rand)?; println!("Cur entry: {}\tExecutions: {}", idx, state.executions()); for stage in self.stages_mut() { - stage.perform(testcase.clone(), state)?; + stage.perform(rand, state, events, testcase.clone())?; } Ok(idx) } } -pub struct StdEngine -where - S: State, - C: Corpus, - E: Executor, - I: Input, -{ - stages: Vec>>, -} - -impl Engine for StdEngine +pub struct StdEngine where S: State, - C: Corpus, + EM: EventManager, E: Executor, + C: Corpus, I: Input, + R: Rand, { - fn stages(&self) -> &[Box>] { + stages: Vec>>, + phantom: PhantomData, +} + +impl Engine for StdEngine +where + S: State, + EM: EventManager, + E: Executor, + C: Corpus, + I: Input, + R: Rand, +{ + 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 StdEngine where S: State, - C: Corpus, + EM: EventManager, E: Executor, + C: Corpus, I: Input, + R: Rand, { pub fn new() -> Self { - StdEngine { stages: vec![] } + StdEngine { + stages: vec![], + phantom: PhantomData, + } } } @@ -290,6 +310,7 @@ mod tests { use crate::corpus::{Corpus, InMemoryCorpus, Testcase}; use crate::engines::{Engine, StdEngine, StdState}; + use crate::events::LoggerEventManager; use crate::executors::inmemory::InMemoryExecutor; use crate::executors::{Executor, ExitKind}; use crate::inputs::bytes::BytesInput; @@ -303,26 +324,28 @@ mod tests { #[test] fn test_engine() { - let rand = StdRand::new(0).into(); + let mut rand = StdRand::new(0); - let mut corpus = InMemoryCorpus::::new(&rand); + let mut corpus = InMemoryCorpus::::new(); let testcase = Testcase::new(vec![0; 4]).into(); corpus.add(testcase); let executor = InMemoryExecutor::::new(harness); let mut state = StdState::new(corpus, executor); + let mut events_manager = LoggerEventManager::new(); + let mut engine = StdEngine::new(); - let mut mutator = StdScheduledMutator::new(&rand); + let mut mutator = StdScheduledMutator::new(); mutator.add_mutation(mutation_bitflip); - let stage = StdMutationalStage::new(&rand, mutator); + let stage = StdMutationalStage::new(mutator); engine.add_stage(Box::new(stage)); // for i in 0..1000 { engine - .fuzz_one(&mut state) + .fuzz_one(&mut rand, &mut state, &mut events_manager) .expect(&format!("Error in iter {}", i)); } } diff --git a/afl/src/mutators/mod.rs b/afl/src/mutators/mod.rs index 7df7a2d26a..9f4d235db6 100644 --- a/afl/src/mutators/mod.rs +++ b/afl/src/mutators/mod.rs @@ -1,24 +1,28 @@ pub mod scheduled; pub use scheduled::ComposedByMutations; -pub use scheduled::StdScheduledMutator; pub use scheduled::HavocBytesMutator; pub use scheduled::ScheduledMutator; +pub use scheduled::StdScheduledMutator; -use crate::corpus::{Corpus, HasCorpus}; -//use crate::engines::State; +use crate::corpus::Corpus; use crate::inputs::Input; -use crate::utils::{HasRand, Rand}; +use crate::utils::Rand; use crate::AflError; -pub trait Mutator +pub trait Mutator where - S: HasRand + HasCorpus, C: Corpus, I: Input, R: Rand, { /// Mutate a given input - fn mutate(&mut self, state: &mut S, input: &mut I, stage_idx: i32) -> Result<(), AflError>; + fn mutate( + &mut self, + rand: &mut R, + corpus: &mut C, + input: &mut I, + stage_idx: i32, + ) -> Result<(), AflError>; /// Post-process given the outcome of the execution fn post_exec(&mut self, _is_interesting: bool, _stage_idx: i32) -> Result<(), AflError> { diff --git a/afl/src/mutators/scheduled.rs b/afl/src/mutators/scheduled.rs index f1b5b71e05..b1678b1810 100644 --- a/afl/src/mutators/scheduled.rs +++ b/afl/src/mutators/scheduled.rs @@ -1,7 +1,7 @@ use crate::inputs::{HasBytesVec, Input}; +use crate::mutators::Corpus; use crate::mutators::Mutator; -use crate::mutators::{Corpus, HasCorpus}; -use crate::utils::{HasRand, Rand}; +use crate::utils::Rand; use crate::AflError; use alloc::vec::Vec; @@ -14,29 +14,27 @@ pub enum MutationResult { // TODO maybe the mutator arg is not needed /// The generic function type that identifies mutations -type MutationFunction = fn(&mut M, &mut S, &mut I) -> Result; +type MutationFunction = + fn(&mut M, &mut R, &mut C, &mut I) -> Result; -pub trait ComposedByMutations +pub trait ComposedByMutations where - S: HasRand + HasCorpus, C: Corpus, I: Input, R: Rand, { /// Get a mutation by index - fn mutation_by_idx(&self, index: usize) -> Result, AflError>; + fn mutation_by_idx(&self, index: usize) -> Result, AflError>; /// Get the number of mutations fn mutations_count(&self) -> usize; /// Add a mutation - fn add_mutation(&mut self, mutation: MutationFunction); + fn add_mutation(&mut self, mutation: MutationFunction); } -pub trait ScheduledMutator: - Mutator + ComposedByMutations +pub trait ScheduledMutator: Mutator + ComposedByMutations where - S: HasRand + HasCorpus, C: Corpus, I: Input, R: Rand, @@ -51,7 +49,7 @@ where &mut self, rand: &mut R, _input: &I, - ) -> Result, AflError> { + ) -> Result, AflError> { let count = self.mutations_count() as u64; if count == 0 { return Err(AflError::Empty("no mutations".into())); @@ -67,47 +65,52 @@ where /// Implementations must forward mutate() to this method fn scheduled_mutate( &mut self, - state: &mut S, + rand: &mut R, + corpus: &mut C, input: &mut I, _stage_idx: i32, ) -> Result<(), AflError> { - let num = self.iterations(state.rand_mut(), input); + let num = self.iterations(rand, input); for _ in 0..num { - self.schedule(state.rand_mut(), input)?(self, state, input)?; + self.schedule(rand, input)?(self, rand, corpus, input)?; } Ok(()) } } -pub struct StdScheduledMutator +pub struct StdScheduledMutator where C: Corpus, I: Input, R: Rand, { - mutations: Vec>, + mutations: Vec>, } -impl Mutator for StdScheduledMutator +impl Mutator for StdScheduledMutator where - S: HasRand + HasCorpus, C: Corpus, I: Input, R: Rand, { - fn mutate(&mut self, state: &mut S, input: &mut I, _stage_idx: i32) -> Result<(), AflError> { - self.scheduled_mutate(state, input, _stage_idx) + fn mutate( + &mut self, + rand: &mut R, + corpus: &mut C, + input: &mut I, + _stage_idx: i32, + ) -> Result<(), AflError> { + self.scheduled_mutate(rand, corpus, input, _stage_idx) } } -impl ComposedByMutations for StdScheduledMutator +impl ComposedByMutations for StdScheduledMutator where - S: HasRand + HasCorpus, C: Corpus, I: Input, R: Rand, { - fn mutation_by_idx(&self, index: usize) -> Result, AflError> { + fn mutation_by_idx(&self, index: usize) -> Result, AflError> { if index >= self.mutations.len() { return Err(AflError::Unknown("oob".into())); } @@ -118,14 +121,13 @@ where self.mutations.len() } - fn add_mutation(&mut self, mutation: MutationFunction) { + fn add_mutation(&mut self, mutation: MutationFunction) { self.mutations.push(mutation) } } -impl ScheduledMutator for DefaultScheduledMutator +impl ScheduledMutator for StdScheduledMutator where - S: HasRand + HasCorpus, C: Corpus, I: Input, R: Rand, @@ -133,9 +135,8 @@ where // Just use the default methods } -impl DefaultScheduledMutator +impl StdScheduledMutator where - S: HasRand + HasCorpus, C: Corpus, I: Input, R: Rand, @@ -145,8 +146,8 @@ where StdScheduledMutator { mutations: vec![] } } - /// Create a new StdScheduledMutator instance specifying mutations and corpus too - pub fn new_all(mutations: Vec>) -> Self { + /// Create a new StdScheduledMutator instance specifying mutations + pub fn with_mutations(mutations: Vec>) -> Self { StdScheduledMutator { mutations: mutations, } @@ -154,19 +155,19 @@ where } /// Bitflip mutation for inputs with a bytes vector -pub fn mutation_bitflip( +pub fn mutation_bitflip( mutator: &mut M, - state: &mut S, + rand: &mut R, + _corpus: &mut C, input: &mut I, ) -> Result where - M: Mutator, - S: HasRand + HasCorpus, + M: Mutator, C: Corpus, I: Input + HasBytesVec, R: Rand, { - let bit = state.rand_mut().below((input.bytes().len() * 8) as u64) as usize; + let bit = rand.below((input.bytes().len() * 8) as u64) as usize; input.bytes_mut()[bit >> 3] ^= (128 >> (bit & 7)) as u8; Ok(MutationResult::Mutated) } @@ -188,14 +189,14 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) { } /// Splicing mutator -pub fn mutation_splice( +pub fn mutation_splice( mutator: &mut M, - state: &mut S, + rand: &mut R, + corpus: &mut C, input: &mut I, ) -> Result where - M: Mutator, - S: HasRand + HasCorpus, + M: Mutator, C: Corpus, I: Input + HasBytesVec, R: Rand, @@ -204,7 +205,7 @@ where // We don't want to use the testcase we're already using for splicing let other_rr = loop { let mut found = false; - let (other_rr, _) = state.corpus_mut().random_entry(state.rand_mut())?.clone(); + let (other_rr, _) = corpus.random_entry(rand)?.clone(); match other_rr.try_borrow_mut() { Ok(_) => found = true, Err(_) => { @@ -251,42 +252,41 @@ where } /// Schedule some selected byte level mutations given a ScheduledMutator type -pub struct HavocBytesMutator +pub struct HavocBytesMutator where + SM: ScheduledMutator, C: Corpus, I: Input + HasBytesVec, - SM: ScheduledMutator, R: Rand, { scheduled: SM, - phantom: PhantomData<(I, R)>, - _phantom_corpus: PhantomData, + phantom: PhantomData<(I, R, C)>, } -impl Mutator for HavocBytesMutator +impl Mutator for HavocBytesMutator where + SM: ScheduledMutator, C: Corpus, I: Input + HasBytesVec, - SM: ScheduledMutator, R: Rand, { /// Mutate bytes fn mutate( &mut self, - corpus: &mut C, rand: &mut R, + corpus: &mut C, input: &mut I, stage_idx: i32, ) -> Result<(), AflError> { - self.scheduled.mutate(corpus, rand, input, stage_idx) + self.scheduled.mutate(rand, corpus, input, stage_idx) } } -impl HavocBytesMutator +impl HavocBytesMutator where + SM: ScheduledMutator, C: Corpus, I: Input + HasBytesVec, - SM: ScheduledMutator, R: Rand, { /// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap @@ -296,12 +296,11 @@ where HavocBytesMutator { scheduled: scheduled, phantom: PhantomData, - _phantom_corpus: PhantomData, } } } -impl HavocBytesMutator, R> +impl HavocBytesMutator, C, I, R> where C: Corpus, I: Input + HasBytesVec, @@ -315,7 +314,6 @@ where HavocBytesMutator { scheduled: scheduled, phantom: PhantomData, - _phantom_corpus: PhantomData, } } } @@ -334,7 +332,7 @@ mod tests { fn test_mut_splice() { // With the current impl, seed of 1 will result in a split at pos 2. let mut rand = XKCDRand::new(); - let mut corpus: InMemoryCorpus = InMemoryCorpus::new(); + let mut corpus: InMemoryCorpus = InMemoryCorpus::new(); corpus.add(Testcase::new(vec!['a' as u8, 'b' as u8, 'c' as u8]).into()); corpus.add(Testcase::new(vec!['d' as u8, 'e' as u8, 'f' as u8]).into()); @@ -345,9 +343,9 @@ mod tests { let mut input = testcase.load_input().expect("No input in testcase").clone(); rand.set_seed(5); - let mut mutator = StdScheduledMutator::, BytesInput, XKCDRand>::new(); + let mut mutator = StdScheduledMutator::new(); - mutation_splice(&mut mutator, &mut corpus, &mut rand, &mut input).unwrap(); + mutation_splice(&mut mutator, &mut rand, &mut corpus, &mut input).unwrap(); #[cfg(feature = "std")] println!("{:?}", input.bytes()); diff --git a/afl/src/stages/mod.rs b/afl/src/stages/mod.rs index 1499834870..e951caca52 100644 --- a/afl/src/stages/mod.rs +++ b/afl/src/stages/mod.rs @@ -4,6 +4,7 @@ pub use mutational::StdMutationalStage; use crate::corpus::testcase::Testcase; use crate::corpus::Corpus; use crate::engines::State; +use crate::events::EventManager; use crate::executors::Executor; use crate::inputs::Input; use crate::utils::Rand; @@ -11,11 +12,12 @@ use crate::AflError; use alloc::rc::Rc; use core::cell::RefCell; -pub trait Stage +pub trait Stage where S: State, - C: Corpus, + EM: EventManager, E: Executor, + C: Corpus, I: Input, R: Rand, { @@ -24,6 +26,7 @@ where &mut self, rand: &mut R, state: &mut S, + events: &mut EM, testcase: Rc>>, ) -> Result<(), AflError>; } diff --git a/afl/src/stages/mutational.rs b/afl/src/stages/mutational.rs index a81d6ea2e6..2beaf82ace 100644 --- a/afl/src/stages/mutational.rs +++ b/afl/src/stages/mutational.rs @@ -15,12 +15,13 @@ use crate::AflError; // TODO multi mutators stage -pub trait MutationalStage: Stage +pub trait MutationalStage: Stage where M: Mutator, S: State, - C: Corpus, + EM: EventManager, E: Executor, + C: Corpus, I: Input, R: Rand, { @@ -41,6 +42,7 @@ where &mut self, rand: &mut R, state: &mut S, + events: &mut EM, testcase: Rc>>, ) -> Result<(), AflError> { let num = self.iterations(rand); @@ -49,7 +51,7 @@ where for i in 0..num { let mut input_tmp = input.clone(); self.mutator_mut() - .mutate(rand, state, &mut input_tmp, i as i32)?; + .mutate(rand, state.corpus_mut(), &mut input_tmp, i as i32)?; let interesting = state.evaluate_input(&input_tmp)?; @@ -64,28 +66,28 @@ where } /// The default mutational stage -pub struct StdMutationalStage +pub struct StdMutationalStage where M: Mutator, - S: State, - C: Corpus, - E: Executor, + S: State, EM: EventManager, + E: Executor, + C: Corpus, I: Input, R: Rand, { mutator: M, - phantom: PhantomData<(S, C, E, EM, I, R)>, + phantom: PhantomData<(S, EM, E, C, I, R)>, } -impl MutationalStage - for StdMutationalStage +impl MutationalStage + for StdMutationalStage where M: Mutator, - S: State, - C: Corpus, - E: Executor, + S: State, EM: EventManager, + E: Executor, + C: Corpus, I: Input, R: Rand, { @@ -100,32 +102,34 @@ where } } -impl Stage for StdMutationalStage +impl Stage for StdMutationalStage where M: Mutator, - S: State, - C: Corpus, - E: Executor, + S: State, EM: EventManager, + E: Executor, + C: Corpus, I: Input, R: Rand, { fn perform( &mut self, - testcase: Rc>>, + rand: &mut R, state: &mut S, + events: &mut EM, + testcase: Rc>>, ) -> Result<(), AflError> { - self.perform_mutational(testcase, state) + self.perform_mutational(rand, state, events, testcase) } } -impl StdMutationalStage +impl StdMutationalStage where M: Mutator, - S: State, - C: Corpus, - E: Executor, + S: State, EM: EventManager, + E: Executor, + C: Corpus, I: Input, R: Rand, { diff --git a/fuzzers/libfuzzer/src/lib.rs b/fuzzers/libfuzzer/src/lib.rs index 3b5cb40820..90d717fbdd 100644 --- a/fuzzers/libfuzzer/src/lib.rs +++ b/fuzzers/libfuzzer/src/lib.rs @@ -8,7 +8,8 @@ use alloc::rc::Rc; use core::cell::RefCell; use afl::corpus::{Corpus, InMemoryCorpus, Testcase}; -use afl::engines::{StdEngine, StdState, Engine, State}; +use afl::engines::{Engine, State, StdEngine, StdState}; +use afl::events::LoggerEventManager; use afl::executors::inmemory::InMemoryExecutor; use afl::executors::{Executor, ExitKind}; use afl::feedbacks::{create_history_map, MaxMapFeedback}; @@ -39,9 +40,9 @@ fn harness(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { #[no_mangle] pub extern "C" fn afl_libfuzzer_main() { - let rand = StdRand::new(0).into(); + let mut rand = StdRand::new(0); - let mut corpus = InMemoryCorpus::::new(&rand); + let mut corpus = InMemoryCorpus::new(); let testcase = Testcase::new(vec![0; 4]).into(); corpus.add(testcase); @@ -58,16 +59,17 @@ pub extern "C" fn afl_libfuzzer_main() { state.add_feedback(Box::new(edges_feedback)); let mut engine = StdEngine::new(); - let mutator = HavocBytesMutator::new_default(&rand); - let stage = StdMutationalStage::new(&rand, mutator); + let mutator = HavocBytesMutator::new_default(); + let stage = StdMutationalStage::new(mutator); engine.add_stage(Box::new(stage)); + let mut events = LoggerEventManager::new(); + for i in 0..1000 { engine - .fuzz_one(&mut state) + .fuzz_one(&mut rand, &mut state, &mut events) .expect(&format!("Error in iter {}", i)); } - #[cfg(feature = "std")] println!("OK"); }