refcell stage

This commit is contained in:
Andrea Fioraldi 2020-11-06 12:17:23 +01:00
parent bf1c1f4057
commit 850c49258e
6 changed files with 69 additions and 81 deletions

View File

@ -304,13 +304,10 @@ mod tests {
#[test] #[test]
fn test_queuecorpus() { fn test_queuecorpus() {
let rand = Xoshiro256StarRand::new_rc(); let rand = Xoshiro256StarRand::new_rr();
let mut q = QueueCorpus::new(OnDiskCorpus::new(&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 = Testcase::with_filename_rr(i, PathBuf::from("fancyfile"));
i,
PathBuf::from("fancyfile"),
)));
q.add(t); q.add(t);
let filename = q let filename = q
.get() .get()

View File

@ -2,34 +2,14 @@ use crate::inputs::Input;
use crate::AflError; use crate::AflError;
use hashbrown::HashMap; use hashbrown::HashMap;
use std::cell::RefCell;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc;
pub trait TestcaseMetadata { pub trait TestcaseMetadata {
fn name(&self) -> &'static str; fn name(&self) -> &'static str;
} }
/*
pub trait TestcaseTrait<I: Input> {
/// Make sure to return a valid input instance loading it from disk if not in memory
fn load_input(&mut self) -> Result<&I, AflError>;
/// Get the input, if any
fn input(&self) -> &Option<I>;
/// Get the input, if any (mutable)
fn input_mut(&mut self) -> &mut Option<I>;
/// Get the filename, if any
fn filename(&self) -> &Option<PathBuf>;
/// Get the filename, if any (mutable)
fn filename_mut(&mut self, filename: PathBuf) -> &mut &Option<PathBuf>;
/// Get all the metadatas into an HashMap
fn metadatas(&mut self) -> &mut HashMap<String, Box<dyn TestcaseMetadata>>;
}
*/
#[derive(Default)] #[derive(Default)]
pub struct Testcase<I> pub struct Testcase<I>
where where
@ -40,6 +20,8 @@ where
metadatas: HashMap<&'static str, Box<dyn TestcaseMetadata>>, metadatas: HashMap<&'static str, Box<dyn TestcaseMetadata>>,
} }
pub type TestcaseRef<I> = Rc<RefCell<Testcase<I>>>;
impl<I> Testcase<I> impl<I> Testcase<I>
where where
I: Input, I: Input,
@ -89,7 +71,7 @@ where
self.metadatas.insert(meta.name(), meta); self.metadatas.insert(meta.name(), meta);
} }
/// Create a new DefaultTestcase instace given an input /// Create a new Testcase instace given an input
pub fn new(input: I) -> Self { pub fn new(input: I) -> Self {
Testcase { Testcase {
input: Some(input), input: Some(input),
@ -98,12 +80,22 @@ where
} }
} }
/// Create a new DefaultTestcase instace given an input and a filename /// Create a new Testcase instace given an input and a filename
pub fn new_with_filename(input: I, filename: PathBuf) -> Self { pub fn with_filename(input: I, filename: PathBuf) -> Self {
Testcase { Testcase {
input: Some(input), input: Some(input),
filename: Some(filename), filename: Some(filename),
metadatas: HashMap::default(), metadatas: HashMap::default(),
} }
} }
/// Create a new Testcase instace given an input behind a Rc RefCell
pub fn new_rr(input: I) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self::new(input)))
}
/// Create a new Testcase instace given an input and a filename behind a Rc RefCell
pub fn with_filename_rr(input: I, filename: PathBuf) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self::with_filename(input, filename)))
}
} }

View File

