diff --git a/src/corpus/mod.rs b/src/corpus/mod.rs index 5fdf232020..81fc1d3cae 100644 --- a/src/corpus/mod.rs +++ b/src/corpus/mod.rs @@ -56,14 +56,14 @@ where } /// Gets a random entry - fn random_entry(&mut self) -> Result<&Rc>>, AflError> { + fn random_entry(&mut self) -> Result>>, AflError> { let len = { self.entries().len() }; let id = self.rand_mut().below(len as u64) as usize; - Ok(self.entries_mut().get_mut(id).unwrap()) + Ok(self.entries()[id].clone()) } /// Gets the next entry (random by default) - fn get(&mut self) -> Result<&Rc>>, AflError> { + fn get(&mut self) -> Result>>, AflError> { self.random_entry() } } @@ -257,12 +257,12 @@ where } /// Gets a random entry - fn random_entry(&mut self) -> Result<&Rc>>, AflError> { + fn random_entry(&mut self) -> Result>>, AflError> { self.corpus.random_entry() } /// Gets the next entry - fn get(&mut self) -> Result<&Rc>>, AflError> { + fn get(&mut self) -> Result>>, AflError> { if self.corpus.count() == 0 { return Err(AflError::Empty("Testcases".to_string())); } @@ -271,7 +271,7 @@ where self.cycles = self.cycles + 1; self.pos = 0; } - Ok(self.corpus.entries_mut().get_mut(self.pos).unwrap()) + Ok(self.corpus.entries()[self.pos].clone()) } } diff --git a/src/corpus/testcase.rs b/src/corpus/testcase.rs index 83a23578f7..007b0dbbae 100644 --- a/src/corpus/testcase.rs +++ b/src/corpus/testcase.rs @@ -82,6 +82,11 @@ where &mut self.metadatas } + /// Add a metadata + pub fn add_metadata(&mut self, name: String, meta: Box) { + self.metadatas.insert(name, meta); + } + /// Create a new DefaultTestcase instace given an input pub fn new(input: I) -> Self { Testcase { diff --git a/src/engines/aflengine.rs b/src/engines/aflengine.rs index f75057281e..5d97150e36 100644 --- a/src/engines/aflengine.rs +++ b/src/engines/aflengine.rs @@ -1,6 +1,6 @@ use std::time; -use crate::engines::Engine; +use crate::engines::Evaluator; use crate::executors::Executor; use crate::feedbacks::Feedback; use crate::inputs::Input; diff --git a/src/engines/mod.rs b/src/engines/mod.rs index 415dab106a..3aa345f96b 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -1,16 +1,160 @@ -pub mod aflengine; - use crate::corpus::testcase::Testcase; +use crate::corpus::Corpus; +use crate::executors::Executor; +use crate::feedbacks::Feedback; use crate::inputs::Input; +use crate::stages::Stage; use crate::AflError; use std::cell::RefCell; use std::rc::Rc; -pub trait Engine<'a, I> +pub trait Evaluator where I: Input, { - fn execute(&mut self, input: &mut I, entry: Rc>>) - -> Result; + fn evaluate_input( + &mut self, + input: &mut I, + entry: Rc>>, + ) -> Result; +} + +pub trait Engine<'a, I, C, E>: Evaluator +where + I: Input, + C: Corpus, + E: Executor, +{ + fn feedbacks(&self) -> &Vec>>; + + fn feedbacks_mut(&mut self) -> &mut Vec>>; + + fn add_feedback(&mut self, feedback: Box>) { + self.feedbacks_mut().push(feedback); + } + + fn stages(&self) -> &Vec>>; + + fn stages_mut(&mut self) -> &mut Vec>>; + + fn add_stage(&mut self, stage: Box>) { + self.stages_mut().push(stage); + } + + fn corpus(&self) -> &C; + + fn corpus_mut(&mut self) -> &mut C; + + fn executor(&self) -> &E; + + fn executor_mut(&mut self) -> &mut E; + + fn fuzz_one(&mut self) -> Result<(), AflError> { + let entry = self.corpus_mut().get()?; + for stage in self.stages_mut() { + stage.perform(entry.clone())?; + } + Ok(()) + } + + fn evaluate_input_engine( + &mut self, + input: &mut I, + entry: Rc>>, + ) -> Result { + { + self.executor_mut().reset_observers()?; + // self.executor_mut().place_input(Box::new(input))?; + + self.executor_mut().run_target()?; + + self.executor_mut().post_exec_observers()?; + } + + // TODO new method for this shit + let mut new_entry: Option>>> = None; // lazy init + let mut rate_acc = 0; + for feedback in self.feedbacks_mut() { + let (rate, meta) = feedback.is_interesting(self.executor_mut()); + rate_acc += rate; + if let Some(m) = meta { + //if new_entry.is_none() { + new_entry = Some(Rc::new(RefCell::new(Testcase::::new(input.clone())))); + //} + new_entry + .unwrap() + .borrow_mut() + .add_metadata("test".to_string(), m); + } + } + + Ok(true) + } +} + +pub struct DefaultEngine<'a, I, C, E> +where + I: Input, + C: Corpus, + E: Executor, +{ + feedbacks: Vec>>, + stages: Vec>>, + executor: &'a mut E, + corpus: &'a mut C, +} + +impl<'a, I, C, E> Evaluator for DefaultEngine<'a, I, C, E> +where + I: Input, + C: Corpus, + E: Executor, +{ + fn evaluate_input( + &mut self, + input: &mut I, + entry: Rc>>, + ) -> Result { + self.evaluate_input_engine(input, entry) + } +} + +impl<'a, I, C, E> Engine<'a, I, C, E> for DefaultEngine<'a, I, C, E> +where + I: Input, + C: Corpus, + E: Executor, +{ + fn feedbacks(&self) -> &Vec>> { + &self.feedbacks + } + + fn feedbacks_mut(&mut self) -> &mut Vec>> { + &mut self.feedbacks + } + + fn stages(&self) -> &Vec>> { + &self.stages + } + + fn stages_mut(&mut self) -> &mut Vec>> { + &mut self.stages + } + + fn corpus(&self) -> &C { + self.corpus + } + + fn corpus_mut(&mut self) -> &mut C { + self.corpus + } + + fn executor(&self) -> &E { + self.executor + } + + fn executor_mut(&mut self) -> &mut E { + self.executor + } } diff --git a/src/executors/inmemory.rs b/src/executors/inmemory.rs index dc6afca1c6..a4c9d3adad 100644 --- a/src/executors/inmemory.rs +++ b/src/executors/inmemory.rs @@ -193,7 +193,6 @@ mod tests { use crate::inputs::Input; use crate::observers::Observer; use crate::AflError; - use std::any::Any; #[derive(Clone)] struct NopInput {} diff --git a/src/feedbacks/mod.rs b/src/feedbacks/mod.rs index 683565b717..dfc92aa7e7 100644 --- a/src/feedbacks/mod.rs +++ b/src/feedbacks/mod.rs @@ -1,6 +1,6 @@ extern crate num; -use crate::corpus::Testcase; +use crate::corpus::{Testcase, TestcaseMetadata}; use crate::executors::Executor; use crate::inputs::Input; use crate::observers::MapObserver; @@ -14,9 +14,13 @@ where I: Input, { /// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55) - fn is_interesting(&mut self, executor: &dyn Executor, entry: &Testcase) -> u8; + fn is_interesting( + &mut self, + executor: &dyn Executor, + ) -> (u32, Option>); } +/// A Reducer function is used to aggregate values for the novelty search pub trait Reducer where T: Integer + Copy + 'static, @@ -86,7 +90,10 @@ where O: MapObserver, I: Input, { - fn is_interesting(&mut self, _executor: &dyn Executor, _entry: &Testcase) -> u8 { + fn is_interesting( + &mut self, + _executor: &dyn Executor, + ) -> (u32, Option>) { let mut interesting = 0; // TODO: impl. correctly, optimize @@ -101,11 +108,11 @@ where *history = reduced; interesting += 25; if interesting >= 250 { - return 255; + return (255, None); } } } - interesting + (interesting, None) } } diff --git a/src/stages/mod.rs b/src/stages/mod.rs index b589e05871..4b6a71f0ca 100644 --- a/src/stages/mod.rs +++ b/src/stages/mod.rs @@ -1,25 +1,25 @@ pub mod mutational; use crate::corpus::Testcase; -use crate::engines::Engine; +use crate::engines::Evaluator; use crate::inputs::Input; use crate::AflError; use std::cell::RefCell; use std::rc::Rc; -pub trait HasEngine<'a, I> +pub trait HasEvaluator where I: Input, { - type E: Engine<'a, I>; + type E: Evaluator; - fn engine(&self) -> &Self::E; + fn eval(&self) -> &Self::E; - fn engine_mut(&mut self) -> &mut Self::E; + fn eval_mut(&mut self) -> &mut Self::E; } -pub trait Stage<'a, I>: HasEngine<'a, I> +pub trait Stage<'a, I>: HasEvaluator where I: Input, { diff --git a/src/stages/mutational.rs b/src/stages/mutational.rs index ec36c60133..cdad856d23 100644 --- a/src/stages/mutational.rs +++ b/src/stages/mutational.rs @@ -1,8 +1,8 @@ use crate::corpus::testcase::Testcase; -use crate::engines::Engine; +use crate::engines::Evaluator; use crate::inputs::Input; use crate::mutators::Mutator; -use crate::stages::{HasEngine, Stage}; +use crate::stages::{HasEvaluator, Stage}; use crate::utils::{HasRand, Rand}; use crate::AflError; @@ -36,7 +36,7 @@ where m.mutate(&mut input, i as i32)?; } - let interesting = self.engine_mut().execute(&mut input, entry.clone())?; + let interesting = self.eval_mut().evaluate_input(&mut input, entry.clone())?; for m in self.mutators_mut() { m.post_exec(interesting, i as i32)?; @@ -52,10 +52,10 @@ pub struct DefaultMutationalStage<'a, I, R, E> where I: Input, R: Rand, - E: Engine<'a, I>, + E: Evaluator, { rand: &'a mut R, - engine: &'a mut E, + eval: &'a mut E, mutators: Vec>>, } @@ -63,7 +63,7 @@ impl<'a, I, R, E> HasRand for DefaultMutationalStage<'a, I, R, E> where I: Input, R: Rand, - E: Engine<'a, I>, + E: Evaluator, { type R = R; @@ -75,20 +75,20 @@ where } } -impl<'a, I, R, E> HasEngine<'a, I> for DefaultMutationalStage<'a, I, R, E> +impl<'a, I, R, E> HasEvaluator for DefaultMutationalStage<'a, I, R, E> where I: Input, R: Rand, - E: Engine<'a, I>, + E: Evaluator, { type E = E; - fn engine(&self) -> &Self::E { - self.engine + fn eval(&self) -> &Self::E { + self.eval } - fn engine_mut(&mut self) -> &mut Self::E { - self.engine + fn eval_mut(&mut self) -> &mut Self::E { + self.eval } } @@ -96,7 +96,7 @@ impl<'a, I, R, E> MutationalStage<'a, I> for DefaultMutationalStage<'a, I, R, E> where I: Input, R: Rand, - E: Engine<'a, I>, + E: Evaluator, { fn mutators(&self) -> &Vec>> { &self.mutators @@ -111,7 +111,7 @@ impl<'a, I, R, E> Stage<'a, I> for DefaultMutationalStage<'a, I, R, E> where I: Input, R: Rand, - E: Engine<'a, I>, + E: Evaluator, { fn perform(&mut self, entry: Rc>>) -> Result<(), AflError> { self.perform_mutational(entry) @@ -122,12 +122,12 @@ impl<'a, I, R, E> DefaultMutationalStage<'a, I, R, E> where I: Input, R: Rand, - E: Engine<'a, I>, + E: Evaluator, { - pub fn new(rand: &'a mut R, engine: &'a mut E) -> Self { + pub fn new(rand: &'a mut R, eval: &'a mut E) -> Self { DefaultMutationalStage { rand: rand, - engine: engine, + eval: eval, mutators: vec![], } }