merged state and corpus

This commit is contained in:
Dominik Maier 2021-02-05 00:33:33 +01:00
parent 2440aaedfc
commit e2c4ed95e6
12 changed files with 335 additions and 305 deletions

1
.gitignore vendored
View File

@ -15,3 +15,4 @@ perf.data
perf.data.old perf.data.old
.vscode .vscode
test.dict

View File

@ -213,11 +213,7 @@ where
where where
ST: Stats; ST: Stats;
/// This method will be called in the clients after handle_in_broker (unless BrokerEventResult::Handled) was returned in handle_in_broker /// This method will be called in the clients after handle_in_broker (unless BrokerEventResult::Handled) was returned in handle_in_broker
fn handle_in_client<C, FT, R>( fn handle_in_client<C, FT, R>(self, state: &mut State<C, I, R, FT>) -> Result<(), AflError>
self,
state: &mut State<I, R, FT>,
corpus: &mut C,
) -> Result<(), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -233,11 +229,7 @@ where
/// Lookup for incoming events and process them. /// Lookup for incoming events and process them.
/// Return the number of processes events or an error /// Return the number of processes events or an error
fn process<C, FT, R>( fn process<C, FT, R>(&mut self, state: &mut State<C, I, R, FT>) -> Result<usize, AflError>
&mut self,
state: &mut State<I, R, FT>,
corpus: &mut C,
) -> Result<usize, AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -298,11 +290,7 @@ impl<I> EventManager<I> for NopEventManager<I>
where where
I: Input, I: Input,
{ {
fn process<C, FT, R>( fn process<C, FT, R>(&mut self, _state: &mut State<C, I, R, FT>) -> Result<usize, AflError>
&mut self,
_state: &mut State<I, R, FT>,
_corpus: &mut C,
) -> Result<usize, AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -417,11 +405,7 @@ where
} }
#[inline] #[inline]
fn handle_in_client<C, FT, R>( fn handle_in_client<C, FT, R>(self, _state: &mut State<C, I, R, FT>) -> Result<(), AflError>
self,
_state: &mut State<I, R, FT>,
_corpus: &mut C,
) -> Result<(), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -452,11 +436,7 @@ where
ST: Stats, ST: Stats,
//CE: CustomEvent<I, OT>, //CE: CustomEvent<I, OT>,
{ {
fn process<C, FT, R>( fn process<C, FT, R>(&mut self, state: &mut State<C, I, R, FT>) -> Result<usize, AflError>
&mut self,
state: &mut State<I, R, FT>,
corpus: &mut C,
) -> Result<usize, AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -465,7 +445,7 @@ where
let count = self.events.len(); let count = self.events.len();
self.events self.events
.drain(..) .drain(..)
.try_for_each(|event| event.handle_in_client(state, corpus))?; .try_for_each(|event| event.handle_in_client(state))?;
Ok(count) Ok(count)
} }
@ -682,11 +662,7 @@ where
} }
#[inline] #[inline]
fn handle_in_client<C, FT, R>( fn handle_in_client<C, FT, R>(self, state: &mut State<C, I, R, FT>) -> Result<(), AflError>
self,
state: &mut State<I, R, FT>,
corpus: &mut C,
) -> Result<(), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -707,7 +683,7 @@ where
let interestingness = state.is_interesting(input.as_ref(), &observers)?; let interestingness = state.is_interesting(input.as_ref(), &observers)?;
match input { match input {
Ptr::Owned(b) => { Ptr::Owned(b) => {
state.add_if_interesting(corpus, *b, interestingness)?; state.add_if_interesting(*b, interestingness)?;
} }
_ => {} _ => {}
}; };
@ -894,11 +870,7 @@ where
ST: Stats, ST: Stats,
//CE: CustomEvent<I>, //CE: CustomEvent<I>,
{ {
fn process<C, FT, R>( fn process<C, FT, R>(&mut self, state: &mut State<C, I, R, FT>) -> Result<usize, AflError>
&mut self,
state: &mut State<I, R, FT>,
corpus: &mut C,
) -> Result<usize, AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -919,7 +891,7 @@ where
sender_id: sender_id, sender_id: sender_id,
kind: kind, kind: kind,
}; };
event.handle_in_client(state, corpus)?; event.handle_in_client(state)?;
count += 1; count += 1;
} }
None => break count, None => break count,

View File

