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
fn random_entry(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
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())
}
@ -68,16 +68,16 @@ where
}
}
pub struct InMemoryCorpus<'a, I, R>
pub struct InMemoryCorpus<I, R>
where
I: Input,
R: Rand,
{
rand: &'a mut R,
rand: Rc<RefCell<R>>,
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
I: Input,
R: Rand,
@ -90,22 +90,19 @@ where
}
}
impl<I, R> HasRand for InMemoryCorpus<'_, I, R>
impl<I, R> HasRand for InMemoryCorpus<I, R>
where
I: Input,
R: Rand,
{
type R = R;
fn rand(&self) -> &Self::R {
fn rand(&self) -> &Rc<RefCell<Self::R>> {
&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
I: Input,
R: Rand,
@ -113,30 +110,30 @@ where
// Just use the default implementation
}
impl<'a, I, R> InMemoryCorpus<'a, I, R>
impl<I, R> InMemoryCorpus<I, R>
where
I: Input,
R: Rand,
{
pub fn new(rand: &'a mut R) -> Self {
pub fn new(rand: &Rc<RefCell<R>>) -> Self {
InMemoryCorpus {
rand: rand,
rand: Rc::clone(rand),
entries: vec![],
}
}
}
pub struct OnDiskCorpus<'a, I, R>
pub struct OnDiskCorpus<I, R>
where
I: Input,
R: Rand,
{
rand: &'a mut R,
rand: Rc<RefCell<R>>,
entries: Vec<Rc<RefCell<Testcase<I>>>>,
dir_path: PathBuf,
}
impl<I, R> HasEntriesVec<I> for OnDiskCorpus<'_, I, R>
impl<I, R> HasEntriesVec<I> for OnDiskCorpus<I, R>
where
I: Input,
R: Rand,
@ -149,22 +146,19 @@ where
}
}
impl<I, R> HasRand for OnDiskCorpus<'_, I, R>
impl<I, R> HasRand for OnDiskCorpus<I, R>
where
I: Input,
R: Rand,
{
type R = R;
fn rand(&self) -> &Self::R {
fn rand(&self) -> &Rc<RefCell<Self::R>> {
&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
I: Input,
R: Rand,
@ -183,16 +177,16 @@ where
// 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
I: Input,
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 {
rand: Rc::clone(rand),
dir_path: dir_path,
entries: vec![],
rand: rand,
}
}
}
@ -229,12 +223,9 @@ where
{
type R = C::R;
fn rand(&self) -> &Self::R {
fn rand(&self) -> &Rc<RefCell<Self::R>> {
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>
@ -313,8 +304,8 @@ mod tests {
#[test]
fn test_queuecorpus() {
let mut rand = Xoshiro256StarRand::new();
let mut q = QueueCorpus::new(OnDiskCorpus::new(&mut rand, PathBuf::from("fancy/path")));
let rand = Xoshiro256StarRand::new_rc();
let mut q = QueueCorpus::new(OnDiskCorpus::new(&rand, PathBuf::from("fancy/path")));
let i = BytesInput::new(vec![0; 4]);
let t = Rc::new(RefCell::new(Testcase::new_with_filename(
i,

View File

@ -175,7 +175,6 @@ where
#[cfg(test)]
mod tests {
use crate::corpus::testcase::Testcase;
use crate::corpus::InMemoryCorpus;
use crate::engines::{DefaultEngine, Engine};
use crate::executors::inmemory::InMemoryExecutor;
@ -185,24 +184,22 @@ mod tests {
use crate::utils::Xoshiro256StarRand;
use std::cell::RefCell;
use std::path::PathBuf;
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
}
#[test]
fn test_engine() {
let mut rand = Xoshiro256StarRand::new();
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&mut rand);
let rand = Rc::new(RefCell::new(Xoshiro256StarRand::new()));
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
let mut executor = InMemoryExecutor::new(harness);
let mut engine = DefaultEngine::new(&mut corpus, &mut executor);
let mut rand1 = Xoshiro256StarRand::new();
let mut stage = Box::new(DefaultMutationalStage::new(&mut rand1, &mut engine));
let mut stage = Box::new(DefaultMutationalStage::new(&rand, &mut engine));
engine.add_stage(stage);
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();
}
}

View File

@ -5,6 +5,8 @@ use crate::utils::{HasRand, Rand};
use crate::AflError;
use std::marker::PhantomData;
use std::rc::Rc;
use std::cell::RefCell;
/// The generic function type that identifies mutations
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
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
@ -40,7 +42,7 @@ where
}
let idx;
{
idx = self.rand_mut().below(count) as usize;
idx = self.rand().borrow_mut().below(count) as usize;
}
self.mutation_by_idx(idx)
}
@ -62,7 +64,7 @@ where
R: Rand,
C: Corpus<I>,
{
rand: &'a mut R,
rand: Rc<RefCell<R>>,
corpus: Option<Box<C>>,
mutations: Vec<MutationFunction<Self, I>>,
}
@ -75,12 +77,9 @@ where
{
type R = R;
fn rand(&self) -> &Self::R {
fn rand(&self) -> &Rc<RefCell<Self::R>> {
&self.rand
}
fn rand_mut(&mut self) -> &mut Self::R {
&mut self.rand
}
}
impl<I, R, C> HasOptionCorpus<I> for DefaultScheduledMutator<'_, I, R, C>
@ -153,9 +152,9 @@ where
C: Corpus<I>,
{
/// 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 {
rand: rand,
rand: Rc::clone(rand),
corpus: None,
mutations: vec![],
}
@ -163,12 +162,12 @@ where
/// Create a new DefaultScheduledMutator instance specifying mutations and corpus too
pub fn new_all(
rand: &'a mut R,
rand: &Rc<RefCell<R>>,
corpus: Option<Box<C>>,
mutations: Vec<MutationFunction<Self, I>>,
) -> Self {
DefaultScheduledMutator {
rand: rand,
rand: Rc::clone(rand),
corpus: corpus,
mutations: mutations,
}
@ -181,7 +180,7 @@ where
M: Mutator<I>,
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;
Ok(())
}
@ -203,11 +202,8 @@ where
{
type R = S::R;
fn rand(&self) -> &Self::R {
self.scheduled.rand()
}
fn rand_mut(&mut self) -> &mut Self::R {
self.scheduled.rand_mut()
fn rand(&self) -> &Rc<RefCell<Self::R>> {
&self.scheduled.rand()
}
}
@ -263,7 +259,7 @@ where
C: Corpus<I>,
{
/// 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);
scheduled.add_mutation(mutation_bitflip);
HavocBytesMutator {

View File

@ -24,7 +24,7 @@ where
}
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> {
@ -54,7 +54,7 @@ where
R: Rand,
E: Evaluator<I>,
{
rand: &'a mut R,
rand: Rc<RefCell<R>>,
eval: &'a mut E,
mutators: Vec<Box<dyn Mutator<I, R = R>>>,
}
@ -67,12 +67,10 @@ where
{
type R = R;
fn rand(&self) -> &Self::R {
fn rand(&self) -> &Rc<RefCell<R>> {
&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>
@ -124,9 +122,9 @@ where
R: Rand,
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 {
rand: rand,
rand: Rc::clone(rand),
eval: eval,
mutators: vec![],
}

View File

@ -1,6 +1,8 @@
//! Utility functions for AFL
use std::debug_assert;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Debug;
use xxhash_rust::xxh3::xxh3_64_with_seed;
@ -44,10 +46,21 @@ pub trait HasRand {
type R: Rand;
/// Get the hold Rand instance
fn rand(&self) -> &Self::R;
fn rand(&self) -> &Rc<RefCell<Self::R>>;
/// Get the hold Rand instance (mutable)
fn rand_mut(&mut self) -> &mut Self::R;
// Gets the next 64 bit value
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;
@ -96,6 +109,10 @@ impl Xoshiro256StarRand {
ret.set_seed(0); // TODO: Proper random seed?
ret
}
pub fn new_rc() -> Rc<RefCell<Xoshiro256StarRand>> {
Rc::new(RefCell::new(Xoshiro256StarRand::new()))
}
}
/// Get the next higher power of two
@ -111,7 +128,7 @@ pub fn next_pow2(val: u64) -> u64 {
#[cfg(test)]
mod tests {
use crate::utils::{next_pow2, Rand, Xoshiro256StarRand};
use crate::utils::{next_pow2, Rand, HasRand, Xoshiro256StarRand};
#[test]
fn test_rand() {
@ -123,6 +140,35 @@ mod tests {
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]
fn test_next_pow2() {
assert_eq!(next_pow2(0), 0);