state trait
This commit is contained in:
parent
056f5b6689
commit
c9cc66311a
@ -80,10 +80,7 @@ where
|
||||
match self {
|
||||
Self::Stored { filename } => {
|
||||
let input = I::from_file(&filename)?;
|
||||
Ok(Self::Loaded {
|
||||
filename,
|
||||
input,
|
||||
})
|
||||
Ok(Self::Loaded { filename, input })
|
||||
}
|
||||
Self::Loaded {
|
||||
input: _,
|
||||
@ -170,11 +167,13 @@ where
|
||||
{
|
||||
/// Make sure to return a valid input instance loading it from disk if not in memory
|
||||
pub fn load_input(&mut self) -> Result<&I, AflError> {
|
||||
// TODO: Implement cache to disk
|
||||
match self.input.as_ref() {
|
||||
Some(i) => Ok(i),
|
||||
None => Err(AflError::NotImplemented("load_input".into())),
|
||||
if self.input.is_none() {
|
||||
let input = I::from_file(self.filename.as_ref().ok_or(AflError::EmptyOptional(
|
||||
"filename not specified".to_string(),
|
||||
))?)?;
|
||||
self.input = Some(input);
|
||||
}
|
||||
Ok(self.input.as_ref().unwrap())
|
||||
}
|
||||
|
||||
/// Get the input, if any
|
||||
@ -226,4 +225,12 @@ where
|
||||
metadatas: HashMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default() -> Self {
|
||||
Testcase {
|
||||
input: None,
|
||||
filename: None,
|
||||
metadatas: HashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +1,126 @@
|
||||
//! The engine is the core piece of every good fuzzer
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use core::cell::RefCell;
|
||||
|
||||
use crate::corpus::Corpus;
|
||||
use crate::corpus::{Corpus, Testcase};
|
||||
use crate::executors::Executor;
|
||||
use crate::feedbacks::Feedback;
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::Observer;
|
||||
use crate::stages::Stage;
|
||||
use crate::AflError;
|
||||
|
||||
pub trait Engine<C, I>
|
||||
pub trait State<C, E, I>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
/// Get the linked observers
|
||||
fn observers(&self) -> &[Box<dyn Observer>];
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers_mut(&mut self) -> &mut Vec<Box<dyn Observer>>;
|
||||
|
||||
/// Add a linked observer
|
||||
fn add_observer(&mut self, observer: Box<dyn Observer>) {
|
||||
self.observers_mut().push(observer);
|
||||
}
|
||||
|
||||
/// Reset the state of all the observes linked to this executor
|
||||
fn reset_observers(&mut self) -> Result<(), AflError> {
|
||||
for observer in self.observers_mut() {
|
||||
observer.reset()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the post exec hook for all the observes linked to this executor
|
||||
fn post_exec_observers(&mut self) -> Result<(), AflError> {
|
||||
self.observers_mut()
|
||||
.iter_mut()
|
||||
.map(|x| x.post_exec())
|
||||
.fold(Ok(()), |acc, x| if x.is_err() { x } else { acc })
|
||||
}
|
||||
|
||||
/// Returns vector of feebacks
|
||||
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>];
|
||||
|
||||
/// Returns vector of feebacks (mutable)
|
||||
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>;
|
||||
|
||||
/// Adds a feedback
|
||||
fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>) {
|
||||
self.feedbacks_mut().push(feedback);
|
||||
}
|
||||
|
||||
fn stages(&self) -> &[Box<dyn Stage<C, I>>];
|
||||
/// Return the corpus
|
||||
fn corpus(&self) -> &C;
|
||||
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<C, I>>>;
|
||||
/// Return the corpus (mutable)
|
||||
fn corpus_mut(&mut self) -> &mut C;
|
||||
|
||||
fn add_stage(&mut self, stage: Box<dyn Stage<C, I>>) {
|
||||
self.stages_mut().push(stage);
|
||||
}
|
||||
/// Return the executor
|
||||
fn executor(&self) -> &E;
|
||||
|
||||
fn fuzz_one(&mut self, corpus: &mut C) -> Result<(), AflError> {
|
||||
let testcase = corpus.next()?;
|
||||
for stage in self.stages_mut() {
|
||||
stage.perform(testcase.clone(), corpus)?;
|
||||
/// Return the executor (mutable)
|
||||
fn executor_mut(&mut self) -> &mut E;
|
||||
|
||||
/// Runs the input and triggers observers and feedback
|
||||
fn evaluate_input(&mut self, input: &I) -> Result<bool, AflError> {
|
||||
self.reset_observers()?;
|
||||
self.executor_mut().run_target(input)?;
|
||||
self.post_exec_observers()?;
|
||||
|
||||
let mut rate_acc = 0;
|
||||
for feedback in self.feedbacks_mut() {
|
||||
rate_acc += feedback.is_interesting(input)?;
|
||||
}
|
||||
|
||||
if rate_acc >= 25 {
|
||||
let testcase = Rc::new(RefCell::new(Testcase::new(input.clone())));
|
||||
for feedback in self.feedbacks_mut() {
|
||||
feedback.append_metadata(testcase.clone())?;
|
||||
}
|
||||
Ok(true)
|
||||
} else {
|
||||
for feedback in self.feedbacks_mut() {
|
||||
feedback.discard_metadata()?;
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultEngine<C, I>
|
||||
pub struct DefaultState<C, E, I>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
observers: Vec<Box<dyn Observer>>,
|
||||
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
||||
stages: Vec<Box<dyn Stage<C, I>>>,
|
||||
corpus: C,
|
||||
executor: E,
|
||||
}
|
||||
|
||||
impl<C, I> Engine<C, I> for DefaultEngine<C, I>
|
||||
impl<C, E, I> State<C, E, I> for DefaultState<C, E, I>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
fn observers(&self) -> &[Box<dyn Observer>] {
|
||||
&self.observers
|
||||
}
|
||||
|
||||
fn observers_mut(&mut self) -> &mut Vec<Box<dyn Observer>> {
|
||||
&mut self.observers
|
||||
}
|
||||
|
||||
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>] {
|
||||
&self.feedbacks
|
||||
}
|
||||
@ -61,25 +129,98 @@ where
|
||||
&mut self.feedbacks
|
||||
}
|
||||
|
||||
fn stages(&self) -> &[Box<dyn Stage<C, I>>] {
|
||||
fn corpus(&self) -> &C {
|
||||
&self.corpus
|
||||
}
|
||||
|
||||
fn corpus_mut(&mut self) -> &mut C {
|
||||
&mut self.corpus
|
||||
}
|
||||
|
||||
fn executor(&self) -> &E {
|
||||
&self.executor
|
||||
}
|
||||
|
||||
fn executor_mut(&mut self) -> &mut E {
|
||||
&mut self.executor
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, E, I> DefaultState<C, E, I>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
pub fn new(corpus: C, executor: E) -> Self {
|
||||
DefaultState {
|
||||
observers: vec![],
|
||||
feedbacks: vec![],
|
||||
corpus: corpus,
|
||||
executor: executor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Engine<S, C, E, I>
|
||||
where
|
||||
S: State<C, E, I>,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
fn stages(&self) -> &[Box<dyn Stage<S, C, E, I>>];
|
||||
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<S, C, E, I>>>;
|
||||
|
||||
fn add_stage(&mut self, stage: Box<dyn Stage<S, C, E, I>>) {
|
||||
self.stages_mut().push(stage);
|
||||
}
|
||||
|
||||
fn fuzz_one(&mut self, state: &mut S) -> Result<(), AflError> {
|
||||
let testcase = state.corpus_mut().next()?;
|
||||
for stage in self.stages_mut() {
|
||||
stage.perform(testcase.clone(), state)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultEngine<S, C, E, I>
|
||||
where
|
||||
S: State<C, E, I>,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
stages: Vec<Box<dyn Stage<S, C, E, I>>>,
|
||||
}
|
||||
|
||||
impl<S, C, E, I> Engine<S, C, E, I> for DefaultEngine<S, C, E, I>
|
||||
where
|
||||
S: State<C, E, I>,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
fn stages(&self) -> &[Box<dyn Stage<S, C, E, I>>] {
|
||||
&self.stages
|
||||
}
|
||||
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<C, I>>> {
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<S, C, E, I>>> {
|
||||
&mut self.stages
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, I> DefaultEngine<C, I>
|
||||
impl<S, C, E, I> DefaultEngine<S, C, E, I>
|
||||
where
|
||||
S: State<C, E, I>,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
DefaultEngine {
|
||||
feedbacks: vec![],
|
||||
stages: vec![],
|
||||
}
|
||||
DefaultEngine { stages: vec![] }
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,7 +230,7 @@ mod tests {
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
|
||||
use crate::engines::{DefaultEngine, Engine};
|
||||
use crate::engines::{DefaultEngine, DefaultState, Engine};
|
||||
use crate::executors::inmemory::InMemoryExecutor;
|
||||
use crate::executors::{Executor, ExitKind};
|
||||
use crate::inputs::bytes::BytesInput;
|
||||
@ -110,18 +251,21 @@ mod tests {
|
||||
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
|
||||
let testcase = Testcase::new(vec![0; 4]).into();
|
||||
corpus.add(testcase);
|
||||
let executor = InMemoryExecutor::<BytesInput>::new(harness).into();
|
||||
|
||||
let executor = InMemoryExecutor::<BytesInput>::new(harness);
|
||||
let mut state = DefaultState::new(corpus, executor);
|
||||
|
||||
let mut engine = DefaultEngine::new();
|
||||
let mut mutator = DefaultScheduledMutator::new(&rand);
|
||||
mutator.add_mutation(mutation_bitflip);
|
||||
let stage = DefaultMutationalStage::new(&rand, &executor, mutator);
|
||||
let stage = DefaultMutationalStage::new(&rand, mutator);
|
||||
engine.add_stage(Box::new(stage));
|
||||
|
||||
//
|
||||
|
||||
for i in 0..1000 {
|
||||
engine
|
||||
.fuzz_one(&mut corpus)
|
||||
.fuzz_one(&mut state)
|
||||
.expect(&format!("Error in iter {}", i));
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ pub mod inmemory;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::corpus::TestcaseMetadata;
|
||||
use crate::corpus::Testcase;
|
||||
use crate::feedbacks::Feedback;
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::Observer;
|
||||
use crate::AflError;
|
||||
use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
|
||||
pub enum ExitKind {
|
||||
Ok,
|
||||
@ -53,19 +55,21 @@ where
|
||||
self.run_target(input)?;
|
||||
self.post_exec_observers()?;
|
||||
|
||||
let mut metadatas: Vec<Box<dyn TestcaseMetadata>> = vec![];
|
||||
let mut rate_acc = 0;
|
||||
for feedback in self.feedbacks_mut() {
|
||||
let (rate, meta) = feedback.is_interesting(input);
|
||||
rate_acc += rate;
|
||||
if let Some(m) = meta {
|
||||
metadatas.push(m);
|
||||
}
|
||||
rate_acc += feedback.is_interesting(input)?;
|
||||
}
|
||||
|
||||
if rate_acc >= 25 {
|
||||
let testcase = Rc::new(RefCell::new(Testcase::new(input.clone())));
|
||||
for feedback in self.feedbacks_mut() {
|
||||
feedback.append_metadata(testcase.clone())?;
|
||||
}
|
||||
Ok(true)
|
||||
} else {
|
||||
for feedback in self.feedbacks_mut() {
|
||||
feedback.discard_metadata()?;
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,32 @@
|
||||
extern crate num;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use core::cell::RefCell;
|
||||
use core::marker::PhantomData;
|
||||
use num::Integer;
|
||||
|
||||
use crate::corpus::TestcaseMetadata;
|
||||
use crate::corpus::Testcase;
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::MapObserver;
|
||||
use crate::AflError;
|
||||
|
||||
pub trait Feedback<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
/// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55)
|
||||
fn is_interesting(&mut self, input: &I) -> (u32, Option<Box<dyn TestcaseMetadata>>);
|
||||
fn is_interesting(&mut self, input: &I) -> Result<u32, AflError>;
|
||||
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
fn append_metadata(&mut self, _testcase: Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
||||
fn discard_metadata(&mut self) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A Reducer function is used to aggregate values for the novelty search
|
||||
@ -88,7 +99,7 @@ where
|
||||
O: MapObserver<T>,
|
||||
I: Input,
|
||||
{
|
||||
fn is_interesting(&mut self, _input: &I) -> (u32, Option<Box<dyn TestcaseMetadata>>) {
|
||||
fn is_interesting(&mut self, _input: &I) -> Result<u32, AflError> {
|
||||
let mut interesting = 0;
|
||||
|
||||
// TODO: impl. correctly, optimize
|
||||
@ -103,11 +114,11 @@ where
|
||||
*history = reduced;
|
||||
interesting += 25;
|
||||
if interesting >= 250 {
|
||||
return (255, None);
|
||||
return Ok(255);
|
||||
}
|
||||
}
|
||||
}
|
||||
(interesting, None)
|
||||
Ok(interesting)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,20 +3,24 @@ pub use mutational::DefaultMutationalStage;
|
||||
|
||||
use crate::corpus::testcase::Testcase;
|
||||
use crate::corpus::Corpus;
|
||||
use crate::engines::State;
|
||||
use crate::executors::Executor;
|
||||
use crate::inputs::Input;
|
||||
use crate::AflError;
|
||||
use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
|
||||
pub trait Stage<C, I>
|
||||
pub trait Stage<S, C, E, I>
|
||||
where
|
||||
S: State<C, E, I>,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
{
|
||||
/// Run the stage
|
||||
fn perform(
|
||||
&mut self,
|
||||
testcase: Rc<RefCell<Testcase<I>>>,
|
||||
corpus: &mut C,
|
||||
state: &mut S,
|
||||
) -> Result<(), AflError>;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use core::cell::RefCell;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::corpus::testcase::Testcase;
|
||||
use crate::engines::State;
|
||||
use crate::executors::Executor;
|
||||
use crate::inputs::Input;
|
||||
use crate::mutators::Mutator;
|
||||
@ -13,12 +14,13 @@ use crate::AflError;
|
||||
|
||||
// TODO multi mutators stage
|
||||
|
||||
pub trait MutationalStage<C, I, M, E>: Stage<C, I> + HasRand
|
||||
pub trait MutationalStage<M, S, C, E, I>: Stage<S, C, E, I> + HasRand
|
||||
where
|
||||
M: Mutator<C, I, R = Self::R>,
|
||||
S: State<C, E, I>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
M: Mutator<C, I, R = Self::R>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
/// The mutator registered for this stage
|
||||
fn mutator(&self) -> &M;
|
||||
@ -26,9 +28,6 @@ where
|
||||
/// The mutator registered for this stage (mutable)
|
||||
fn mutator_mut(&mut self) -> &mut M;
|
||||
|
||||
/// Rc Refcell to the executor
|
||||
fn executor(&self) -> &Rc<RefCell<E>>;
|
||||
|
||||
/// Gets the number of iterations this mutator should run for.
|
||||
/// This call uses internal mutability, so it may change for each call
|
||||
fn iterations(&mut self) -> usize {
|
||||
@ -39,7 +38,7 @@ where
|
||||
fn perform_mutational(
|
||||
&mut self,
|
||||
testcase: Rc<RefCell<Testcase<I>>>,
|
||||
corpus: &mut C,
|
||||
state: &mut S,
|
||||
) -> Result<(), AflError> {
|
||||
let num = self.iterations();
|
||||
let input = testcase.borrow_mut().load_input()?.clone();
|
||||
@ -47,14 +46,14 @@ where
|
||||
for i in 0..num {
|
||||
let mut input_tmp = input.clone();
|
||||
self.mutator_mut()
|
||||
.mutate(corpus, &mut input_tmp, i as i32)?;
|
||||
.mutate(state.corpus_mut(), &mut input_tmp, i as i32)?;
|
||||
|
||||
let interesting = self.executor().borrow_mut().evaluate_input(&input_tmp)?;
|
||||
let interesting = state.evaluate_input(&input_tmp)?;
|
||||
|
||||
self.mutator_mut().post_exec(interesting, i as i32)?;
|
||||
|
||||
if interesting {
|
||||
corpus.add(Testcase::new(input_tmp).into());
|
||||
state.corpus_mut().add(Testcase::new(input_tmp).into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -62,28 +61,25 @@ where
|
||||
}
|
||||
|
||||
/// The default mutational stage
|
||||
pub struct DefaultMutationalStage<C, I, R, M, E>
|
||||
pub struct DefaultMutationalStage<M, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R = R>,
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
M: Mutator<C, I, R = R>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
rand: Rc<RefCell<R>>,
|
||||
executor: Rc<RefCell<E>>,
|
||||
mutator: M,
|
||||
_phantom_corpus: PhantomData<C>,
|
||||
_phantom_input: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<C, I, R, M, E> HasRand for DefaultMutationalStage<C, I, R, M, E>
|
||||
impl<M, C, I, R> HasRand for DefaultMutationalStage<M, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R = R>,
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
M: Mutator<C, I, R = R>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
type R = R;
|
||||
|
||||
@ -92,13 +88,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, I, R, M, E> MutationalStage<C, I, M, E> for DefaultMutationalStage<C, I, R, M, E>
|
||||
impl<M, S, C, E, I, R> MutationalStage<M, S, C, E, I> for DefaultMutationalStage<M, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R = R>,
|
||||
S: State<C, E, I>,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
M: Mutator<C, I, R = R>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
/// The mutator, added to this stage
|
||||
fn mutator(&self) -> &M {
|
||||
@ -109,42 +106,37 @@ where
|
||||
fn mutator_mut(&mut self) -> &mut M {
|
||||
&mut self.mutator
|
||||
}
|
||||
|
||||
fn executor(&self) -> &Rc<RefCell<E>> {
|
||||
&self.executor
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, I, R, M, E> Stage<C, I> for DefaultMutationalStage<C, I, R, M, E>
|
||||
impl<M, S, C, E, I, R> Stage<S, C, E, I> for DefaultMutationalStage<M, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R = R>,
|
||||
S: State<C, E, I>,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
M: Mutator<C, I, R = R>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
fn perform(
|
||||
&mut self,
|
||||
testcase: Rc<RefCell<Testcase<I>>>,
|
||||
corpus: &mut C,
|
||||
state: &mut S,
|
||||
) -> Result<(), AflError> {
|
||||
self.perform_mutational(testcase, corpus)
|
||||
self.perform_mutational(testcase, state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, I, R, M, E> DefaultMutationalStage<C, I, R, M, E>
|
||||
impl<M, C, I, R> DefaultMutationalStage<M, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R = R>,
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
M: Mutator<C, I, R = R>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
/// Creates a new default mutational stage
|
||||
pub fn new(rand: &Rc<RefCell<R>>, executor: &Rc<RefCell<E>>, mutator: M) -> Self {
|
||||
pub fn new(rand: &Rc<RefCell<R>>, mutator: M) -> Self {
|
||||
DefaultMutationalStage {
|
||||
rand: Rc::clone(rand),
|
||||
executor: Rc::clone(executor),
|
||||
mutator: mutator,
|
||||
_phantom_corpus: PhantomData,
|
||||
_phantom_input: PhantomData,
|
||||
|
Loading…
x
Reference in New Issue
Block a user