@ -50,8 +50,7 @@ where
#[inline] #[inline]
fn pre_exec<R, FT, C, EM>( fn pre_exec<R, FT, C, EM>(
&mut self, &mut self,
_state: &State<I, R, FT>, _state: &State<C, I, R, FT>,
_corpus: &C,
_event_mgr: &mut EM, _event_mgr: &mut EM,
_input: &I, _input: &I,
) -> Result<(), AflError> ) -> Result<(), AflError>
@ -64,7 +63,7 @@ where
#[cfg(unix)] #[cfg(unix)]
#[cfg(feature = "std")] #[cfg(feature = "std")]
unsafe { unsafe {
set_oncrash_ptrs::<EM, C, OT, FT, I, R>(_state, _corpus, _event_mgr, _input); set_oncrash_ptrs::<EM, C, OT, FT, I, R>(_state, _event_mgr, _input);
} }
Ok(()) Ok(())
} }
@ -72,8 +71,7 @@ where
#[inline] #[inline]
fn post_exec<R, FT, C, EM>( fn post_exec<R, FT, C, EM>(
&mut self, &mut self,
_state: &State<I, R, FT>, _state: &State<C, I, R, FT>,
_corpus: &C,
_event_mgr: &mut EM, _event_mgr: &mut EM,
_input: &I, _input: &I,
) -> Result<(), AflError> ) -> Result<(), AflError>
@ -142,8 +140,7 @@ where
name: &'static str, name: &'static str,
harness_fn: HarnessFunction<Self>, harness_fn: HarnessFunction<Self>,
observers: OT, observers: OT,
_state: &State<I, R, FT>, _state: &mut State<C, I, R, FT>,
_corpus: &C,
_event_mgr: &mut EM, _event_mgr: &mut EM,
) -> Self ) -> Self
where where
@ -211,7 +208,6 @@ pub mod unix_signals {
/// Pointers to values only needed on crash. As the program will not continue after a crash, /// Pointers to values only needed on crash. As the program will not continue after a crash,
/// we should (tm) be okay with raw pointers here, /// we should (tm) be okay with raw pointers here,
static mut CORPUS_PTR: *const c_void = ptr::null_mut();
static mut STATE_PTR: *const c_void = ptr::null_mut(); static mut STATE_PTR: *const c_void = ptr::null_mut();
static mut EVENT_MGR_PTR: *mut c_void = ptr::null_mut(); static mut EVENT_MGR_PTR: *mut c_void = ptr::null_mut();
/// The (unsafe) pointer to the current inmem input, for the current run. /// The (unsafe) pointer to the current inmem input, for the current run.
@ -245,7 +241,6 @@ pub mod unix_signals {
let _ = stdout().flush(); let _ = stdout().flush();
/*let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); /*let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap();
let corpus = (CORPUS_PTR as *const C).as_ref().unwrap();
let state = (EVENT_MGR_PTR as *const State<I, R, FT>).as_ref().unwrap(); let state = (EVENT_MGR_PTR as *const State<I, R, FT>).as_ref().unwrap();
let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap(); let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap();
@ -281,7 +276,6 @@ pub mod unix_signals {
} }
/*let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); /*let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap();
let corpus = (CORPUS_PTR as *const C).as_ref().unwrap();
let state = (EVENT_MGR_PTR as *const State<I, R, FT>).as_ref().unwrap(); let state = (EVENT_MGR_PTR as *const State<I, R, FT>).as_ref().unwrap();
let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap(); let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap();
@ -315,8 +309,7 @@ pub mod unix_signals {
#[inline] #[inline]
pub unsafe fn set_oncrash_ptrs<EM, C, OT, FT, I, R>( pub unsafe fn set_oncrash_ptrs<EM, C, OT, FT, I, R>(
state: &State<I, R, FT>, state: &State<C, I, R, FT>,
corpus: &C,
event_mgr: &mut EM, event_mgr: &mut EM,
input: &I, input: &I,
) where ) where
@ -328,7 +321,6 @@ pub mod unix_signals {
R: Rand, R: Rand,
{ {
CURRENT_INPUT_PTR = input as *const _ as *const c_void; CURRENT_INPUT_PTR = input as *const _ as *const c_void;
CORPUS_PTR = corpus as *const _ as *const c_void;
STATE_PTR = state as *const _ as *const c_void; STATE_PTR = state as *const _ as *const c_void;
EVENT_MGR_PTR = event_mgr as *mut _ as *mut c_void; EVENT_MGR_PTR = event_mgr as *mut _ as *mut c_void;
} }
@ -336,7 +328,6 @@ pub mod unix_signals {
#[inline] #[inline]
pub unsafe fn reset_oncrash_ptrs<EM, C, OT, FT, I, R>() { pub unsafe fn reset_oncrash_ptrs<EM, C, OT, FT, I, R>() {
CURRENT_INPUT_PTR = ptr::null(); CURRENT_INPUT_PTR = ptr::null();
CORPUS_PTR = ptr::null();
STATE_PTR = ptr::null(); STATE_PTR = ptr::null();
EVENT_MGR_PTR = ptr::null_mut(); EVENT_MGR_PTR = ptr::null_mut();
} }

View File

@ -84,8 +84,7 @@ where
/// Called right before exexution starts /// Called right before exexution starts
fn pre_exec<R, FT, C, EM>( fn pre_exec<R, FT, C, EM>(
&mut self, &mut self,
_state: &State<I, R, FT>, _state: &State<C, I, R, FT>,
_corpus: &C,
_event_mgr: &mut EM, _event_mgr: &mut EM,
_input: &I, _input: &I,
) -> Result<(), AflError> ) -> Result<(), AflError>
@ -102,8 +101,7 @@ where
/// Called right after execution finished. /// Called right after execution finished.
fn post_exec<R, FT, C, EM>( fn post_exec<R, FT, C, EM>(
&mut self, &mut self,
_state: &State<I, R, FT>, _state: &State<C, I, R, FT>,
_corpus: &C,
_event_mgr: &mut EM, _event_mgr: &mut EM,
_input: &I, _input: &I,
) -> Result<(), AflError> ) -> Result<(), AflError>

View File

@ -3,24 +3,31 @@ pub use scheduled::*;
pub mod mutations; pub mod mutations;
pub use mutations::*; pub use mutations::*;
use crate::{corpus::Corpus, inputs::Input, utils::Rand, AflError}; use crate::{
corpus::Corpus,
inputs::Input,
state::{HasCorpus, HasMetadata},
utils::Rand,
AflError,
};
// TODO mutator stats method that produces something that can be sent with the NewTestcase event // TODO mutator stats method that produces something that can be sent with the NewTestcase event
// We can use it to report which mutations generated the testcase in the broker logs // We can use it to report which mutations generated the testcase in the broker logs
/// A mutator takes input, and mutates it. /// A mutator takes input, and mutates it.
/// Simple as that. /// Simple as that.
pub trait Mutator<C, I, R> pub trait Mutator<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
/// Mutate a given input /// Mutate a given input
fn mutate( fn mutate(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
corpus: &C, state: &mut S,
input: &mut I, input: &mut I,
stage_idx: i32, stage_idx: i32,
) -> Result<(), AflError>; ) -> Result<(), AflError>;
@ -28,6 +35,7 @@ where
/// Post-process given the outcome of the execution /// Post-process given the outcome of the execution
fn post_exec( fn post_exec(
&mut self, &mut self,
_state: &mut S,
_is_interesting: u32, _is_interesting: u32,
_input: &I, _input: &I,
_stage_idx: i32, _stage_idx: i32,

View File

@ -6,11 +6,9 @@ use crate::{
AflError, AflError,
}; };
use std::fs::File;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::{ use std::io::{BufRead, BufReader};
fs::File,
io::{BufRead, BufReader},
};
const ARITH_MAX: u64 = 35; const ARITH_MAX: u64 = 35;
@ -59,23 +57,24 @@ pub enum MutationResult {
// TODO maybe the mutator arg is not needed // TODO maybe the mutator arg is not needed
/// The generic function type that identifies mutations /// The generic function type that identifies mutations
pub type MutationFunction<M, C, I, R> = pub type MutationFunction<I, M, R, S> =
fn(&mut M, &mut R, &C, &mut I) -> Result<MutationResult, AflError>; fn(&mut M, &mut R, &mut S, &mut I) -> Result<MutationResult, AflError>;
pub trait ComposedByMutations<C, I, R> pub trait ComposedByMutations<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
/// Get a mutation by index /// Get a mutation by index
fn mutation_by_idx(&self, index: usize) -> MutationFunction<Self, C, I, R>; fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, R, S>;
/// Get the number of mutations /// Get the number of mutations
fn mutations_count(&self) -> usize; fn mutations_count(&self) -> usize;
/// Add a mutation /// Add a mutation
fn add_mutation(&mut self, mutation: MutationFunction<Self, C, I, R>); fn add_mutation(&mut self, mutation: MutationFunction<I, Self, R, S>);
} }
#[inline] #[inline]
@ -109,10 +108,10 @@ fn mem_set(data: &mut [u8], from: usize, len: usize, val: u8) {
} }
/// Bitflip mutation for inputs with a bytes vector /// Bitflip mutation for inputs with a bytes vector
pub fn mutation_bitflip<M, C, I, R>( pub fn mutation_bitflip<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -131,10 +130,10 @@ where
} }
} }
pub fn mutation_byteflip<M, C, I, R>( pub fn mutation_byteflip<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -153,10 +152,10 @@ where
} }
} }
pub fn mutation_byteinc<M, C, I, R>( pub fn mutation_byteinc<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -176,10 +175,10 @@ where
} }
} }
pub fn mutation_bytedec<M, C, I, R>( pub fn mutation_bytedec<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -199,10 +198,10 @@ where
} }
} }
pub fn mutation_byteneg<M, C, I, R>( pub fn mutation_byteneg<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -221,10 +220,10 @@ where
} }
} }
pub fn mutation_byterand<M, C, I, R>( pub fn mutation_byterand<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -243,10 +242,10 @@ where
} }
} }
pub fn mutation_byteadd<M, C, I, R>( pub fn mutation_byteadd<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -270,10 +269,10 @@ where
} }
} }
pub fn mutation_wordadd<M, C, I, R>( pub fn mutation_wordadd<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -299,10 +298,10 @@ where
} }
} }
pub fn mutation_dwordadd<M, C, I, R>( pub fn mutation_dwordadd<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -328,10 +327,10 @@ where
} }
} }
pub fn mutation_qwordadd<M, C, I, R>( pub fn mutation_qwordadd<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -357,10 +356,10 @@ where
} }
} }
pub fn mutation_byteinteresting<M, C, I, R>( pub fn mutation_byteinteresting<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -380,10 +379,10 @@ where
} }
} }
pub fn mutation_wordinteresting<M, C, I, R>( pub fn mutation_wordinteresting<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -408,10 +407,10 @@ where
} }
} }
pub fn mutation_dwordinteresting<M, C, I, R>( pub fn mutation_dwordinteresting<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -436,10 +435,10 @@ where
} }
} }
pub fn mutation_bytesdelete<M, C, I, R>( pub fn mutation_bytesdelete<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -458,11 +457,11 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesexpand<M, C, I, R>( pub fn mutation_bytesexpand<I, M, R, S>(
// TODO: max_size instead of mutator? // TODO: max_size instead of mutator?
mutator: &mut M, mutator: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -485,10 +484,10 @@ where
/* /*
// Insert a dictionary token // Insert a dictionary token
pub fn mutation_tokeninsert<M, C, I, R>( pub fn mutation_tokeninsert<I, M, R, S>(
mutator: &mut M, mutator: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -512,10 +511,10 @@ where
} }
*/ */
pub fn mutation_bytesinsert<M, C, I, R>( pub fn mutation_bytesinsert<I, M, R, S>(
mutator: &mut M, mutator: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -538,10 +537,10 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesrandinsert<M, C, I, R>( pub fn mutation_bytesrandinsert<I, M, R, S>(
mutator: &mut M, mutator: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -564,10 +563,10 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesset<M, C, I, R>( pub fn mutation_bytesset<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -590,10 +589,10 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesrandset<M, C, I, R>( pub fn mutation_bytesrandset<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -616,10 +615,10 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytescopy<M, C, I, R>( pub fn mutation_bytescopy<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -639,10 +638,10 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesswap<M, C, I, R>( pub fn mutation_bytesswap<I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
_: &C, _: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
@ -681,20 +680,21 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
} }
/// Splicing mutator /// Splicing mutator
pub fn mutation_splice<M, C, I, R>( pub fn mutation_splice<C, I, M, R, S>(
_: &mut M, _: &mut M,
rand: &mut R, rand: &mut R,
corpus: &C, state: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, AflError> ) -> Result<MutationResult, AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
R: Rand, R: Rand,
S: HasCorpus<C>,
{ {
// We don't want to use the testcase we're already using for splicing // We don't want to use the testcase we're already using for splicing
let (other_testcase, idx) = corpus.random_entry(rand)?; let (other_testcase, idx) = state.corpus().random_entry(rand)?;
if idx == corpus.current_testcase().1 { if idx == state.corpus().current_testcase().1 {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
} }
// println!("Input: {:?}, other input: {:?}", input.bytes(), other.bytes()); // println!("Input: {:?}, other input: {:?}", input.bytes(), other.bytes());
@ -847,14 +847,25 @@ pub fn read_dict_file(f: &str, dict: &mut Vec<Vec<u8>>) -> Result<u32, AflError>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::fs;
use crate::mutators::read_dict_file; use crate::mutators::read_dict_file;
#[test] #[test]
fn test_read_dict() { fn test_read_dict() {
println!("For this testcase to success create \"test.dic\"."); let _ = fs::remove_file("test.dict");
let data = r###"
# comment
token1="AAA"
token1="A\x41A"
token2="B"
"###;
fs::write("test.dict", data).expect("Unable to write test.dict");
let mut v: Vec<Vec<u8>> = Vec::new(); let mut v: Vec<Vec<u8>> = Vec::new();
let res = read_dict_file(&"test.dic".to_string(), &mut v).unwrap(); let res = read_dict_file(&"test.dic".to_string(), &mut v).unwrap();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Dictionary entries: {:?}", res); println!("Dictionary entries: {:?}", res);
assert_eq!(res, 2);
let _ = fs::remove_file("test.dict");
} }
} }

View File

@ -5,15 +5,18 @@ use fmt::Debug;
use crate::{ use crate::{
inputs::{HasBytesVec, Input}, inputs::{HasBytesVec, Input},
mutators::{Corpus, *}, mutators::{Corpus, *},
state::{HasCorpus, HasMetadata},
utils::Rand, utils::Rand,
AflError, AflError,
}; };
pub trait ScheduledMutator<C, I, R>: Mutator<C, I, R> + ComposedByMutations<C, I, R> pub trait ScheduledMutator<C, I, R, S>:
Mutator<C, I, R, S> + ComposedByMutations<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
/// Compute the number of iterations used to apply stacked mutations /// Compute the number of iterations used to apply stacked mutations
#[inline] #[inline]
@ -33,35 +36,37 @@ where
fn scheduled_mutate( fn scheduled_mutate(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
corpus: &C, state: &mut S,
input: &mut I, input: &mut I,
_stage_idx: i32, _stage_idx: i32,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
let num = self.iterations(rand, input); let num = self.iterations(rand, input);
for _ in 0..num { for _ in 0..num {
let idx = self.schedule(self.mutations_count(), rand, input); let idx = self.schedule(self.mutations_count(), rand, input);
self.mutation_by_idx(idx)(self, rand, corpus, input)?; self.mutation_by_idx(idx)(self, rand, state, input)?;
} }
Ok(()) Ok(())
} }
} }
#[derive(Clone)] #[derive(Clone)]
pub struct StdScheduledMutator<C, I, R> pub struct StdScheduledMutator<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
mutations: Vec<MutationFunction<Self, C, I, R>>, mutations: Vec<MutationFunction<I, Self, R, S>>,
max_size: usize, max_size: usize,
} }
impl<C, I, R> Debug for StdScheduledMutator<C, I, R> impl<C, I, R, S> Debug for StdScheduledMutator<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
@ -74,31 +79,33 @@ where
} }
} }
impl<C, I, R> Mutator<C, I, R> for StdScheduledMutator<C, I, R> impl<C, I, R, S> Mutator<C, I, R, S> for StdScheduledMutator<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
fn mutate( fn mutate(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
corpus: &C, state: &mut S,
input: &mut I, input: &mut I,
_stage_idx: i32, _stage_idx: i32,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
self.scheduled_mutate(rand, corpus, input, _stage_idx) self.scheduled_mutate(rand, state, input, _stage_idx)
} }
} }
impl<C, I, R> ComposedByMutations<C, I, R> for StdScheduledMutator<C, I, R> impl<C, I, R, S> ComposedByMutations<C, I, R, S> for StdScheduledMutator<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
#[inline] #[inline]
fn mutation_by_idx(&self, index: usize) -> MutationFunction<Self, C, I, R> { fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, R, S> {
self.mutations[index] self.mutations[index]
} }
@ -108,25 +115,27 @@ where
} }
#[inline] #[inline]
fn add_mutation(&mut self, mutation: MutationFunction<Self, C, I, R>) { fn add_mutation(&mut self, mutation: MutationFunction<I, Self, R, S>) {
self.mutations.push(mutation) self.mutations.push(mutation)
} }
} }
impl<C, I, R> ScheduledMutator<C, I, R> for StdScheduledMutator<C, I, R> impl<C, I, R, S> ScheduledMutator<C, I, R, S> for StdScheduledMutator<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
// Just use the default methods // Just use the default methods
} }
impl<C, I, R> HasMaxSize for StdScheduledMutator<C, I, R> impl<C, I, R, S> HasMaxSize for StdScheduledMutator<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
#[inline] #[inline]
fn max_size(&self) -> usize { fn max_size(&self) -> usize {
@ -139,11 +148,12 @@ where
} }
} }
impl<C, I, R> StdScheduledMutator<C, I, R> impl<C, I, R, S> StdScheduledMutator<C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
/// Create a new StdScheduledMutator instance without mutations and corpus /// Create a new StdScheduledMutator instance without mutations and corpus
pub fn new() -> Self { pub fn new() -> Self {
@ -154,7 +164,7 @@ where
} }
/// Create a new StdScheduledMutator instance specifying mutations /// Create a new StdScheduledMutator instance specifying mutations
pub fn with_mutations(mutations: Vec<MutationFunction<Self, C, I, R>>) -> Self { pub fn with_mutations(mutations: Vec<MutationFunction<I, Self, R, S>>) -> Self {
StdScheduledMutator { StdScheduledMutator {
mutations: mutations, mutations: mutations,
max_size: DEFAULT_MAX_SIZE, max_size: DEFAULT_MAX_SIZE,
@ -164,29 +174,31 @@ where
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Schedule some selected byte level mutations given a ScheduledMutator type /// Schedule some selected byte level mutations given a ScheduledMutator type
pub struct HavocBytesMutator<SM, C, I, R> pub struct HavocBytesMutator<SM, C, I, R, S>
where where
SM: ScheduledMutator<C, I, R> + HasMaxSize, SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
scheduled: SM, scheduled: SM,
phantom: PhantomData<(I, R, C)>, phantom: PhantomData<(C, I, R, S)>,
} }
impl<SM, C, I, R> Mutator<C, I, R> for HavocBytesMutator<SM, C, I, R> impl<SM, C, I, R, S> Mutator<C, I, R, S> for HavocBytesMutator<SM, C, I, R, S>
where where
SM: ScheduledMutator<C, I, R> + HasMaxSize, SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
/// Mutate bytes /// Mutate bytes
fn mutate( fn mutate(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
corpus: &C, state: &mut S,
input: &mut I, input: &mut I,
_stage_idx: i32, _stage_idx: i32,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
@ -210,18 +222,19 @@ where
11 => mutation_dwordinteresting, 11 => mutation_dwordinteresting,
_ => mutation_splice, _ => mutation_splice,
}; };
mutation(self, rand, corpus, input)?; mutation(self, rand, state, input)?;
} }
Ok(()) Ok(())
} }
} }
impl<SM, C, I, R> HasMaxSize for HavocBytesMutator<SM, C, I, R> impl<SM, C, I, R, S> HasMaxSize for HavocBytesMutator<SM, C, I, R, S>
where where
SM: ScheduledMutator<C, I, R> + HasMaxSize, SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
#[inline] #[inline]
fn max_size(&self) -> usize { fn max_size(&self) -> usize {
@ -234,12 +247,13 @@ where
} }
} }
impl<SM, C, I, R> HavocBytesMutator<SM, C, I, R> impl<SM, C, I, R, S> HavocBytesMutator<SM, C, I, R, S>
where where
SM: ScheduledMutator<C, I, R> + HasMaxSize, SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
/// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap /// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap
pub fn new(mut scheduled: SM) -> Self { pub fn new(mut scheduled: SM) -> Self {
@ -252,15 +266,16 @@ where
} }
} }
impl<C, I, R> HavocBytesMutator<StdScheduledMutator<C, I, R>, C, I, R> impl<C, I, R, S> HavocBytesMutator<StdScheduledMutator<C, I, R, S>, C, I, R, S>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
R: Rand, R: Rand,
S: HasCorpus<C> + HasMetadata,
{ {
/// Create a new HavocBytesMutator instance wrapping StdScheduledMutator /// Create a new HavocBytesMutator instance wrapping StdScheduledMutator
pub fn new_default() -> Self { pub fn new_default() -> Self {
let mut scheduled = StdScheduledMutator::<C, I, R>::new(); let mut scheduled = StdScheduledMutator::<C, I, R, S>::new();
scheduled.add_mutation(mutation_bitflip); scheduled.add_mutation(mutation_bitflip);
scheduled.add_mutation(mutation_byteflip); scheduled.add_mutation(mutation_byteflip);
scheduled.add_mutation(mutation_byteinc); scheduled.add_mutation(mutation_byteinc);
@ -309,6 +324,7 @@ mod tests {
inputs::BytesInput, inputs::BytesInput,
inputs::HasBytesVec, inputs::HasBytesVec,
mutators::scheduled::{mutation_splice, StdScheduledMutator}, mutators::scheduled::{mutation_splice, StdScheduledMutator},
state::State,
utils::{Rand, XKCDRand}, utils::{Rand, XKCDRand},
}; };
@ -325,10 +341,17 @@ mod tests {
.expect("Corpus did not contain entries"); .expect("Corpus did not contain entries");
let mut input = testcase.borrow_mut().load_input().unwrap().clone(); let mut input = testcase.borrow_mut().load_input().unwrap().clone();
rand.set_seed(5); let mut state = State::new(corpus, ());
let mut mutator = StdScheduledMutator::<InMemoryCorpus<BytesInput, XKCDRand>, _, _>::new();
mutation_splice(&mut mutator, &mut rand, &mut corpus, &mut input).unwrap(); rand.set_seed(5);
let mut mutator = StdScheduledMutator::<
InMemoryCorpus<BytesInput, XKCDRand>,
_,
_,
State<_, _, _, ()>,
>::new();
mutation_splice(&mut mutator, &mut rand, &mut state, &mut input).unwrap();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("{:?}", input.bytes()); println!("{:?}", input.bytes());

View File

@ -16,7 +16,7 @@ use crate::{
/// A stage is one step in the fuzzing process. /// A stage is one step in the fuzzing process.
/// Multiple stages will be scheduled one by one for each input. /// Multiple stages will be scheduled one by one for each input.
pub trait Stage<EM, E, OT, FT, C, I, R> pub trait Stage<C, E, EM, FT, I, OT, R>
where where
EM: EventManager<I>, EM: EventManager<I>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
@ -31,8 +31,7 @@ where
&mut self, &mut self,
rand: &mut R, rand: &mut R,
executor: &mut E, executor: &mut E,
state: &mut State<I, R, FT>, state: &mut State<C, I, R, FT>,
corpus: &mut C,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError>; ) -> Result<(), AflError>;
@ -52,13 +51,12 @@ where
&mut self, &mut self,
rand: &mut R, rand: &mut R,
executor: &mut E, executor: &mut E,
state: &mut State<I, R, FT>, state: &mut State<C, I, R, FT>,
corpus: &mut C,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError>; ) -> Result<(), AflError>;
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>)); fn for_each(&self, f: fn(&dyn Stage<C, E, EM, FT, I, OT, R>));
fn for_each_mut(&mut self, f: fn(&mut dyn Stage<EM, E, OT, FT, C, I, R>)); fn for_each_mut(&mut self, f: fn(&mut dyn Stage<C, E, EM, FT, I, OT, R>));
} }
impl<EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for () impl<EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for ()
@ -75,20 +73,19 @@ where
&mut self, &mut self,
_rand: &mut R, _rand: &mut R,
_executor: &mut E, _executor: &mut E,
_state: &mut State<I, R, FT>, _state: &mut State<C, I, R, FT>,
_corpus: &mut C,
_manager: &mut EM, _manager: &mut EM,
_corpus_idx: usize, _corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
Ok(()) Ok(())
} }
fn for_each(&self, _f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>)) {} fn for_each(&self, _f: fn(&dyn Stage<C, E, EM, FT, I, OT, R>)) {}
fn for_each_mut(&mut self, _f: fn(&mut dyn Stage<EM, E, OT, FT, C, I, R>)) {} fn for_each_mut(&mut self, _f: fn(&mut dyn Stage<C, E, EM, FT, I, OT, R>)) {}
} }
impl<Head, Tail, EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for (Head, Tail) impl<Head, Tail, EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for (Head, Tail)
where where
Head: Stage<EM, E, OT, FT, C, I, R>, Head: Stage<C, E, EM, FT, I, OT, R>,
Tail: StagesTuple<EM, E, OT, FT, C, I, R> + TupleList, Tail: StagesTuple<EM, E, OT, FT, C, I, R> + TupleList,
EM: EventManager<I>, EM: EventManager<I>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
@ -102,23 +99,21 @@ where
&mut self, &mut self,
rand: &mut R, rand: &mut R,
executor: &mut E, executor: &mut E,
state: &mut State<I, R, FT>, state: &mut State<C, I, R, FT>,
corpus: &mut C,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
self.0 self.0.perform(rand, executor, state, manager, corpus_idx)?;
.perform(rand, executor, state, corpus, manager, corpus_idx)?;
self.1 self.1
.perform_all(rand, executor, state, corpus, manager, corpus_idx) .perform_all(rand, executor, state, manager, corpus_idx)
} }
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>)) { fn for_each(&self, f: fn(&dyn Stage<C, E, EM, FT, I, OT, R>)) {
f(&self.0); f(&self.0);
self.1.for_each(f) self.1.for_each(f)
} }
fn for_each_mut(&mut self, f: fn(&mut dyn Stage<EM, E, OT, FT, C, I, R>)) { fn for_each_mut(&mut self, f: fn(&mut dyn Stage<C, E, EM, FT, I, OT, R>)) {
f(&mut self.0); f(&mut self.0);
self.1.for_each_mut(f) self.1.for_each_mut(f)
} }

