diff --git a/src/engines/mod.rs b/src/engines/mod.rs index 313c3deaca..564d0b8b7f 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -1,5 +1,7 @@ +//! The engine is the core piece of every good fuzzer extern crate alloc; -use crate::corpus::testcase::Testcase; + +use crate::corpus::Corpus; use crate::feedbacks::Feedback; use crate::inputs::Input; use crate::stages::Stage; @@ -8,8 +10,9 @@ use crate::AflError; use alloc::rc::Rc; use core::cell::RefCell; -pub trait Engine +pub trait Engine where + C: Corpus, I: Input, { fn feedbacks(&self) -> &Vec>>; @@ -20,32 +23,34 @@ where self.feedbacks_mut().push(feedback); } - fn stages(&self) -> &Vec>>; + fn stages(&self) -> &Vec>>; - 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(&mut self, testcase: &Rc>>) -> Result<(), AflError> { + fn fuzz_one(&mut self, corpus: &mut C) -> Result<(), AflError> { for stage in self.stages_mut() { - stage.perform(&testcase)?; + stage.perform(corpus)?; } Ok(()) } } -pub struct DefaultEngine +pub struct DefaultEngine where + C: Corpus, I: Input, { feedbacks: Vec>>, - stages: Vec>>, + stages: Vec>>, } -impl Engine for DefaultEngine +impl Engine for DefaultEngine where + C: Corpus, I: Input, { fn feedbacks(&self) -> &Vec>> { @@ -56,17 +61,18 @@ where &mut self.feedbacks } - fn stages(&self) -> &Vec>> { + fn stages(&self) -> &Vec>> { &self.stages } - fn stages_mut(&mut self) -> &mut Vec>> { + fn stages_mut(&mut self) -> &mut Vec>> { &mut self.stages } } -impl DefaultEngine +impl DefaultEngine where + C: Corpus, I: Input, { pub fn new() -> Self { @@ -92,6 +98,8 @@ mod tests { mutation_bitflip, ComposedByMutations, DefaultScheduledMutator, }; use crate::stages::mutational::DefaultMutationalStage; + use alloc::rc::Rc; + use core::cell::RefCell; use crate::utils::Xoshiro256StarRand; @@ -106,12 +114,16 @@ mod tests { let mut corpus = InMemoryCorpus::::new(&rand); let testcase = Testcase::new_rr(BytesInput::new(vec![0; 4])); corpus.add(testcase); - let executor = InMemoryExecutor::new_rr(harness); + let executor: Rc>> = InMemoryExecutor::new_rr(harness); let mut engine = DefaultEngine::new(); let mut mutator = DefaultScheduledMutator::new(&rand); mutator.add_mutation(mutation_bitflip); let stage = DefaultMutationalStage::new(&rand, &executor, mutator); engine.add_stage(Box::new(stage)); - engine.fuzz_one(&corpus.next().unwrap()).unwrap(); + for i in 0..1000 { + engine + .fuzz_one(&mut corpus) + .expect(&format!("Error in iter {}", i)); + } } } diff --git a/src/stages/mod.rs b/src/stages/mod.rs index d951ff2dc3..639ad8f1fa 100644 --- a/src/stages/mod.rs +++ b/src/stages/mod.rs @@ -1,18 +1,16 @@ extern crate alloc; pub mod mutational; +use crate::corpus::Corpus; pub use mutational::DefaultMutationalStage; -use crate::corpus::Testcase; use crate::inputs::Input; use crate::AflError; -use alloc::rc::Rc; -use core::cell::RefCell; - -pub trait Stage +pub trait Stage where + C: Corpus, I: Input, { /// Run the stage - fn perform(&mut self, entry: &Rc>>) -> Result<(), AflError>; + fn perform(&mut self, corpus: &mut C) -> Result<(), AflError>; } diff --git a/src/stages/mutational.rs b/src/stages/mutational.rs index 8d58ee954a..532b8fba95 100644 --- a/src/stages/mutational.rs +++ b/src/stages/mutational.rs @@ -3,6 +3,7 @@ use crate::corpus::testcase::Testcase; use crate::executors::Executor; use crate::inputs::Input; use crate::mutators::Mutator; +use crate::stages::Corpus; use crate::stages::Stage; use crate::utils::{HasRand, Rand}; use crate::AflError; @@ -13,8 +14,9 @@ use core::marker::PhantomData; // TODO create HasMutatorsVec trait -pub trait MutationalStage: Stage + HasRand +pub trait MutationalStage: Stage + HasRand where + C: Corpus, I: Input, M: Mutator, E: Executor, @@ -34,9 +36,9 @@ where 1 + self.rand_below(128) as usize } - // TODO: We need a way to get testcases for splicing /// Runs this (mutational) stage for the given testcase - fn perform_mutational(&mut self, testcase: &Rc>>) -> Result<(), AflError> { + fn perform_mutational(&mut self, corpus: &mut C) -> Result<(), AflError> { + let testcase = corpus.next()?; let num = self.iterations(); let input = testcase.borrow_mut().load_input()?.clone(); @@ -47,6 +49,10 @@ where let interesting = self.executor().borrow_mut().evaluate_input(&input_tmp)?; self.mutator_mut().post_exec(interesting, i as i32)?; + + if interesting { + corpus.add(Testcase::new_rr(input_tmp)); + } } Ok(()) } @@ -80,8 +86,9 @@ where } } -impl MutationalStage for DefaultMutationalStage +impl MutationalStage for DefaultMutationalStage where + C: Corpus, I: Input, R: Rand, M: Mutator, @@ -102,15 +109,16 @@ where } } -impl Stage for DefaultMutationalStage +impl Stage for DefaultMutationalStage where + C: Corpus, I: Input, R: Rand, M: Mutator, E: Executor, { - fn perform(&mut self, testcase: &Rc>>) -> Result<(), AflError> { - self.perform_mutational(testcase) + fn perform(&mut self, corpus: &mut C) -> Result<(), AflError> { + self.perform_mutational(corpus) } }