diff --git a/src/corpus/mod.rs b/src/corpus/mod.rs index aa43f1d628..22e88c0c23 100644 --- a/src/corpus/mod.rs +++ b/src/corpus/mod.rs @@ -6,29 +6,30 @@ use crate::inputs::Input; use crate::AflError; use std::path::PathBuf; +use std::marker::PhantomData; -pub trait HasEntriesVec { +pub trait HasEntriesVec where I: Input { /// Get the entries vector field - fn entries(&self) -> &Vec>>; + fn entries(&self) -> &Vec>>; /// Get the entries vector field (mutable) - fn entries_mut(&mut self) -> &mut Vec>>; + fn entries_mut(&mut self) -> &mut Vec>>; } /// Corpus with all current testcases -pub trait Corpus : HasEntriesVec + HasRand { +pub trait Corpus : HasEntriesVec + HasRand where I: Input { /// Returns the number of elements fn count(&self) -> usize { self.entries().len() } /// Add an entry to the corpus - fn add(&mut self, mut entry: Box>) { + fn add(&mut self, mut entry: Box>) { self.entries_mut().push(entry); } /// Removes an entry from the corpus, returning it if it was present. - fn remove(&mut self, entry: &Testcase) -> Option>> { + fn remove(&mut self, entry: &Testcase) -> Option>> { let mut i: usize = 0; let mut found = false; for x in self.entries() { @@ -45,46 +46,49 @@ pub trait Corpus : HasEntriesVec + HasRand Result<&Box>, AflError> { - let id = self.rand_mut().below(self.entries().len() as u64) as usize; + fn random_entry(&mut self) -> Result<&Box>, 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()) } /// Gets the next entry (random by default) - fn get(&mut self) -> Result<&Box>, AflError> { + fn get(&mut self) -> Result<&Box>, AflError> { self.random_entry() } } -pub struct InMemoryCorpus<'a, InputT: Input, RandT: Rand> { - rand: &'a mut RandT, - entries: Vec>>, +pub struct InMemoryCorpus<'a, I, R> where I: Input, R: Rand { + rand: &'a mut R, + entries: Vec>> } -impl HasEntriesVec for InMemoryCorpus<'_, InputT, RandT> { - fn entries(&self) -> &Vec>> { +impl HasEntriesVec for InMemoryCorpus<'_, I, R> where I: Input, R: Rand { + fn entries(&self) -> &Vec>> { &self.entries } - fn entries_mut(&mut self) -> &mut Vec>>{ + fn entries_mut(&mut self) -> &mut Vec>>{ &mut self.entries } } -impl HasRand for InMemoryCorpus<'_, InputT, RandT> { - fn rand(&self) -> &Box { +impl HasRand for InMemoryCorpus<'_, I, R> where I: Input, R: Rand { + type R = R; + + fn rand(&self) -> &Self::R { &self.rand } - fn rand_mut(&mut self) -> &mut Box { + fn rand_mut(&mut self) -> &mut Self::R { &mut self.rand } } -impl Corpus for InMemoryCorpus<'_, InputT, RandT> { +impl Corpus for InMemoryCorpus<'_, I, R> where I: Input, R: Rand { // Just use the default implementation } -impl InMemoryCorpus<'_, InputT, RandT> { - pub fn new<'a>(rand: &'a mut RandT) -> Self { +impl<'a, I, R> InMemoryCorpus<'a, I, R> where I: Input, R: Rand { + pub fn new(rand: &'a mut R) -> Self { InMemoryCorpus { rand: rand, entries: vec![], @@ -92,38 +96,40 @@ impl InMemoryCorpus<'_, InputT, RandT> { } } -pub struct OnDiskCorpus<'a, InputT: Input, RandT: Rand> { - rand: &'a mut RandT, - entries: Vec>>, +pub struct OnDiskCorpus<'a, I, R> where I: Input, R: Rand { + rand: &'a mut R, + entries: Vec>>, dir_path: PathBuf, } -impl HasEntriesVec for OnDiskCorpus<'_, InputT, RandT> { - fn entries(&self) -> &Vec>> { +impl HasEntriesVec for OnDiskCorpus<'_, I, R> where I: Input, R: Rand { + fn entries(&self) -> &Vec>> { &self.entries } - fn entries_mut(&mut self) -> &mut Vec>>{ + fn entries_mut(&mut self) -> &mut Vec>>{ &mut self.entries } } -impl HasRand for OnDiskCorpus<'_, InputT, RandT> { - fn rand(&self) -> &Box { +impl HasRand for OnDiskCorpus<'_, I, R> where I: Input, R: Rand { + type R = R; + + fn rand(&self) -> &Self::R { &self.rand } - fn rand_mut(&mut self) -> &mut Box { + fn rand_mut(&mut self) -> &mut Self::R { &mut self.rand } } -impl Corpus for OnDiskCorpus<'_, InputT, RandT> { +impl Corpus for OnDiskCorpus<'_, I, R> where I: Input, R: Rand { /// Add an entry and save it to disk - fn add(&mut self, mut entry: Box>) { - if entry.filename() == None { + fn add(&mut self, mut entry: Box>) { + if *entry.filename() == None { // TODO walk entry metadatas to ask for pices of filename (e.g. :havoc in AFL) let filename = &(String::from("id:") + &self.entries.len().to_string()); let filename = self.dir_path.join(filename); - entry.filename_mut() = filename; + *entry.filename_mut() = Some(filename); } self.entries.push(entry); } @@ -131,8 +137,8 @@ impl Corpus for OnDiskCorpus<'_, Inpu // TODO save and remove files, cache, etc..., ATM use just InMemoryCorpus } -impl OnDiskCorpus<'_, InputT, RandT> { - pub fn new<'a>(rand: &'a mut RandT, dir_path: PathBuf) -> Self { +impl<'a, I, R> OnDiskCorpus<'a, I, R> where I: Input, R: Rand { + pub fn new(rand: &'a mut R, dir_path: PathBuf) -> Self { OnDiskCorpus { dir_path: dir_path, entries: vec![], @@ -142,50 +148,72 @@ impl OnDiskCorpus<'_, InputT, RandT> { } /// A Queue-like corpus, wrapping an existing Corpus instance -pub struct QueueCorpus<'a, InputT: Input, RandT: Rand, CorpusT: Corpus> { - corpus: CorpusT, +pub struct QueueCorpus where I: Input, C: Corpus { + corpus: C, + phantom: PhantomData, pos: usize, cycles: u64, } -impl<'a, InputT: Input, RandT: Rand, CorpusT: Corpus> Corpus for QueueCorpus<'_, InputT, RandT, CorpusT> { +impl<'a, I, C> HasEntriesVec for QueueCorpus where I: Input, C: Corpus { + fn entries(&self) -> &Vec>> { + self.corpus.entries() + } + fn entries_mut(&mut self) -> &mut Vec>>{ + self.corpus.entries_mut() + } +} + +impl<'a, I, C> HasRand for QueueCorpus where I: Input, C: Corpus { + type R = C::R; + + fn rand(&self) -> &Self::R { + self.corpus.rand() + } + fn rand_mut(&mut self) -> &mut Self::R { + self.corpus.rand_mut() + } +} + +impl<'a, I, C> Corpus for QueueCorpus where I: Input, C: Corpus { /// Returns the number of elements fn count(&self) -> usize { self.corpus.count() } - fn add(&mut self, entry: Box>) { + fn add(&mut self, entry: Box>) { self.corpus.add(entry); } /// Removes an entry from the corpus, returning it if it was present. - fn remove(&mut self, entry: &Testcase) -> Option>> { + fn remove(&mut self, entry: &Testcase) -> Option>> { self.corpus.remove(entry) } /// Gets a random entry - fn random_entry(&mut self) -> Result<&Box>, AflError> { + fn random_entry(&mut self) -> Result<&Box>, AflError> { self.corpus.random_entry() } /// Gets the next entry - fn get(&mut self) -> Result<&Box>, AflError> { - if self.count() == 0 { + fn get(&mut self) -> Result<&Box>, AflError> { + if self.corpus.count() == 0 { return Err(AflError::Empty("Testcases".to_string())); } self.pos = self.pos + 1; - if self.pos >= self.count() { + if self.pos >= self.corpus.count() { self.cycles = self.cycles + 1; self.pos = 0; } - Ok(self.corpus.entries.get_mut(self.pos).unwrap()) + Ok(self.corpus.entries_mut().get_mut(self.pos).unwrap()) } } -impl<'a, InputT: Input, RandT: Rand, CorpusT: Corpus> QueueCorpus<'_, InputT, RandT, CorpusT> { - pub fn new(corpus: CorpusT) -> Self { - QueueCorpus { +impl<'a, I, C> QueueCorpus where I: Input, C: Corpus { + pub fn new(corpus: C) -> Self { + QueueCorpus:: { corpus: corpus, + phantom: PhantomData, cycles: 0, pos: 0, } @@ -217,10 +245,10 @@ mod tests { let mut q = QueueCorpus::new(OnDiskCorpus::new(&mut rand, PathBuf::from("fancy/path"))); let i = Box::new(BytesInput::new(vec![0; 4])); let mut t = Box::new(Testcase::new(i)); - t.set_filename(PathBuf::from("fancyfile")); + *t.filename_mut() = Some(PathBuf::from("fancyfile")); q.add(t); - let filename = q.get().unwrap().get_filename().unwrap().to_owned(); - assert_eq!(filename, q.get().unwrap().get_filename().unwrap().to_owned()); + let filename = q.get().unwrap().filename().as_ref().unwrap().to_owned(); + assert_eq!(filename, q.get().unwrap().filename().as_ref().unwrap().to_owned()); assert_eq!(filename, PathBuf::from("fancy/path/fancyfile")); } } diff --git a/src/corpus/testcase.rs b/src/corpus/testcase.rs index 65328db237..1a37139aec 100644 --- a/src/corpus/testcase.rs +++ b/src/corpus/testcase.rs @@ -7,15 +7,15 @@ use std::path::PathBuf; pub trait TestcaseMetadata {} /* -pub trait TestcaseTrait { +pub trait TestcaseTrait { /// Make sure to return a valid input instance loading it from disk if not in memory - fn load_input(&mut self) -> Result<&Box, AflError>; + fn load_input(&mut self) -> Result<&Box, AflError>; /// Get the input, if any - fn input(&self) -> &Option>; + fn input(&self) -> &Option>; /// Get the input, if any (mutable) - fn input_mut(&mut self) -> &mut Option>; + fn input_mut(&mut self) -> &mut Option>; /// Get the filename, if any fn filename(&self) -> &Option; @@ -29,38 +29,44 @@ pub trait TestcaseTrait { */ #[derive(Default)] -pub struct Testcase { - input: Option>, +pub struct Testcase where I: Input { + input: Option>, filename: Option, metadatas: HashMap>, } -impl Testcase { +impl Testcase where I: Input { /// Make sure to return a valid input instance loading it from disk if not in memory - pub fn load_input(&mut self) -> Result<&Box, AflError> { + pub fn load_input(&mut self) -> Result<&Box, AflError> { // TODO: Implement cache to disk self.input.as_ref().ok_or(AflError::NotImplemented("load_input".to_string())) } /// Get the input, if any - pub fn input(&self) -> &Option> { + pub fn input(&self) -> &Option> { &self.input } - /// Get the input, if any (mutable) - pub fn input_mut(&mut self) -> &mut Option> { + pub fn input_mut(&mut self) -> &mut Option> { &mut self.input } + /// Set the input + pub fn set_input(&mut self, input: Option>) { + self.input = input; + } /// Get the filename, if any pub fn filename(&self) -> &Option { &self.filename } - /// Get the filename, if any (mutable) - pub fn filename_mut(&mut self, filename: PathBuf) -> &mut Option { + pub fn filename_mut(&mut self) -> &mut Option { &mut self.filename } + /// Set the filename + pub fn set_filename(&mut self, filename: Option) { + self.filename = filename; + } /// Get all the metadatas into an HashMap pub fn metadatas(&mut self) -> &mut HashMap> { @@ -68,7 +74,7 @@ impl Testcase { } /// Create a new DefaultTestcase instace given an input - pub fn new(input: Box) -> Self { + pub fn new(input: Box) -> Self { Testcase { input: Some(input), filename: None, @@ -77,10 +83,10 @@ impl Testcase { } /// Create a new DefaultTestcase instace given an input and a filename - pub fn new_with_filename(input: Box, filename: &PathBuf) -> Self { + pub fn new_with_filename(input: Box, filename: PathBuf) -> Self { Testcase { input: Some(input), - filename: filename, + filename: Some(filename), metadatas: HashMap::default(), } } diff --git a/src/engines/aflengine.rs b/src/engines/aflengine.rs index c46199be04..bf8fa0080c 100644 --- a/src/engines/aflengine.rs +++ b/src/engines/aflengine.rs @@ -1,18 +1,19 @@ use std::time; use crate::engines::Engine; +use crate::inputs::Input; use crate::executors::Executor; use crate::feedbacks::Feedback; use crate::monitors::Monitor; use crate::stages::Stage; use crate::utils::Rand; -pub struct AflEngine<'a> { +pub struct AflEngine<'a, InputT: Input> { pub rand: &'a mut dyn Rand, - pub feedbacks: Vec>, + pub feedbacks: Vec>>, - pub stages: Vec>, - pub current_stage: &'a Box, + pub stages: Vec>>, + pub current_stage: &'a Box>, pub executor: Box, @@ -25,4 +26,4 @@ pub struct AflEngine<'a> { pub monitors: Vec>, } -impl Engine<'_> for AflEngine<'_> {} +impl Engine<'_> for AflEngine<'_, InputT> {} diff --git a/src/feedbacks/mod.rs b/src/feedbacks/mod.rs index 9eca463d21..6aaf394287 100644 --- a/src/feedbacks/mod.rs +++ b/src/feedbacks/mod.rs @@ -1,15 +1,22 @@ extern crate num; use crate::corpus::Testcase; +use crate::inputs::Input; use crate::executors::Executor; use crate::observers::MapObserver; use num::Integer; use std::marker::PhantomData; +pub trait Feedback { + /// 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; +} + +/* pub trait Feedback { /// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55) - fn is_interesting(&mut self, executor: &dyn Executor, entry: &dyn Testcase) -> u8; + fn is_interesting(&mut self, executor: &dyn Executor, entry: &Testcase) -> u8; } pub trait Reducer { @@ -69,3 +76,5 @@ impl<'a, MapT: Integer + Copy + 'static, ReducerT: Reducer> MapFeedback = MapFeedback>; #[allow(dead_code)] type MinMapFeedback = MapFeedback>; + +*/ \ No newline at end of file diff --git a/src/mutators/mod.rs b/src/mutators/mod.rs index f045fa1299..9bb40b727a 100644 --- a/src/mutators/mod.rs +++ b/src/mutators/mod.rs @@ -1,20 +1,30 @@ use crate::inputs::Input; -use crate::utils::{Rand, HasRand}; +use crate::utils::HasRand; use crate::corpus::Corpus; use crate::AflError; pub mod scheduled; pub use scheduled::{ComposedByMutations, ScheduledMutator, HavocBytesMutator}; -pub trait Mutator : HasRand { +pub trait HasOptionCorpus where I: Input { + type C : Corpus; + + /// Get the associated corpus, if any + fn corpus(&self) -> &Option>; + + /// Get the associated corpus, if any (mutable) + fn corpus_mut(&mut self) -> &mut Option>; + + /// Set the associated corpus + fn set_corpus(&mut self, corpus: Option>); +} + +pub trait Mutator : HasRand + HasOptionCorpus where I: Input { /// Mutate a given input - fn mutate(&mut self, input: &mut InputT, stage_idx: i32) -> Result<(), AflError>; + fn mutate(&mut self, 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> { Ok(()) } - - /// Get the associated corpus, if any - fn corpus(&mut self) -> &mut Option>>; } diff --git a/src/mutators/scheduled.rs b/src/mutators/scheduled.rs index cd26df644c..b2ff7f41e9 100644 --- a/src/mutators/scheduled.rs +++ b/src/mutators/scheduled.rs @@ -1,4 +1,4 @@ -use crate::mutators::Mutator; +use crate::mutators::{HasOptionCorpus, Mutator}; use crate::utils::{Rand, HasRand}; use crate::corpus::Corpus; use crate::inputs::{Input, HasBytesVec}; @@ -7,27 +7,27 @@ use crate::AflError; use std::marker::PhantomData; /// The generic function type that identifies mutations -type MutationFunction = fn(&mut MutatorT, &mut InputT) -> Result<(), AflError>; +type MutationFunction = fn(&mut M, &mut I) -> Result<(), AflError>; -pub trait ComposedByMutations { +pub trait ComposedByMutations where I: Input { /// 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 { - /// Computer the number of iterations used to apply stacked mutations - fn iterations(&mut self, _input: &InputT) -> u64 { +pub trait ScheduledMutator: Mutator + ComposedByMutations where I: Input { + /// Compute the number of iterations used to apply stacked mutations + fn iterations(&mut self, _input: &I) -> u64 { 1 << (1 + self.rand_mut().below(7)) } /// Get the next mutation to apply - fn schedule(&mut self, _input: &InputT) -> Result, AflError> { + fn schedule(&mut self, _input: &I) -> Result, AflError> { let count = self.mutations_count() as u64; if count == 0 { return Err(AflError::Empty("no mutations".to_string())); @@ -41,7 +41,7 @@ pub trait ScheduledMutator: Mutator /// New default implementation for mutate /// Implementations must forward mutate() to this method - fn scheduled_mutate(&mut self, input: &mut InputT, _stage_idx: i32) -> Result<(), AflError> { + fn scheduled_mutate(&mut self, input: &mut I, _stage_idx: i32) -> Result<(), AflError> { let num = self.iterations(input); for _ in 0..num { self.schedule(input)?(self, input)?; @@ -50,23 +50,47 @@ pub trait ScheduledMutator: Mutator } } -pub struct DefaultScheduledMutator { - rand: Box, - corpus: Option>>, - mutations: Vec> +pub struct DefaultScheduledMutator<'a, I, R, C> where I: Input, R: Rand, C: Corpus { + rand: &'a mut R, + corpus: Option>, + mutations: Vec> } -impl HasRand for DefaultScheduledMutator { - fn rand(&self) -> &Box { +impl<'a, I, R, C> HasRand for DefaultScheduledMutator<'_, I, R, C> where I: Input, R: Rand, C: Corpus { + type R = R; + + fn rand(&self) -> &Self::R { &self.rand } - fn rand_mut(&mut self) -> &mut Box { + fn rand_mut(&mut self) -> &mut Self::R { &mut self.rand } } -impl ComposedByMutations for DefaultScheduledMutator { - fn mutation_by_idx(&self, index: usize) -> Result, AflError> { +impl HasOptionCorpus for DefaultScheduledMutator<'_, I, R, C> where I: Input, R: Rand, C: Corpus { + type C = C; + + fn corpus(&self) -> &Option> { + &self.corpus + } + + fn corpus_mut(&mut self) -> &mut Option> { + &mut self.corpus + } + + fn set_corpus(&mut self, corpus: Option>) { + self.corpus = corpus + } +} + +impl<'a, I, R, C> Mutator for DefaultScheduledMutator<'_, I, R, C> where I: Input, R: Rand, C: Corpus { + fn mutate(&mut self, input: &mut I, _stage_idx: i32) -> Result<(), AflError> { + self.scheduled_mutate(input, _stage_idx) + } +} + +impl<'a, I, R, C> ComposedByMutations for DefaultScheduledMutator<'_, I, R, C> where I: Input, R: Rand, C: Corpus { + fn mutation_by_idx(&self, index: usize) -> Result, AflError> { if index >= self.mutations.len() { return Err(AflError::Unknown("oob".to_string())); } @@ -77,28 +101,18 @@ impl ComposedByMutations for DefaultSchedul 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<'a, I, R, C> ScheduledMutator for DefaultScheduledMutator<'_, I, R, C> where I: Input, R: Rand, C: Corpus { // Just use the default methods } -impl Mutator for DefaultScheduledMutator { - fn mutate(&mut self, input: &mut InputT, _stage_idx: i32) -> Result<(), AflError> { - self.scheduled_mutate(input, _stage_idx) - } - - fn corpus(&mut self) -> &mut Option> { - &mut self.corpus - } -} - -impl DefaultScheduledMutator { +impl<'a, I, R, C> DefaultScheduledMutator<'a, I, R, C> where I: Input, R: Rand, C: Corpus { /// Create a new DefaultScheduledMutator instance without mutations and corpus - pub fn new(rand: Box) -> Self { + pub fn new(rand: &'a mut R) -> Self { DefaultScheduledMutator { rand: rand, corpus: None, @@ -107,7 +121,7 @@ impl DefaultScheduledMutator { } /// Create a new DefaultScheduledMutator instance specifying mutations and corpus too - pub fn new_all(rand: Box, corpus: Option>, mutations: Vec>) -> Self { + pub fn new_all(rand: &'a mut R, corpus: Option>, mutations: Vec>) -> Self { DefaultScheduledMutator { rand: rand, corpus: corpus, @@ -117,56 +131,70 @@ impl DefaultScheduledMutator { } /// Bitflip mutation for inputs with a bytes vector -pub fn mutation_bitflip, InputT: Input + HasBytesVec, RandT: Rand>(mutator: &mut MutatorT, input: &mut InputT) -> Result<(), AflError> { +pub fn mutation_bitflip(mutator: &mut M, input: &mut I) -> Result<(), AflError> where M: Mutator, I: Input + HasBytesVec { let bit = mutator.rand_mut().below(input.bytes().len() as u64) as usize; input.bytes_mut()[bit >> 3] ^= (128 >> (bit & 7)) as u8; Ok(()) } /// Schedule some selected byte level mutations given a ScheduledMutator type -pub struct HavocBytesMutator> { - scheduled: ScheduledMutatorT, - _phantom: PhantomData +pub struct HavocBytesMutator where I: Input + HasBytesVec, S: ScheduledMutator { + scheduled: S, + phantom: PhantomData } -impl> Mutator for HavocBytesMutator { - fn mutate(&mut self, input: &mut InputT, stage_idx: i32) -> Result<(), AflError> { - self.scheduled.mutate(input, stage_idx) - } +impl HasRand for HavocBytesMutator where I: Input + HasBytesVec, S: ScheduledMutator { + type R = S::R; - fn corpus(&mut self) -> &mut Option> { - self.scheduled.corpus() - } -} - -impl> HasRand for HavocBytesMutator { - fn rand(&self) -> &Box { + fn rand(&self) -> &Self::R { self.scheduled.rand() } - fn rand_mut(&mut self) -> &mut Box { + fn rand_mut(&mut self) -> &mut Self::R { self.scheduled.rand_mut() } } -impl> HavocBytesMutator { +impl HasOptionCorpus for HavocBytesMutator where I: Input + HasBytesVec, S: ScheduledMutator { + type C = S::C; + + fn corpus(&self) -> &Option> { + self.scheduled.corpus() + } + + fn corpus_mut(&mut self) -> &mut Option> { + self.scheduled.corpus_mut() + } + + fn set_corpus(&mut self, corpus: Option>) { + self.scheduled.set_corpus(corpus) + } +} + +impl Mutator for HavocBytesMutator where I: Input + HasBytesVec, S: ScheduledMutator { + fn mutate(&mut self, input: &mut I, stage_idx: i32) -> Result<(), AflError> { + self.scheduled.mutate(input, stage_idx) + } +} + +impl HavocBytesMutator where I: Input + HasBytesVec, S: ScheduledMutator { /// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap - pub fn new(mut scheduled: ScheduledMutatorT) -> Self { + pub fn new(mut scheduled: S) -> Self { scheduled.add_mutation(mutation_bitflip); HavocBytesMutator { scheduled: scheduled, - _phantom: PhantomData + phantom: PhantomData } } } -impl HavocBytesMutator> { +impl<'a, I, R, C> HavocBytesMutator> where I: Input + HasBytesVec, R: Rand, C: Corpus { /// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator - pub fn new_default(rand: Box) -> Self { - let mut scheduled = DefaultScheduledMutator::new(rand); + pub fn new_default(rand: &'a mut R) -> Self { + let mut scheduled = DefaultScheduledMutator::<'a, I, R, C>::new(rand); scheduled.add_mutation(mutation_bitflip); HavocBytesMutator { scheduled: scheduled, - _phantom: PhantomData + phantom: PhantomData } } } \ No newline at end of file diff --git a/src/stages/mod.rs b/src/stages/mod.rs index c4f3e4962d..f24ddac29c 100644 --- a/src/stages/mod.rs +++ b/src/stages/mod.rs @@ -2,6 +2,6 @@ use crate::corpus::Testcase; use crate::inputs::Input; use crate::AflError; /// Stages -pub trait Stage { - fn perform(&mut self, input: &dyn Input, entry: &mut Testcase) -> Result<(), AflError>; +pub trait Stage { + fn perform(&mut self, input: &dyn Input, entry: &mut Testcase) -> Result<(), AflError>; } diff --git a/src/utils.rs b/src/utils.rs index ed4e927d21..ee32d74e57 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -40,12 +40,14 @@ pub trait Rand: Debug { } /// Has a Rand box field -pub trait HasRand { +pub trait HasRand { + type R : Rand; + /// Get the hold Rand instance - fn rand(&self) -> &Box; + fn rand(&self) -> &Self::R; /// Get the hold Rand instance (mutable) - fn rand_mut(&mut self) -> &mut Box; + fn rand_mut(&mut self) -> &mut Self::R; } const HASH_CONST: u64 = 0xa5b35705;