View File

@ -9,7 +9,7 @@ use crate::{
observers::ObserversTuple, observers::ObserversTuple,
stages::Corpus, stages::Corpus,
stages::Stage, stages::Stage,
state::State, state::{HasCorpus, State},
utils::Rand, utils::Rand,
AflError, AflError,
}; };
@ -19,9 +19,9 @@ use crate::{
/// A Mutational stage is the stage in a fuzzing run that mutates inputs. /// A Mutational stage is the stage in a fuzzing run that mutates inputs.
/// Mutational stages will usually have a range of mutations that are /// Mutational stages will usually have a range of mutations that are
/// being applied to the input one by one, between executions. /// being applied to the input one by one, between executions.
pub trait MutationalStage<M, EM, E, OT, FT, C, I, R>: Stage<EM, E, OT, FT, C, I, R> pub trait MutationalStage<C, E, EM, FT, I, M, OT, R>: Stage<C, E, EM, FT, I, OT, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R, State<C, I, R, FT>>,
EM: EventManager<I>, EM: EventManager<I>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
@ -48,21 +48,25 @@ where
&mut self, &mut self,
rand: &mut R, rand: &mut R,
executor: &mut E, executor: &mut E,
state: &mut State<I, R, FT>, state: &mut State<C, I, R, FT>,
corpus: &mut C,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
let num = self.iterations(rand); let num = self.iterations(rand);
for i in 0..num { for i in 0..num {
let mut input_mut = corpus.get(corpus_idx).borrow_mut().load_input()?.clone(); let mut input_mut = state
.corpus()
.get(corpus_idx)
.borrow_mut()
.load_input()?
.clone();
self.mutator_mut() self.mutator_mut()
.mutate(rand, corpus, &mut input_mut, i as i32)?; .mutate(rand, state, &mut input_mut, i as i32)?;
let fitness = state.evaluate_input(&input_mut, executor, corpus, manager)?; let fitness = state.evaluate_input(&input_mut, executor, manager)?;
self.mutator_mut() self.mutator_mut()
.post_exec(fitness, &input_mut, i as i32)?; .post_exec(state, fitness, &input_mut, i as i32)?;
let observers = executor.observers(); let observers = executor.observers();
@ -73,8 +77,13 @@ where
// if needed by particular cases // if needed by particular cases
if fitness > 0 { if fitness > 0 {
// TODO decouple events manager and engine // TODO decouple events manager and engine
manager.new_testcase(&input_mut, observers, corpus.count() + 1, "test".into())?; manager.new_testcase(
state.add_if_interesting(corpus, input_mut, fitness)?; &input_mut,
observers,
state.corpus().count() + 1,
"test".into(),
)?;
state.add_if_interesting(input_mut, fitness)?;
// let _ = corpus.add(testcase); // let _ = corpus.add(testcase);
} else { } else {
state.discard_input(&input_mut)?; state.discard_input(&input_mut)?;
@ -86,31 +95,31 @@ where
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// The default mutational stage /// The default mutational stage
pub struct StdMutationalStage<M, EM, E, OT, FT, C, I, R> pub struct StdMutationalStage<C, E, EM, FT, I, M, OT, R>
where where
M: Mutator<C, I, R>,
EM: EventManager<I>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I> + HasObservers<OT>,
EM: EventManager<I>,
FT: FeedbacksTuple<I>,
I: Input, I: Input,
M: Mutator<C, I, R, State<C, I, R, FT>>,
OT: ObserversTuple,
R: Rand, R: Rand,
{ {
mutator: M, mutator: M,
phantom: PhantomData<(EM, E, OT, FT, C, I, R)>, phantom: PhantomData<(EM, E, OT, FT, C, I, R)>,
} }
impl<M, EM, E, OT, FT, C, I, R> MutationalStage<M, EM, E, OT, FT, C, I, R> impl<C, E, EM, FT, I, M, OT, R> MutationalStage<C, E, EM, FT, I, M, OT, R>
for StdMutationalStage<M, EM, E, OT, FT, C, I, R> for StdMutationalStage<C, E, EM, FT, I, M, OT, R>
where where
M: Mutator<C, I, R>,
EM: EventManager<I>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I> + HasObservers<OT>,
EM: EventManager<I>,
FT: FeedbacksTuple<I>,
I: Input, I: Input,
M: Mutator<C, I, R, State<C, I, R, FT>>,
OT: ObserversTuple,
R: Rand, R: Rand,
{ {
/// The mutator, added to this stage /// The mutator, added to this stage
@ -126,10 +135,10 @@ where
} }
} }
impl<M, EM, E, OT, FT, C, I, R> Stage<EM, E, OT, FT, C, I, R> impl<C, E, EM, FT, I, M, OT, R> Stage<C, E, EM, FT, I, OT, R>
for StdMutationalStage<M, EM, E, OT, FT, C, I, R> for StdMutationalStage<C, E, EM, FT, I, M, OT, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R, State<C, I, R, FT>>,
EM: EventManager<I>, EM: EventManager<I>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
@ -143,18 +152,17 @@ where
&mut self, &mut self,
rand: &mut R, rand: &mut R,
executor: &mut E, executor: &mut E,
state: &mut State<I, R, FT>, state: &mut State<C, I, R, FT>,
corpus: &mut C,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
self.perform_mutational(rand, executor, state, corpus, manager, corpus_idx) self.perform_mutational(rand, executor, state, manager, corpus_idx)
} }
} }
impl<M, EM, E, OT, FT, C, I, R> StdMutationalStage<M, EM, E, OT, FT, C, I, R> impl<C, E, EM, FT, I, M, OT, R> StdMutationalStage<C, E, EM, FT, I, M, OT, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R, State<C, I, R, FT>>,
EM: EventManager<I>, EM: EventManager<I>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,