@ -20,7 +20,7 @@ where
) -> Result<bool, AflError>; ) -> Result<bool, AflError>;
} }
pub trait Engine<'a, I, C, E>: Evaluator<I> pub trait Engine<I, C, E>: Evaluator<I>
where where
I: Input, I: Input,
C: Corpus<I>, C: Corpus<I>,
@ -34,11 +34,11 @@ where
self.feedbacks_mut().push(feedback); self.feedbacks_mut().push(feedback);
} }
fn stages(&self) -> &Vec<Box<dyn Stage<'a, I, E = Self>>>; fn stages(&self) -> &Vec<Box<dyn Stage<I, E = Self>>>;
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<'a, I, E = Self>>>; fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I, E = Self>>>;
fn add_stage(&mut self, stage: Box<dyn Stage<'a, I, E = Self>>) { fn add_stage(&mut self, stage: Box<dyn Stage<I, E = Self>>) {
self.stages_mut().push(stage); self.stages_mut().push(stage);
} }
@ -91,19 +91,19 @@ where
} }
} }
pub struct DefaultEngine<'a, I, C, E> pub struct DefaultEngine<I, C, E>
where where
I: Input, I: Input,
C: Corpus<I>, C: Corpus<I>,
E: Executor<I>, E: Executor<I>,
{ {
feedbacks: Vec<Box<dyn Feedback<I>>>, feedbacks: Vec<Box<dyn Feedback<I>>>,
stages: Vec<Box<dyn Stage<'a, I, E = Self>>>, stages: Vec<Box<dyn Stage<I, E = Self>>>,
executor: &'a mut E, executor: E,
corpus: &'a mut C, corpus: C,
} }
impl<'a, I, C, E> Evaluator<I> for DefaultEngine<'a, I, C, E> impl<I, C, E> Evaluator<I> for DefaultEngine<I, C, E>
where where
I: Input, I: Input,
C: Corpus<I>, C: Corpus<I>,
@ -118,7 +118,7 @@ where
} }
} }
impl<'a, I, C, E> Engine<'a, I, C, E> for DefaultEngine<'a, I, C, E> impl<I, C, E> Engine<I, C, E> for DefaultEngine<I, C, E>
where where
I: Input, I: Input,
C: Corpus<I>, C: Corpus<I>,
@ -132,38 +132,38 @@ where
&mut self.feedbacks &mut self.feedbacks
} }
fn stages(&self) -> &Vec<Box<dyn Stage<'a, I, E = Self>>> { fn stages(&self) -> &Vec<Box<dyn Stage<I, E = Self>>> {
&self.stages &self.stages
} }
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<'a, I, E = Self>>> { fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I, E = Self>>> {
&mut self.stages &mut self.stages
} }
fn corpus(&self) -> &C { fn corpus(&self) -> &C {
self.corpus &self.corpus
} }
fn corpus_mut(&mut self) -> &mut C { fn corpus_mut(&mut self) -> &mut C {
self.corpus &mut self.corpus
} }
fn executor(&self) -> &E { fn executor(&self) -> &E {
self.executor &self.executor
} }
fn executor_mut(&mut self) -> &mut E { fn executor_mut(&mut self) -> &mut E {
self.executor &mut self.executor
} }
} }
impl<'a, I, C, E> DefaultEngine<'a, I, C, E> impl<I, C, E> DefaultEngine<I, C, E>
where where
I: Input, I: Input,
C: Corpus<I>, C: Corpus<I>,
E: Executor<I>, E: Executor<I>,
{ {
pub fn new(corpus: &'a mut C, executor: &'a mut E) -> Self { pub fn new(corpus: C, executor: E) -> Self {
DefaultEngine { DefaultEngine {
feedbacks: vec![], feedbacks: vec![],
stages: vec![], stages: vec![],
@ -171,11 +171,15 @@ where
executor: executor, executor: executor,
} }
} }
pub fn new_rr(corpus: C, executor: E) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self::new(corpus, executor)))
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::corpus::InMemoryCorpus; use crate::corpus::{Corpus, InMemoryCorpus};
use crate::engines::{DefaultEngine, Engine}; use crate::engines::{DefaultEngine, Engine};
use crate::executors::inmemory::InMemoryExecutor; use crate::executors::inmemory::InMemoryExecutor;
use crate::executors::{Executor, ExitKind}; use crate::executors::{Executor, ExitKind};
@ -192,14 +196,12 @@ mod tests {
#[test] #[test]
fn test_engine() { fn test_engine() {
let rand = Rc::new(RefCell::new(Xoshiro256StarRand::new())); let rand = Xoshiro256StarRand::new_rr();
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&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_rr(corpus, executor);
let stage = Box::new(DefaultMutationalStage::new(&rand, &mut engine)); let stage = Box::new(DefaultMutationalStage::new(&rand, &engine));
engine.add_stage(stage); engine.borrow_mut().add_stage(stage);
engine.fuzz_one().unwrap(); engine.borrow_mut().fuzz_one().unwrap();
let stage1 = Box::new(DefaultMutationalStage::new(&rand, &mut engine));
engine.fuzz_one().unwrap();
} }
} }

View File

