moved to rc'd rand

This commit is contained in:
Dominik Maier 2020-11-06 02:44:35 +01:00
parent 76e36ab4d8
commit 6ceb02be17
5 changed files with 97 additions and 69 deletions

View File

@ -58,7 +58,7 @@ where
/// Gets a random entry /// Gets a random entry
fn random_entry(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> { fn random_entry(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
let len = { self.entries().len() }; let len = { self.entries().len() };
let id = self.rand_mut().below(len as u64) as usize; let id = self.rand_below(len as u64) as usize;
Ok(self.entries()[id].clone()) Ok(self.entries()[id].clone())
} }
@ -68,16 +68,16 @@ where
} }
} }
pub struct InMemoryCorpus<'a, I, R> pub struct InMemoryCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
rand: &'a mut R, rand: Rc<RefCell<R>>,
entries: Vec<Rc<RefCell<Testcase<I>>>>, entries: Vec<Rc<RefCell<Testcase<I>>>>,
} }
impl<I, R> HasEntriesVec<I> for InMemoryCorpus<'_, I, R> impl<I, R> HasEntriesVec<I> for InMemoryCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
@ -90,22 +90,19 @@ where
} }
} }
impl<I, R> HasRand for InMemoryCorpus<'_, I, R> impl<I, R> HasRand for InMemoryCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
type R = R; type R = R;
fn rand(&self) -> &Self::R { fn rand(&self) -> &Rc<RefCell<Self::R>> {
&self.rand &self.rand
} }
fn rand_mut(&mut self) -> &mut Self::R {
&mut self.rand
}
} }
impl<I, R> Corpus<I> for InMemoryCorpus<'_, I, R> impl<I, R> Corpus<I> for InMemoryCorpus< I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
@ -113,30 +110,30 @@ where
// Just use the default implementation // Just use the default implementation
} }
impl<'a, I, R> InMemoryCorpus<'a, I, R> impl<I, R> InMemoryCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
pub fn new(rand: &'a mut R) -> Self { pub fn new(rand: &Rc<RefCell<R>>) -> Self {
InMemoryCorpus { InMemoryCorpus {
rand: rand, rand: Rc::clone(rand),
entries: vec![], entries: vec![],
} }
} }
} }
pub struct OnDiskCorpus<'a, I, R> pub struct OnDiskCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
rand: &'a mut R, rand: Rc<RefCell<R>>,
entries: Vec<Rc<RefCell<Testcase<I>>>>, entries: Vec<Rc<RefCell<Testcase<I>>>>,
dir_path: PathBuf, dir_path: PathBuf,
} }
impl<I, R> HasEntriesVec<I> for OnDiskCorpus<'_, I, R> impl<I, R> HasEntriesVec<I> for OnDiskCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
@ -149,22 +146,19 @@ where
} }
} }
impl<I, R> HasRand for OnDiskCorpus<'_, I, R> impl<I, R> HasRand for OnDiskCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
type R = R; type R = R;
fn rand(&self) -> &Self::R { fn rand(&self) -> &Rc<RefCell<Self::R>> {
&self.rand &self.rand
} }
fn rand_mut(&mut self) -> &mut Self::R {
&mut self.rand
}
} }
impl<I, R> Corpus<I> for OnDiskCorpus<'_, I, R> impl<I, R> Corpus<I> for OnDiskCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
@ -183,16 +177,16 @@ where
// TODO save and remove files, cache, etc..., ATM use just InMemoryCorpus // TODO save and remove files, cache, etc..., ATM use just InMemoryCorpus
} }
impl<'a, I, R> OnDiskCorpus<'a, I, R> impl<I, R> OnDiskCorpus<I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
pub fn new(rand: &'a mut R, dir_path: PathBuf) -> Self { pub fn new(rand: &Rc<RefCell<R>>, dir_path: PathBuf) -> Self {
OnDiskCorpus { OnDiskCorpus {
rand: Rc::clone(rand),
dir_path: dir_path, dir_path: dir_path,
entries: vec![], entries: vec![],
rand: rand,
} }
} }
} }
@ -229,12 +223,9 @@ where
{ {
type R = C::R; type R = C::R;
fn rand(&self) -> &Self::R { fn rand(&self) -> &Rc<RefCell<Self::R>> {
self.corpus.rand() self.corpus.rand()
} }
fn rand_mut(&mut self) -> &mut Self::R {
self.corpus.rand_mut()
}
} }
impl<'a, I, C> Corpus<I> for QueueCorpus<I, C> impl<'a, I, C> Corpus<I> for QueueCorpus<I, C>
@ -313,8 +304,8 @@ mod tests {
#[test] #[test]
fn test_queuecorpus() { fn test_queuecorpus() {
let mut rand = Xoshiro256StarRand::new(); let rand = Xoshiro256StarRand::new_rc();
let mut q = QueueCorpus::new(OnDiskCorpus::new(&mut rand, PathBuf::from("fancy/path"))); let mut q = QueueCorpus::new(OnDiskCorpus::new(&rand, PathBuf::from("fancy/path")));
let i = BytesInput::new(vec![0; 4]); let i = BytesInput::new(vec![0; 4]);
let t = Rc::new(RefCell::new(Testcase::new_with_filename( let t = Rc::new(RefCell::new(Testcase::new_with_filename(
i, i,

View File

@ -175,7 +175,6 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::corpus::testcase::Testcase;
use crate::corpus::InMemoryCorpus; use crate::corpus::InMemoryCorpus;
use crate::engines::{DefaultEngine, Engine}; use crate::engines::{DefaultEngine, Engine};
use crate::executors::inmemory::InMemoryExecutor; use crate::executors::inmemory::InMemoryExecutor;
@ -185,24 +184,22 @@ mod tests {
use crate::utils::Xoshiro256StarRand; use crate::utils::Xoshiro256StarRand;
use std::cell::RefCell; use std::cell::RefCell;
use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
fn harness<I>(_executor: &dyn Executor<I>, buf: &[u8]) -> ExitKind { fn harness<I>(_executor: &dyn Executor<I>, _buf: &[u8]) -> ExitKind {
ExitKind::Ok ExitKind::Ok
} }
#[test] #[test]
fn test_engine() { fn test_engine() {
let mut rand = Xoshiro256StarRand::new(); let rand = Rc::new(RefCell::new(Xoshiro256StarRand::new()));
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&mut rand); let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
let mut executor = InMemoryExecutor::new(harness); let mut executor = InMemoryExecutor::new(harness);
let mut engine = DefaultEngine::new(&mut corpus, &mut executor); let mut engine = DefaultEngine::new(&mut corpus, &mut executor);
let mut rand1 = Xoshiro256StarRand::new(); let mut stage = Box::new(DefaultMutationalStage::new(&rand, &mut engine));
let mut stage = Box::new(DefaultMutationalStage::new(&mut rand1, &mut engine));
engine.add_stage(stage); engine.add_stage(stage);
engine.fuzz_one().unwrap(); engine.fuzz_one().unwrap();
let mut stage1 = Box::new(DefaultMutationalStage::new(&mut rand1, &mut engine)); let mut stage1 = Box::new(DefaultMutationalStage::new(&rand, &mut engine));
engine.fuzz_one().unwrap(); engine.fuzz_one().unwrap();
} }
} }

View File

@ -5,6 +5,8 @@ use crate::utils::{HasRand, Rand};
use crate::AflError; use crate::AflError;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc;
use std::cell::RefCell;
/// The generic function type that identifies mutations /// The generic function type that identifies mutations
type MutationFunction<M, I> = fn(&mut M, &mut I) -> Result<(), AflError>; type MutationFunction<M, I> = fn(&mut M, &mut I) -> Result<(), AflError>;
@ -29,7 +31,7 @@ where
{ {
/// Compute the number of iterations used to apply stacked mutations /// Compute the number of iterations used to apply stacked mutations
fn iterations(&mut self, _input: &I) -> u64 { fn iterations(&mut self, _input: &I) -> u64 {
1 << (1 + self.rand_mut().below(7)) 1 << (1 + self.rand_below(7))
} }
/// Get the next mutation to apply /// Get the next mutation to apply
@ -40,7 +42,7 @@ where
} }
let idx; let idx;
{ {
idx = self.rand_mut().below(count) as usize; idx = self.rand().borrow_mut().below(count) as usize;
} }
self.mutation_by_idx(idx) self.mutation_by_idx(idx)
} }
@ -62,7 +64,7 @@ where
R: Rand, R: Rand,
C: Corpus<I>, C: Corpus<I>,
{ {
rand: &'a mut R, rand: Rc<RefCell<R>>,
corpus: Option<Box<C>>, corpus: Option<Box<C>>,
mutations: Vec<MutationFunction<Self, I>>, mutations: Vec<MutationFunction<Self, I>>,
} }
@ -75,12 +77,9 @@ where
{ {
type R = R; type R = R;
fn rand(&self) -> &Self::R { fn rand(&self) -> &Rc<RefCell<Self::R>> {
&self.rand &self.rand
} }
fn rand_mut(&mut self) -> &mut Self::R {
&mut self.rand
}
} }
impl<I, R, C> HasOptionCorpus<I> for DefaultScheduledMutator<'_, I, R, C> impl<I, R, C> HasOptionCorpus<I> for DefaultScheduledMutator<'_, I, R, C>
@ -153,9 +152,9 @@ where
C: Corpus<I>, C: Corpus<I>,
{ {
/// Create a new DefaultScheduledMutator instance without mutations and corpus /// Create a new DefaultScheduledMutator instance without mutations and corpus
pub fn new(rand: &'a mut R) -> Self { pub fn new(rand: &Rc<RefCell<R>>) -> Self {
DefaultScheduledMutator { DefaultScheduledMutator {
rand: rand, rand: Rc::clone(rand),
corpus: None, corpus: None,
mutations: vec![], mutations: vec![],
} }
@ -163,12 +162,12 @@ where
/// Create a new DefaultScheduledMutator instance specifying mutations and corpus too /// Create a new DefaultScheduledMutator instance specifying mutations and corpus too
pub fn new_all( pub fn new_all(
rand: &'a mut R, rand: &Rc<RefCell<R>>,
corpus: Option<Box<C>>, corpus: Option<Box<C>>,
mutations: Vec<MutationFunction<Self, I>>, mutations: Vec<MutationFunction<Self, I>>,
) -> Self { ) -> Self {
DefaultScheduledMutator { DefaultScheduledMutator {
rand: rand, rand: Rc::clone(rand),
corpus: corpus, corpus: corpus,
mutations: mutations, mutations: mutations,
} }
@ -181,7 +180,7 @@ where
M: Mutator<I>, M: Mutator<I>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
{ {
let bit = mutator.rand_mut().below(input.bytes().len() as u64) as usize; let bit = mutator.rand().borrow_mut().below(input.bytes().len() as u64) as usize;
input.bytes_mut()[bit >> 3] ^= (128 >> (bit & 7)) as u8; input.bytes_mut()[bit >> 3] ^= (128 >> (bit & 7)) as u8;
Ok(()) Ok(())
} }
@ -203,11 +202,8 @@ where
{ {
type R = S::R; type R = S::R;
fn rand(&self) -> &Self::R { fn rand(&self) -> &Rc<RefCell<Self::R>> {
self.scheduled.rand() &self.scheduled.rand()
}
fn rand_mut(&mut self) -> &mut Self::R {
self.scheduled.rand_mut()
} }
} }
@ -263,7 +259,7 @@ where
C: Corpus<I>, C: Corpus<I>,
{ {
/// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator /// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator
pub fn new_default(rand: &'a mut R) -> Self { pub fn new_default(rand: &Rc<RefCell<R>>) -> Self {
let mut scheduled = DefaultScheduledMutator::<'a, I, R, C>::new(rand); let mut scheduled = DefaultScheduledMutator::<'a, I, R, C>::new(rand);
scheduled.add_mutation(mutation_bitflip); scheduled.add_mutation(mutation_bitflip);
HavocBytesMutator { HavocBytesMutator {

View File

@ -24,7 +24,7 @@ where
} }
fn iterations(&mut self) -> usize { fn iterations(&mut self) -> usize {
1 + self.rand_mut().below(128) as usize 1 + self.rand().borrow_mut().below(128) as usize
} }
fn perform_mutational(&mut self, entry: Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> { fn perform_mutational(&mut self, entry: Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
@ -54,7 +54,7 @@ where
R: Rand, R: Rand,
E: Evaluator<I>, E: Evaluator<I>,
{ {
rand: &'a mut R, rand: Rc<RefCell<R>>,
eval: &'a mut E, eval: &'a mut E,
mutators: Vec<Box<dyn Mutator<I, R = R>>>, mutators: Vec<Box<dyn Mutator<I, R = R>>>,
} }
@ -67,12 +67,10 @@ where
{ {
type R = R; type R = R;
fn rand(&self) -> &Self::R { fn rand(&self) -> &Rc<RefCell<R>> {
&self.rand &self.rand
} }
fn rand_mut(&mut self) -> &mut Self::R {
&mut self.rand
}
} }
impl<'a, I, R, E> HasEvaluator<I> for DefaultMutationalStage<'a, I, R, E> impl<'a, I, R, E> HasEvaluator<I> for DefaultMutationalStage<'a, I, R, E>
@ -124,9 +122,9 @@ where
R: Rand, R: Rand,
E: Evaluator<I>, E: Evaluator<I>,
{ {
pub fn new(rand: &'a mut R, eval: &'a mut E) -> Self { pub fn new(rand: &Rc<RefCell<R>>, eval: &'a mut E) -> Self {
DefaultMutationalStage { DefaultMutationalStage {
rand: rand, rand: Rc::clone(rand),
eval: eval, eval: eval,
mutators: vec![], mutators: vec![],
} }

View File

@ -1,6 +1,8 @@
//! Utility functions for AFL //! Utility functions for AFL
use std::debug_assert; use std::debug_assert;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Debug; use std::fmt::Debug;
use xxhash_rust::xxh3::xxh3_64_with_seed; use xxhash_rust::xxh3::xxh3_64_with_seed;
@ -44,10 +46,21 @@ pub trait HasRand {
type R: Rand; type R: Rand;
/// Get the hold Rand instance /// Get the hold Rand instance
fn rand(&self) -> &Self::R; fn rand(&self) -> &Rc<RefCell<Self::R>>;
/// Get the hold Rand instance (mutable) // Gets the next 64 bit value
fn rand_mut(&mut self) -> &mut Self::R; fn rand_next(&self) -> u64 {
self.rand().borrow_mut().next()
}
// Gets a value below the given 64 bit val (inclusive)
fn rand_below(&self, upper_bound_excl: u64) -> u64 {
self.rand().borrow_mut().below(upper_bound_excl)
}
// Gets a value between the given lower bound (inclusive) and upper bound (inclusive)
fn rand_between(&self, lower_bound_incl: u64, upper_bound_incl: u64) -> u64 {
self.rand().borrow_mut().between(lower_bound_incl, upper_bound_incl)
}
} }
const HASH_CONST: u64 = 0xa5b35705; const HASH_CONST: u64 = 0xa5b35705;
@ -96,6 +109,10 @@ impl Xoshiro256StarRand {
ret.set_seed(0); // TODO: Proper random seed? ret.set_seed(0); // TODO: Proper random seed?
ret ret
} }
pub fn new_rc() -> Rc<RefCell<Xoshiro256StarRand>> {
Rc::new(RefCell::new(Xoshiro256StarRand::new()))
}
} }
/// Get the next higher power of two /// Get the next higher power of two
@ -111,7 +128,7 @@ pub fn next_pow2(val: u64) -> u64 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::utils::{next_pow2, Rand, Xoshiro256StarRand}; use crate::utils::{next_pow2, Rand, HasRand, Xoshiro256StarRand};
#[test] #[test]
fn test_rand() { fn test_rand() {
@ -123,6 +140,35 @@ mod tests {
assert!(rand.between(11, 20) > 10); assert!(rand.between(11, 20) > 10);
} }
use std::rc::Rc;
use std::cell::RefCell;
struct HasRandTest<R>
where
R: Rand,
{
rand: Rc<RefCell<R>>
}
impl<R> HasRand for HasRandTest<R>
where
R: Rand
{
type R = R;
fn rand(&self) -> &Rc<RefCell<R>> {
&self.rand
}
}
fn test_has_rand() {
let rand = Xoshiro256StarRand::new_rc();
let has_rand = HasRandTest{rand: Rc::clone(&rand)};
assert!(has_rand.rand_below(100) < 100);
assert_eq!(has_rand.rand_below(1), 0);
}
#[test] #[test]
fn test_next_pow2() { fn test_next_pow2() {
assert_eq!(next_pow2(0), 0); assert_eq!(next_pow2(0), 0);