View File

@ -26,24 +26,53 @@ use crate::{
use crate::inputs::bytes::BytesInput; use crate::inputs::bytes::BytesInput;
pub trait StateMetadata: Debug { pub trait StateMetadata: Debug {
/// The name of this metadata - used to find it in the list of avaliable metadatas /// The name of this metadata - used to find it in the list of avaliable metadata
fn name(&self) -> &'static str; fn name(&self) -> &'static str;
} }
/// Trait for elements offering a corpus
pub trait HasCorpus<C> {
/// The testcase corpus
fn corpus(&self) -> &C;
/// The testcase corpus (mut)
fn corpus_mut(&mut self) -> &mut C;
}
/// Trait for elements offering metadata
pub trait HasMetadata {
/// A map, storing all metadata
fn metadata(&self) -> &SerdeAnyMap;
/// A map, storing all metadata (mut)
fn metadata_mut(&mut self) -> &mut SerdeAnyMap;
/// Add a metadata to the metadata map
#[inline]
fn add_metadata<M>(&mut self, meta: M)
where
M: SerdeAny,
{
self.metadata_mut().insert(meta);
}
}
/// The state a fuzz run. /// The state a fuzz run.
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "FT: serde::de::DeserializeOwned")] #[serde(bound = "FT: serde::de::DeserializeOwned")]
pub struct State<I, R, FT> pub struct State<C, I, R, FT>
where where
C: Corpus<I, R>,
I: Input, I: Input,
R: Rand,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
{ {
/// How many times the executor ran the harness/target /// How many times the executor ran the harness/target
executions: usize, executions: usize,
/// The corpus
corpus: C,
/// At what time the fuzzing started /// At what time the fuzzing started
start_time: u64, start_time: u64,
/// Metadata stored for this state by one of the components /// Metadata stored for this state by one of the components
metadatas: SerdeAnyMap, metadata: SerdeAnyMap,
// additional_corpuses, maybe another TupleList? // additional_corpuses, maybe another TupleList?
// Feedbacks used to evaluate an input // Feedbacks used to evaluate an input
feedbacks: FT, feedbacks: FT,
@ -51,15 +80,15 @@ where
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<R, FT> State<BytesInput, R, FT> impl<C, R, FT> State<C, BytesInput, R, FT>
where where
C: Corpus<BytesInput, R>,
R: Rand, R: Rand,
FT: FeedbacksTuple<BytesInput>, FT: FeedbacksTuple<BytesInput>,
{ {
pub fn load_from_directory<G, C, E, OT, EM>( pub fn load_from_directory<G, E, OT, EM>(
&mut self, &mut self,
executor: &mut E, executor: &mut E,
corpus: &mut C,
generator: &mut G, generator: &mut G,
manager: &mut EM, manager: &mut EM,
in_dir: &Path, in_dir: &Path,
@ -86,22 +115,21 @@ where
println!("Loading file {:?} ...", &path); println!("Loading file {:?} ...", &path);
let bytes = fs::read(&path)?; let bytes = fs::read(&path)?;
let input = BytesInput::new(bytes); let input = BytesInput::new(bytes);
let fitness = self.evaluate_input(&input, executor, corpus, manager)?; let fitness = self.evaluate_input(&input, executor, manager)?;
if self.add_if_interesting(corpus, input, fitness)?.is_none() { if self.add_if_interesting(input, fitness)?.is_none() {
println!("File {:?} was not interesting, skipped.", &path); println!("File {:?} was not interesting, skipped.", &path);
} }
} else if attr.is_dir() { } else if attr.is_dir() {
self.load_from_directory(executor, corpus, generator, manager, &path)?; self.load_from_directory(executor, generator, manager, &path)?;
} }
} }
Ok(()) Ok(())
} }
pub fn load_initial_inputs<G, C, E, OT, EM>( pub fn load_initial_inputs<G, E, OT, EM>(
&mut self, &mut self,
executor: &mut E, executor: &mut E,
corpus: &mut C,
generator: &mut G, generator: &mut G,
manager: &mut EM, manager: &mut EM,
in_dirs: &[PathBuf], in_dirs: &[PathBuf],
@ -114,19 +142,59 @@ where
EM: EventManager<BytesInput>, EM: EventManager<BytesInput>,
{ {
for in_dir in in_dirs { for in_dir in in_dirs {
self.load_from_directory(executor, corpus, generator, manager, in_dir)?; self.load_from_directory(executor, generator, manager, in_dir)?;
} }
manager.log( manager.log(
0, 0,
format!("Loaded {} initial testcases.", corpus.count()), // get corpus count format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
)?; )?;
manager.process(self, corpus)?; manager.process(self)?;
Ok(()) Ok(())
} }
} }
impl<I, R, FT> State<I, R, FT> impl<C, I, R, FT> HasCorpus<C> for State<C, I, R, FT>
where where
C: Corpus<I, R>,
I: Input,
R: Rand,
FT: FeedbacksTuple<I>,
{
/// Returns the corpus
fn corpus(&self) -> &C {
&self.corpus
}
/// Returns the mutable corpus
fn corpus_mut(&mut self) -> &mut C {
&mut self.corpus
}
}
/// Trait for elements offering metadata
impl<C, I, R, FT> HasMetadata for State<C, I, R, FT>
where
C: Corpus<I, R>,
I: Input,
R: Rand,
FT: FeedbacksTuple<I>,
{
/// Get all the metadata into an HashMap
#[inline]
fn metadata(&self) -> &SerdeAnyMap {
&self.metadata
}
/// Get all the metadata into an HashMap (mutable)
#[inline]
fn metadata_mut(&mut self) -> &mut SerdeAnyMap {
&mut self.metadata
}
}
impl<C, I, R, FT> State<C, I, R, FT>
where
C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -151,7 +219,6 @@ where
pub fn set_start_time(&mut self, ms: u64) { pub fn set_start_time(&mut self, ms: u64) {
self.start_time = ms self.start_time = ms
} }
// TODO as this is done in the event manager, we can remove it // TODO as this is done in the event manager, we can remove it
#[inline] #[inline]
pub fn executions_over_seconds(&self) -> u64 { pub fn executions_over_seconds(&self) -> u64 {
@ -167,27 +234,6 @@ where
} }
} }
/// Get all the metadatas into an HashMap
#[inline]
pub fn metadatas(&self) -> &SerdeAnyMap {
&self.metadatas
}
/// Get all the metadatas into an HashMap (mutable)
#[inline]
pub fn metadatas_mut(&mut self) -> &mut SerdeAnyMap {
&mut self.metadatas
}
/// Add a metadata
#[inline]
pub fn add_metadata<M>(&mut self, meta: M)
where
M: SerdeAny,
{
self.metadatas.insert(meta);
}
/// Returns vector of feebacks /// Returns vector of feebacks
#[inline] #[inline]
pub fn feedbacks(&self) -> &FT { pub fn feedbacks(&self) -> &FT {
@ -210,11 +256,10 @@ where
} }
/// Runs the input and triggers observers and feedback /// Runs the input and triggers observers and feedback
pub fn evaluate_input<C, E, EM, OT>( pub fn evaluate_input<E, EM, OT>(
&mut self, &mut self,
input: &I, input: &I,
executor: &mut E, executor: &mut E,
corpus: &C,
event_mgr: &mut EM, event_mgr: &mut EM,
) -> Result<u32, AflError> ) -> Result<u32, AflError>
where where
@ -225,9 +270,9 @@ where
{ {
executor.pre_exec_observers()?; executor.pre_exec_observers()?;
executor.pre_exec(&self, corpus, event_mgr, input)?; executor.pre_exec(&self, event_mgr, input)?;
executor.run_target(input)?; executor.run_target(input)?;
executor.post_exec(&self, corpus, event_mgr, input)?; executor.post_exec(&self, event_mgr, input)?;
self.set_executions(self.executions() + 1); self.set_executions(self.executions() + 1);
executor.post_exec_observers()?; executor.post_exec_observers()?;
@ -270,29 +315,23 @@ where
/// Adds this input to the corpus, if it's intersting /// Adds this input to the corpus, if it's intersting
#[inline] #[inline]
pub fn add_if_interesting<C>( pub fn add_if_interesting(&mut self, input: I, fitness: u32) -> Result<Option<usize>, AflError>
&mut self,
corpus: &mut C,
input: I,
fitness: u32,
) -> Result<Option<usize>, AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
{ {
if fitness > 0 { if fitness > 0 {
let testcase = self.input_to_testcase(input, fitness)?; let testcase = self.input_to_testcase(input, fitness)?;
Ok(Some(corpus.add(testcase))) Ok(Some(self.corpus_mut().add(testcase)))
} else { } else {
self.discard_input(&input)?; self.discard_input(&input)?;
Ok(None) Ok(None)
} }
} }
pub fn generate_initial_inputs<G, C, E, OT, EM>( pub fn generate_initial_inputs<G, E, OT, EM>(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
executor: &mut E, executor: &mut E,
corpus: &mut C,
generator: &mut G, generator: &mut G,
manager: &mut EM, manager: &mut EM,
num: usize, num: usize,
@ -307,8 +346,8 @@ where
let mut added = 0; let mut added = 0;
for _ in 0..num { for _ in 0..num {
let input = generator.generate(rand)?; let input = generator.generate(rand)?;
let fitness = self.evaluate_input(&input, executor, corpus, manager)?; let fitness = self.evaluate_input(&input, executor, manager)?;
if !self.add_if_interesting(corpus, input, fitness)?.is_none() { if !self.add_if_interesting(input, fitness)?.is_none() {
added += 1; added += 1;
} }
} }
@ -316,15 +355,16 @@ where
0, 0,
format!("Loaded {} over {} initial testcases", added, num), format!("Loaded {} over {} initial testcases", added, num),
)?; )?;
manager.process(self, corpus)?; manager.process(self)?;
Ok(()) Ok(())
} }
pub fn new(feedbacks: FT) -> Self { pub fn new(corpus: C, feedbacks: FT) -> Self {
Self { Self {
corpus,
executions: 0, executions: 0,
start_time: current_milliseconds(), start_time: current_milliseconds(),
metadatas: SerdeAnyMap::default(), metadata: SerdeAnyMap::default(),
feedbacks: feedbacks, feedbacks: feedbacks,
phantom: PhantomData, phantom: PhantomData,
} }
@ -350,16 +390,15 @@ where
&mut self, &mut self,
rand: &mut R, rand: &mut R,
executor: &mut E, executor: &mut E,
state: &mut State<I, R, FT>, state: &mut State<C, I, R, FT>,
corpus: &mut C,
manager: &mut EM, manager: &mut EM,
) -> Result<usize, AflError> { ) -> Result<usize, AflError> {
let (_, idx) = corpus.next(rand)?; let (_, idx) = state.corpus_mut().next(rand)?;
self.stages_mut() self.stages_mut()
.perform_all(rand, executor, state, corpus, manager, idx)?; .perform_all(rand, executor, state, manager, idx)?;
manager.process(state, corpus)?; manager.process(state)?;
Ok(idx) Ok(idx)
} }
@ -367,13 +406,12 @@ where
&mut self, &mut self,
rand: &mut R, rand: &mut R,
executor: &mut E, executor: &mut E,
state: &mut State<I, R, FT>, state: &mut State<C, I, R, FT>,
corpus: &mut C,
manager: &mut EM, manager: &mut EM,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
let mut last = current_milliseconds(); let mut last = current_milliseconds();
loop { loop {
self.fuzz_one(rand, executor, state, corpus, manager)?; self.fuzz_one(rand, executor, state, manager)?;
let cur = current_milliseconds(); let cur = current_milliseconds();
if cur - last > 60 * 100 { if cur - last > 60 * 100 {
last = cur; last = cur;
@ -458,6 +496,8 @@ mod tests {
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::events::{LoggerEventManager, SimpleStats}; use crate::events::{LoggerEventManager, SimpleStats};
use super::HasCorpus;
fn harness<E: Executor<I>, I: Input>(_executor: &E, _buf: &[u8]) -> ExitKind { fn harness<E: Executor<I>, I: Input>(_executor: &E, _buf: &[u8]) -> ExitKind {
ExitKind::Ok ExitKind::Ok
} }
@ -470,7 +510,7 @@ mod tests {
let testcase = Testcase::new(vec![0; 4]).into(); let testcase = Testcase::new(vec![0; 4]).into();
corpus.add(testcase); corpus.add(testcase);
let mut state = State::new(tuple_list!()); let mut state = State::new(corpus, tuple_list!());
let mut event_manager = LoggerEventManager::new(SimpleStats::new(|s| { let mut event_manager = LoggerEventManager::new(SimpleStats::new(|s| {
println!("{}", s); println!("{}", s);
@ -481,8 +521,7 @@ mod tests {
harness, harness,
tuple_list!(), tuple_list!(),
//Box::new(|_, _, _, _, _| ()), //Box::new(|_, _, _, _, _| ()),
&state, &mut state,
&corpus,
&mut event_manager, &mut event_manager,
); );
@ -493,24 +532,18 @@ mod tests {
for i in 0..1000 { for i in 0..1000 {
fuzzer fuzzer
.fuzz_one( .fuzz_one(&mut rand, &mut executor, &mut state, &mut event_manager)
&mut rand,
&mut executor,
&mut state,
&mut corpus,
&mut event_manager,
)
.expect(&format!("Error in iter {}", i)); .expect(&format!("Error in iter {}", i));
} }
let state_serialized = postcard::to_allocvec(&state).unwrap(); let state_serialized = postcard::to_allocvec(&state).unwrap();
let state_deserialized: State<BytesInput, StdRand, ()> = let state_deserialized: State<InMemoryCorpus<BytesInput, _>, BytesInput, StdRand, ()> =
postcard::from_bytes(state_serialized.as_slice()).unwrap(); postcard::from_bytes(state_serialized.as_slice()).unwrap();
assert_eq!(state.executions, state_deserialized.executions); assert_eq!(state.executions, state_deserialized.executions);
let corpus_serialized = postcard::to_allocvec(&corpus).unwrap(); let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap();
let corpus_deserialized: InMemoryCorpus<BytesInput, StdRand> = let corpus_deserialized: InMemoryCorpus<BytesInput, StdRand> =
postcard::from_bytes(corpus_serialized.as_slice()).unwrap(); postcard::from_bytes(corpus_serialized.as_slice()).unwrap();
assert_eq!(corpus.count(), corpus_deserialized.count()); assert_eq!(state.corpus().count(), corpus_deserialized.count());
} }
} }

View File

@ -25,8 +25,7 @@ pub type StdRand = RomuTrioRand;
/// On top, add the current llmp event manager instance to be restored /// On top, add the current llmp event manager instance to be restored
/// This method is needed when the fuzzer run crashes and has to restart. /// This method is needed when the fuzzer run crashes and has to restart.
pub fn serialize_state_corpus_mgr<C, FT, I, R, SH, ST>( pub fn serialize_state_corpus_mgr<C, FT, I, R, SH, ST>(
state: &State<I, R, FT>, state: &State<C, I, R, FT>,
corpus: &C,
mgr: &LlmpEventManager<I, SH, ST>, mgr: &LlmpEventManager<I, SH, ST>,
) -> Result<Vec<u8>, AflError> ) -> Result<Vec<u8>, AflError>
where where
@ -37,7 +36,7 @@ where
SH: ShMem, SH: ShMem,
ST: Stats, ST: Stats,
{ {
let ret_slice = postcard::to_allocvec(&(&state, &corpus, &mgr.describe()?))?; let ret_slice = postcard::to_allocvec(&(&state, &mgr.describe()?))?;
//let corpus_bytes = serde_json::to_string(&corpus).unwrap(); //let corpus_bytes = serde_json::to_string(&corpus).unwrap();
//println!("fun"); //println!("fun");
@ -58,7 +57,7 @@ where
pub fn deserialize_state_corpus_mgr<C, FT, I, R, SH, ST>( pub fn deserialize_state_corpus_mgr<C, FT, I, R, SH, ST>(
state_corpus_serialized: &[u8], state_corpus_serialized: &[u8],
stats: ST, stats: ST,
) -> Result<(State<I, R, FT>, C, LlmpEventManager<I, SH, ST>), AflError> ) -> Result<(State<C, I, R, FT>, LlmpEventManager<I, SH, ST>), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -67,11 +66,10 @@ where
SH: ShMem, SH: ShMem,
ST: Stats, ST: Stats,
{ {
let tuple: (Vec<u8>, Vec<u8>, Vec<u8>) = postcard::from_bytes(&state_corpus_serialized)?; let tuple: (Vec<u8>, Vec<u8>) = postcard::from_bytes(&state_corpus_serialized)?;
let client_description = postcard::from_bytes(&tuple.2)?; let client_description = postcard::from_bytes(&tuple.1)?;
Ok(( Ok((
postcard::from_bytes(&tuple.0)?, postcard::from_bytes(&tuple.0)?,
postcard::from_bytes(&tuple.1)?,
LlmpEventManager::existing_client_from_description(&client_description, stats)?, LlmpEventManager::existing_client_from_description(&client_description, stats)?,
)) ))
} }
@ -79,7 +77,7 @@ where
/// Serialize the current state and corpus during an executiont to bytes. /// Serialize the current state and corpus during an executiont to bytes.
/// This method is needed when the fuzzer run crashes and has to restart. /// This method is needed when the fuzzer run crashes and has to restart.
pub fn serialize_state_corpus<C, FT, I, R>( pub fn serialize_state_corpus<C, FT, I, R>(
state: &State<I, R, FT>, state: &State<C, I, R, FT>,
corpus: &C, corpus: &C,
) -> Result<Vec<u8>, AflError> ) -> Result<Vec<u8>, AflError>
where where
@ -96,7 +94,7 @@ where
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` /// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
pub fn deserialize_state_corpus<C, FT, I, R>( pub fn deserialize_state_corpus<C, FT, I, R>(
state_corpus_serialized: &[u8], state_corpus_serialized: &[u8],
) -> Result<(State<I, R, FT>, C), AflError> ) -> Result<(State<C, I, R, FT>, C), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,

View File

@ -16,7 +16,7 @@ use afl::{
observers::StdMapObserver, observers::StdMapObserver,
shmem::{AflShmem, ShMem}, shmem::{AflShmem, ShMem},
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::{Fuzzer, State, StdFuzzer}, state::{Fuzzer, HasCorpus, State, StdFuzzer},
tuples::tuple_list, tuples::tuple_list,
utils::{deserialize_state_corpus_mgr, StdRand}, utils::{deserialize_state_corpus_mgr, StdRand},
AflError, AflError,
@ -185,7 +185,7 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
} }
// If we're restarting, deserialize the old state. // If we're restarting, deserialize the old state.
let (mut state, mut corpus, mut mgr) = match receiver.recv_buf()? { let (mut state, mut mgr) = match receiver.recv_buf()? {
None => { None => {
println!("First run. Let's set it all up"); println!("First run. Let's set it all up");
// Mgr to send and receive msgs from/to all other fuzzer instances // Mgr to send and receive msgs from/to all other fuzzer instances
@ -196,9 +196,9 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
// Initial execution, read or generate initial state, corpus, and feedbacks // Initial execution, read or generate initial state, corpus, and feedbacks
let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer); let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer);
let state = State::new(tuple_list!(edges_feedback));
let corpus = InMemoryCorpus::new(); let corpus = InMemoryCorpus::new();
(state, corpus, mgr) let state = State::new(corpus, tuple_list!(edges_feedback));
(state, mgr)
} }
// Restoring from a previous run, deserialize state and corpus. // Restoring from a previous run, deserialize state and corpus.
Some((_sender, _tag, msg)) => { Some((_sender, _tag, msg)) => {
@ -233,34 +233,26 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
"Libfuzzer", "Libfuzzer",
harness, harness,
tuple_list!(edges_observer), tuple_list!(edges_observer),
&state, &mut state,
&corpus,
&mut mgr, &mut mgr,
); );
// in case the corpus is empty (on first run), reset // in case the corpus is empty (on first run), reset
if corpus.count() < 1 { if state.corpus().count() < 1 {
match input { match input {
Some(x) => state Some(x) => state
.load_initial_inputs(&mut executor, &mut corpus, &mut generator, &mut mgr, &x) .load_initial_inputs(&mut executor, &mut generator, &mut mgr, &x)
.expect(&format!("Failed to load initial corpus at {:?}", &x)), .expect(&format!("Failed to load initial corpus at {:?}", &x)),
None => (), None => (),
} }
println!("We imported {} inputs from disk.", corpus.count()); println!("We imported {} inputs from disk.", state.corpus().count());
} }
if corpus.count() < 1 { if state.corpus().count() < 1 {
println!("Generating random inputs"); println!("Generating random inputs");
state state
.generate_initial_inputs( .generate_initial_inputs(&mut rand, &mut executor, &mut generator, &mut mgr, 4)
&mut rand,
&mut executor,
&mut corpus,
&mut generator,
&mut mgr,
4,
)
.expect("Failed to generate initial inputs"); .expect("Failed to generate initial inputs");
println!("We generated {} inputs.", corpus.count()); println!("We generated {} inputs.", state.corpus().count());
} }
let mut mutator = HavocBytesMutator::new_default(); let mut mutator = HavocBytesMutator::new_default();
@ -269,5 +261,5 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
let stage = StdMutationalStage::new(mutator); let stage = StdMutationalStage::new(mutator);
let mut fuzzer = StdFuzzer::new(tuple_list!(stage)); let mut fuzzer = StdFuzzer::new(tuple_list!(stage));
fuzzer.fuzz_loop(&mut rand, &mut executor, &mut state, &mut corpus, &mut mgr) fuzzer.fuzz_loop(&mut rand, &mut executor, &mut state, &mut mgr)
} }