@ -14,12 +14,10 @@ where
{ {
type E: Evaluator<I>; type E: Evaluator<I>;
fn eval(&self) -> &Self::E; fn eval(&self) -> &Rc<RefCell<Self::E>>;
fn eval_mut(&mut self) -> &mut Self::E;
} }
pub trait Stage<'a, I>: HasEvaluator<I> pub trait Stage<I>: HasEvaluator<I>
where where
I: Input, I: Input,
{ {

View File

@ -11,7 +11,7 @@ use std::rc::Rc;
// TODO create HasMutatorsVec trait // TODO create HasMutatorsVec trait
pub trait MutationalStage<'a, I>: Stage<'a, I> + HasRand pub trait MutationalStage<I>: Stage<I> + HasRand
where where
I: Input, I: Input,
{ {
@ -36,7 +36,10 @@ where
m.mutate(&mut input, i as i32)?; m.mutate(&mut input, i as i32)?;
} }
let interesting = self.eval_mut().evaluate_input(&mut input, entry.clone())?; let interesting = self
.eval()
.borrow_mut()
.evaluate_input(&mut input, entry.clone())?;
for m in self.mutators_mut() { for m in self.mutators_mut() {
m.post_exec(interesting, i as i32)?; m.post_exec(interesting, i as i32)?;
@ -48,18 +51,18 @@ where
} }
} }
pub struct DefaultMutationalStage<'a, I, R, E> pub struct DefaultMutationalStage<I, R, E>
where where
I: Input, I: Input,
R: Rand, R: Rand,
E: Evaluator<I>, E: Evaluator<I>,
{ {
rand: Rc<RefCell<R>>, rand: Rc<RefCell<R>>,
eval: &'a mut E, eval: Rc<RefCell<E>>,
mutators: Vec<Box<dyn Mutator<I, R = R>>>, mutators: Vec<Box<dyn Mutator<I, R = R>>>,
} }
impl<'a, I, R, E> HasRand for DefaultMutationalStage<'a, I, R, E> impl<I, R, E> HasRand for DefaultMutationalStage<I, R, E>
where where
I: Input, I: Input,
R: Rand, R: Rand,
@ -72,7 +75,7 @@ where
} }
} }
impl<'a, I, R, E> HasEvaluator<I> for DefaultMutationalStage<'a, I, R, E> impl<I, R, E> HasEvaluator<I> for DefaultMutationalStage<I, R, E>
where where
I: Input, I: Input,
R: Rand, R: Rand,
@ -80,16 +83,12 @@ where
{ {
type E = E; type E = E;
fn eval(&self) -> &Self::E { fn eval(&self) -> &Rc<RefCell<Self::E>> {
self.eval &self.eval
}
fn eval_mut(&mut self) -> &mut Self::E {
self.eval
} }
} }
impl<'a, I, R, E> MutationalStage<'a, I> for DefaultMutationalStage<'a, I, R, E> impl<I, R, E> MutationalStage<I> for DefaultMutationalStage<I, R, E>
where where
I: Input, I: Input,
R: Rand, R: Rand,
@ -104,7 +103,7 @@ where
} }
} }
impl<'a, I, R, E> Stage<'a, I> for DefaultMutationalStage<'a, I, R, E> impl<I, R, E> Stage<I> for DefaultMutationalStage<I, R, E>
where where
I: Input, I: Input,
R: Rand, R: Rand,
@ -115,16 +114,16 @@ where
} }
} }
impl<'a, I, R, E> DefaultMutationalStage<'a, I, R, E> impl<I, R, E> DefaultMutationalStage<I, R, E>
where where
I: Input, I: Input,
R: Rand, R: Rand,
E: Evaluator<I>, E: Evaluator<I>,
{ {
pub fn new(rand: &Rc<RefCell<R>>, eval: &'a mut E) -> Self { pub fn new(rand: &Rc<RefCell<R>>, eval: &Rc<RefCell<E>>) -> Self {
DefaultMutationalStage { DefaultMutationalStage {
rand: Rc::clone(rand), rand: Rc::clone(rand),
eval: eval, eval: Rc::clone(eval),
mutators: vec![], mutators: vec![],
} }
} }

View File

@ -41,7 +41,7 @@ pub trait Rand: Debug {
} }
} }
/// Has a Rand box field /// Has a Rand Rc RefCell field
pub trait HasRand { pub trait HasRand {
type R: Rand; type R: Rand;
@ -106,13 +106,13 @@ impl Rand for Xoshiro256StarRand {
} }
impl Xoshiro256StarRand { impl Xoshiro256StarRand {
pub fn new() -> Xoshiro256StarRand { pub fn new() -> Self {
let mut ret: Xoshiro256StarRand = Default::default(); let mut ret: Xoshiro256StarRand = Default::default();
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>> { pub fn new_rr() -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Xoshiro256StarRand::new())) Rc::new(RefCell::new(Xoshiro256StarRand::new()))
} }
} }
@ -163,7 +163,7 @@ mod tests {
} }
fn test_has_rand() { fn test_has_rand() {
let rand = Xoshiro256StarRand::new_rc(); let rand = Xoshiro256StarRand::new_rr();
let has_rand = HasRandTest { let has_rand = HasRandTest {
rand: Rc::clone(&rand), rand: Rc::clone(&rand),
}; };