merged state and corpus
This commit is contained in:
parent
2440aaedfc
commit
e2c4ed95e6
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@ perf.data
|
||||
perf.data.old
|
||||
|
||||
.vscode
|
||||
test.dict
|
@ -213,11 +213,7 @@ where
|
||||
where
|
||||
ST: Stats;
|
||||
/// 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>(
|
||||
self,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
) -> Result<(), AflError>
|
||||
fn handle_in_client<C, FT, R>(self, state: &mut State<C, I, R, FT>) -> Result<(), AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -233,11 +229,7 @@ where
|
||||
|
||||
/// Lookup for incoming events and process them.
|
||||
/// Return the number of processes events or an error
|
||||
fn process<C, FT, R>(
|
||||
&mut self,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
) -> Result<usize, AflError>
|
||||
fn process<C, FT, R>(&mut self, state: &mut State<C, I, R, FT>) -> Result<usize, AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -298,11 +290,7 @@ impl<I> EventManager<I> for NopEventManager<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
fn process<C, FT, R>(
|
||||
&mut self,
|
||||
_state: &mut State<I, R, FT>,
|
||||
_corpus: &mut C,
|
||||
) -> Result<usize, AflError>
|
||||
fn process<C, FT, R>(&mut self, _state: &mut State<C, I, R, FT>) -> Result<usize, AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -417,11 +405,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn handle_in_client<C, FT, R>(
|
||||
self,
|
||||
_state: &mut State<I, R, FT>,
|
||||
_corpus: &mut C,
|
||||
) -> Result<(), AflError>
|
||||
fn handle_in_client<C, FT, R>(self, _state: &mut State<C, I, R, FT>) -> Result<(), AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -452,11 +436,7 @@ where
|
||||
ST: Stats,
|
||||
//CE: CustomEvent<I, OT>,
|
||||
{
|
||||
fn process<C, FT, R>(
|
||||
&mut self,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
) -> Result<usize, AflError>
|
||||
fn process<C, FT, R>(&mut self, state: &mut State<C, I, R, FT>) -> Result<usize, AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -465,7 +445,7 @@ where
|
||||
let count = self.events.len();
|
||||
self.events
|
||||
.drain(..)
|
||||
.try_for_each(|event| event.handle_in_client(state, corpus))?;
|
||||
.try_for_each(|event| event.handle_in_client(state))?;
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
@ -682,11 +662,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn handle_in_client<C, FT, R>(
|
||||
self,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
) -> Result<(), AflError>
|
||||
fn handle_in_client<C, FT, R>(self, state: &mut State<C, I, R, FT>) -> Result<(), AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -707,7 +683,7 @@ where
|
||||
let interestingness = state.is_interesting(input.as_ref(), &observers)?;
|
||||
match input {
|
||||
Ptr::Owned(b) => {
|
||||
state.add_if_interesting(corpus, *b, interestingness)?;
|
||||
state.add_if_interesting(*b, interestingness)?;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
@ -894,11 +870,7 @@ where
|
||||
ST: Stats,
|
||||
//CE: CustomEvent<I>,
|
||||
{
|
||||
fn process<C, FT, R>(
|
||||
&mut self,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
) -> Result<usize, AflError>
|
||||
fn process<C, FT, R>(&mut self, state: &mut State<C, I, R, FT>) -> Result<usize, AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -919,7 +891,7 @@ where
|
||||
sender_id: sender_id,
|
||||
kind: kind,
|
||||
};
|
||||
event.handle_in_client(state, corpus)?;
|
||||
event.handle_in_client(state)?;
|
||||
count += 1;
|
||||
}
|
||||
None => break count,
|
||||
|
@ -50,8 +50,7 @@ where
|
||||
#[inline]
|
||||
fn pre_exec<R, FT, C, EM>(
|
||||
&mut self,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_state: &State<C, I, R, FT>,
|
||||
_event_mgr: &mut EM,
|
||||
_input: &I,
|
||||
) -> Result<(), AflError>
|
||||
@ -64,7 +63,7 @@ where
|
||||
#[cfg(unix)]
|
||||
#[cfg(feature = "std")]
|
||||
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(())
|
||||
}
|
||||
@ -72,8 +71,7 @@ where
|
||||
#[inline]
|
||||
fn post_exec<R, FT, C, EM>(
|
||||
&mut self,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_state: &State<C, I, R, FT>,
|
||||
_event_mgr: &mut EM,
|
||||
_input: &I,
|
||||
) -> Result<(), AflError>
|
||||
@ -142,8 +140,7 @@ where
|
||||
name: &'static str,
|
||||
harness_fn: HarnessFunction<Self>,
|
||||
observers: OT,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_state: &mut State<C, I, R, FT>,
|
||||
_event_mgr: &mut EM,
|
||||
) -> Self
|
||||
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,
|
||||
/// 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 EVENT_MGR_PTR: *mut c_void = ptr::null_mut();
|
||||
/// The (unsafe) pointer to the current inmem input, for the current run.
|
||||
@ -245,7 +241,6 @@ pub mod unix_signals {
|
||||
let _ = stdout().flush();
|
||||
|
||||
/*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 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 corpus = (CORPUS_PTR as *const C).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();
|
||||
|
||||
@ -315,8 +309,7 @@ pub mod unix_signals {
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_oncrash_ptrs<EM, C, OT, FT, I, R>(
|
||||
state: &State<I, R, FT>,
|
||||
corpus: &C,
|
||||
state: &State<C, I, R, FT>,
|
||||
event_mgr: &mut EM,
|
||||
input: &I,
|
||||
) where
|
||||
@ -328,7 +321,6 @@ pub mod unix_signals {
|
||||
R: Rand,
|
||||
{
|
||||
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;
|
||||
EVENT_MGR_PTR = event_mgr as *mut _ as *mut c_void;
|
||||
}
|
||||
@ -336,7 +328,6 @@ pub mod unix_signals {
|
||||
#[inline]
|
||||
pub unsafe fn reset_oncrash_ptrs<EM, C, OT, FT, I, R>() {
|
||||
CURRENT_INPUT_PTR = ptr::null();
|
||||
CORPUS_PTR = ptr::null();
|
||||
STATE_PTR = ptr::null();
|
||||
EVENT_MGR_PTR = ptr::null_mut();
|
||||
}
|
||||
|
@ -84,8 +84,7 @@ where
|
||||
/// Called right before exexution starts
|
||||
fn pre_exec<R, FT, C, EM>(
|
||||
&mut self,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_state: &State<C, I, R, FT>,
|
||||
_event_mgr: &mut EM,
|
||||
_input: &I,
|
||||
) -> Result<(), AflError>
|
||||
@ -102,8 +101,7 @@ where
|
||||
/// Called right after execution finished.
|
||||
fn post_exec<R, FT, C, EM>(
|
||||
&mut self,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_state: &State<C, I, R, FT>,
|
||||
_event_mgr: &mut EM,
|
||||
_input: &I,
|
||||
) -> Result<(), AflError>
|
||||
|
@ -3,24 +3,31 @@ pub use scheduled::*;
|
||||
pub mod 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
|
||||
// We can use it to report which mutations generated the testcase in the broker logs
|
||||
|
||||
/// A mutator takes input, and mutates it.
|
||||
/// Simple as that.
|
||||
pub trait Mutator<C, I, R>
|
||||
pub trait Mutator<C, I, R, S>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
/// Mutate a given input
|
||||
fn mutate(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
corpus: &C,
|
||||
state: &mut S,
|
||||
input: &mut I,
|
||||
stage_idx: i32,
|
||||
) -> Result<(), AflError>;
|
||||
@ -28,6 +35,7 @@ where
|
||||
/// Post-process given the outcome of the execution
|
||||
fn post_exec(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_is_interesting: u32,
|
||||
_input: &I,
|
||||
_stage_idx: i32,
|
||||
|
@ -6,11 +6,9 @@ use crate::{
|
||||
AflError,
|
||||
};
|
||||
|
||||
use std::fs::File;
|
||||
#[cfg(feature = "std")]
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader},
|
||||
};
|
||||
use std::io::{BufRead, BufReader};
|
||||
|
||||
const ARITH_MAX: u64 = 35;
|
||||
|
||||
@ -59,23 +57,24 @@ pub enum MutationResult {
|
||||
|
||||
// TODO maybe the mutator arg is not needed
|
||||
/// The generic function type that identifies mutations
|
||||
pub type MutationFunction<M, C, I, R> =
|
||||
fn(&mut M, &mut R, &C, &mut I) -> Result<MutationResult, AflError>;
|
||||
pub type MutationFunction<I, M, R, S> =
|
||||
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
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
/// 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
|
||||
fn mutations_count(&self) -> usize;
|
||||
|
||||
/// 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]
|
||||
@ -109,10 +108,10 @@ fn mem_set(data: &mut [u8], from: usize, len: usize, val: u8) {
|
||||
}
|
||||
|
||||
/// 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,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -131,10 +130,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_byteflip<M, C, I, R>(
|
||||
pub fn mutation_byteflip<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -153,10 +152,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_byteinc<M, C, I, R>(
|
||||
pub fn mutation_byteinc<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -176,10 +175,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_bytedec<M, C, I, R>(
|
||||
pub fn mutation_bytedec<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -199,10 +198,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_byteneg<M, C, I, R>(
|
||||
pub fn mutation_byteneg<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -221,10 +220,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_byterand<M, C, I, R>(
|
||||
pub fn mutation_byterand<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -243,10 +242,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_byteadd<M, C, I, R>(
|
||||
pub fn mutation_byteadd<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -270,10 +269,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_wordadd<M, C, I, R>(
|
||||
pub fn mutation_wordadd<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -299,10 +298,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_dwordadd<M, C, I, R>(
|
||||
pub fn mutation_dwordadd<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -328,10 +327,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_qwordadd<M, C, I, R>(
|
||||
pub fn mutation_qwordadd<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -357,10 +356,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_byteinteresting<M, C, I, R>(
|
||||
pub fn mutation_byteinteresting<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -380,10 +379,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_wordinteresting<M, C, I, R>(
|
||||
pub fn mutation_wordinteresting<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -408,10 +407,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_dwordinteresting<M, C, I, R>(
|
||||
pub fn mutation_dwordinteresting<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -436,10 +435,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutation_bytesdelete<M, C, I, R>(
|
||||
pub fn mutation_bytesdelete<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -458,11 +457,11 @@ where
|
||||
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?
|
||||
mutator: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -485,10 +484,10 @@ where
|
||||
|
||||
/*
|
||||
// Insert a dictionary token
|
||||
pub fn mutation_tokeninsert<M, C, I, R>(
|
||||
pub fn mutation_tokeninsert<I, M, R, S>(
|
||||
mutator: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
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,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -538,10 +537,10 @@ where
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
||||
pub fn mutation_bytesrandinsert<M, C, I, R>(
|
||||
pub fn mutation_bytesrandinsert<I, M, R, S>(
|
||||
mutator: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -564,10 +563,10 @@ where
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
||||
pub fn mutation_bytesset<M, C, I, R>(
|
||||
pub fn mutation_bytesset<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -590,10 +589,10 @@ where
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
||||
pub fn mutation_bytesrandset<M, C, I, R>(
|
||||
pub fn mutation_bytesrandset<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -616,10 +615,10 @@ where
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
||||
pub fn mutation_bytescopy<M, C, I, R>(
|
||||
pub fn mutation_bytescopy<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -639,10 +638,10 @@ where
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
||||
pub fn mutation_bytesswap<M, C, I, R>(
|
||||
pub fn mutation_bytesswap<I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
_: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
@ -681,20 +680,21 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
|
||||
}
|
||||
|
||||
/// Splicing mutator
|
||||
pub fn mutation_splice<M, C, I, R>(
|
||||
pub fn mutation_splice<C, I, M, R, S>(
|
||||
_: &mut M,
|
||||
rand: &mut R,
|
||||
corpus: &C,
|
||||
state: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
S: HasCorpus<C>,
|
||||
{
|
||||
// We don't want to use the testcase we're already using for splicing
|
||||
let (other_testcase, idx) = corpus.random_entry(rand)?;
|
||||
if idx == corpus.current_testcase().1 {
|
||||
let (other_testcase, idx) = state.corpus().random_entry(rand)?;
|
||||
if idx == state.corpus().current_testcase().1 {
|
||||
return Ok(MutationResult::Skipped);
|
||||
}
|
||||
// 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)]
|
||||
mod tests {
|
||||
use std::fs;
|
||||
|
||||
use crate::mutators::read_dict_file;
|
||||
|
||||
#[test]
|
||||
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 res = read_dict_file(&"test.dic".to_string(), &mut v).unwrap();
|
||||
#[cfg(feature = "std")]
|
||||
println!("Dictionary entries: {:?}", res);
|
||||
assert_eq!(res, 2);
|
||||
let _ = fs::remove_file("test.dict");
|
||||
}
|
||||
}
|
||||
|
@ -5,15 +5,18 @@ use fmt::Debug;
|
||||
use crate::{
|
||||
inputs::{HasBytesVec, Input},
|
||||
mutators::{Corpus, *},
|
||||
state::{HasCorpus, HasMetadata},
|
||||
utils::Rand,
|
||||
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
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
/// Compute the number of iterations used to apply stacked mutations
|
||||
#[inline]
|
||||
@ -33,35 +36,37 @@ where
|
||||
fn scheduled_mutate(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
corpus: &C,
|
||||
state: &mut S,
|
||||
input: &mut I,
|
||||
_stage_idx: i32,
|
||||
) -> Result<(), AflError> {
|
||||
let num = self.iterations(rand, input);
|
||||
for _ in 0..num {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct StdScheduledMutator<C, I, R>
|
||||
pub struct StdScheduledMutator<C, I, R, S>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
mutations: Vec<MutationFunction<Self, C, I, R>>,
|
||||
mutations: Vec<MutationFunction<I, Self, R, S>>,
|
||||
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
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
fn mutate(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
corpus: &C,
|
||||
state: &mut S,
|
||||
input: &mut I,
|
||||
_stage_idx: i32,
|
||||
) -> 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
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
#[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]
|
||||
}
|
||||
|
||||
@ -108,25 +115,27 @@ where
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
// 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
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
#[inline]
|
||||
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
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
/// Create a new StdScheduledMutator instance without mutations and corpus
|
||||
pub fn new() -> Self {
|
||||
@ -154,7 +164,7 @@ where
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
mutations: mutations,
|
||||
max_size: DEFAULT_MAX_SIZE,
|
||||
@ -164,29 +174,31 @@ where
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// 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
|
||||
SM: ScheduledMutator<C, I, R> + HasMaxSize,
|
||||
SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
|
||||
C: Corpus<I, R>,
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
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
|
||||
SM: ScheduledMutator<C, I, R> + HasMaxSize,
|
||||
SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
|
||||
C: Corpus<I, R>,
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
/// Mutate bytes
|
||||
fn mutate(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
corpus: &C,
|
||||
state: &mut S,
|
||||
input: &mut I,
|
||||
_stage_idx: i32,
|
||||
) -> Result<(), AflError> {
|
||||
@ -210,18 +222,19 @@ where
|
||||
11 => mutation_dwordinteresting,
|
||||
_ => mutation_splice,
|
||||
};
|
||||
mutation(self, rand, corpus, input)?;
|
||||
mutation(self, rand, state, input)?;
|
||||
}
|
||||
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
|
||||
SM: ScheduledMutator<C, I, R> + HasMaxSize,
|
||||
SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
|
||||
C: Corpus<I, R>,
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
#[inline]
|
||||
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
|
||||
SM: ScheduledMutator<C, I, R> + HasMaxSize,
|
||||
SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
|
||||
C: Corpus<I, R>,
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
/// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap
|
||||
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
|
||||
C: Corpus<I, R>,
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
S: HasCorpus<C> + HasMetadata,
|
||||
{
|
||||
/// Create a new HavocBytesMutator instance wrapping StdScheduledMutator
|
||||
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_byteflip);
|
||||
scheduled.add_mutation(mutation_byteinc);
|
||||
@ -309,6 +324,7 @@ mod tests {
|
||||
inputs::BytesInput,
|
||||
inputs::HasBytesVec,
|
||||
mutators::scheduled::{mutation_splice, StdScheduledMutator},
|
||||
state::State,
|
||||
utils::{Rand, XKCDRand},
|
||||
};
|
||||
|
||||
@ -325,10 +341,17 @@ mod tests {
|
||||
.expect("Corpus did not contain entries");
|
||||
let mut input = testcase.borrow_mut().load_input().unwrap().clone();
|
||||
|
||||
rand.set_seed(5);
|
||||
let mut mutator = StdScheduledMutator::<InMemoryCorpus<BytesInput, XKCDRand>, _, _>::new();
|
||||
let mut state = State::new(corpus, ());
|
||||
|
||||
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")]
|
||||
println!("{:?}", input.bytes());
|
||||
|
@ -16,7 +16,7 @@ use crate::{
|
||||
|
||||
/// A stage is one step in the fuzzing process.
|
||||
/// 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
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
@ -31,8 +31,7 @@ where
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
corpus_idx: usize,
|
||||
) -> Result<(), AflError>;
|
||||
@ -52,13 +51,12 @@ where
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
corpus_idx: usize,
|
||||
) -> Result<(), AflError>;
|
||||
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>));
|
||||
fn for_each_mut(&mut self, f: fn(&mut 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<C, E, EM, FT, I, OT, R>));
|
||||
}
|
||||
|
||||
impl<EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for ()
|
||||
@ -75,20 +73,19 @@ where
|
||||
&mut self,
|
||||
_rand: &mut R,
|
||||
_executor: &mut E,
|
||||
_state: &mut State<I, R, FT>,
|
||||
_corpus: &mut C,
|
||||
_state: &mut State<C, I, R, FT>,
|
||||
_manager: &mut EM,
|
||||
_corpus_idx: usize,
|
||||
) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
fn for_each(&self, _f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>)) {}
|
||||
fn for_each_mut(&mut self, _f: fn(&mut 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<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)
|
||||
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,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
@ -102,23 +99,21 @@ where
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
corpus_idx: usize,
|
||||
) -> Result<(), AflError> {
|
||||
self.0
|
||||
.perform(rand, executor, state, corpus, manager, corpus_idx)?;
|
||||
self.0.perform(rand, executor, state, manager, corpus_idx)?;
|
||||
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);
|
||||
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);
|
||||
self.1.for_each_mut(f)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
observers::ObserversTuple,
|
||||
stages::Corpus,
|
||||
stages::Stage,
|
||||
state::State,
|
||||
state::{HasCorpus, State},
|
||||
utils::Rand,
|
||||
AflError,
|
||||
};
|
||||
@ -19,9 +19,9 @@ use crate::{
|
||||
/// A Mutational stage is the stage in a fuzzing run that mutates inputs.
|
||||
/// Mutational stages will usually have a range of mutations that are
|
||||
/// 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
|
||||
M: Mutator<C, I, R>,
|
||||
M: Mutator<C, I, R, State<C, I, R, FT>>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
@ -48,21 +48,25 @@ where
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
corpus_idx: usize,
|
||||
) -> Result<(), AflError> {
|
||||
let num = self.iterations(rand);
|
||||
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()
|
||||
.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()
|
||||
.post_exec(fitness, &input_mut, i as i32)?;
|
||||
.post_exec(state, fitness, &input_mut, i as i32)?;
|
||||
|
||||
let observers = executor.observers();
|
||||
|
||||
@ -73,8 +77,13 @@ where
|
||||
// if needed by particular cases
|
||||
if fitness > 0 {
|
||||
// TODO decouple events manager and engine
|
||||
manager.new_testcase(&input_mut, observers, corpus.count() + 1, "test".into())?;
|
||||
state.add_if_interesting(corpus, input_mut, fitness)?;
|
||||
manager.new_testcase(
|
||||
&input_mut,
|
||||
observers,
|
||||
state.corpus().count() + 1,
|
||||
"test".into(),
|
||||
)?;
|
||||
state.add_if_interesting(input_mut, fitness)?;
|
||||
// let _ = corpus.add(testcase);
|
||||
} else {
|
||||
state.discard_input(&input_mut)?;
|
||||
@ -86,31 +95,31 @@ where
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// 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
|
||||
M: Mutator<C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
EM: EventManager<I>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
I: Input,
|
||||
M: Mutator<C, I, R, State<C, I, R, FT>>,
|
||||
OT: ObserversTuple,
|
||||
R: Rand,
|
||||
{
|
||||
mutator: M,
|
||||
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>
|
||||
for StdMutationalStage<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<C, E, EM, FT, I, M, OT, R>
|
||||
where
|
||||
M: Mutator<C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
EM: EventManager<I>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
I: Input,
|
||||
M: Mutator<C, I, R, State<C, I, R, FT>>,
|
||||
OT: ObserversTuple,
|
||||
R: Rand,
|
||||
{
|
||||
/// 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>
|
||||
for StdMutationalStage<M, 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<C, E, EM, FT, I, M, OT, R>
|
||||
where
|
||||
M: Mutator<C, I, R>,
|
||||
M: Mutator<C, I, R, State<C, I, R, FT>>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
@ -143,18 +152,17 @@ where
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
corpus_idx: usize,
|
||||
) -> 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
|
||||
M: Mutator<C, I, R>,
|
||||
M: Mutator<C, I, R, State<C, I, R, FT>>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
|
@ -26,24 +26,53 @@ use crate::{
|
||||
use crate::inputs::bytes::BytesInput;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "FT: serde::de::DeserializeOwned")]
|
||||
pub struct State<I, R, FT>
|
||||
pub struct State<C, I, R, FT>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbacksTuple<I>,
|
||||
{
|
||||
/// How many times the executor ran the harness/target
|
||||
executions: usize,
|
||||
/// The corpus
|
||||
corpus: C,
|
||||
/// At what time the fuzzing started
|
||||
start_time: u64,
|
||||
/// Metadata stored for this state by one of the components
|
||||
metadatas: SerdeAnyMap,
|
||||
metadata: SerdeAnyMap,
|
||||
// additional_corpuses, maybe another TupleList?
|
||||
// Feedbacks used to evaluate an input
|
||||
feedbacks: FT,
|
||||
@ -51,15 +80,15 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<R, FT> State<BytesInput, R, FT>
|
||||
impl<C, R, FT> State<C, BytesInput, R, FT>
|
||||
where
|
||||
C: Corpus<BytesInput, R>,
|
||||
R: Rand,
|
||||
FT: FeedbacksTuple<BytesInput>,
|
||||
{
|
||||
pub fn load_from_directory<G, C, E, OT, EM>(
|
||||
pub fn load_from_directory<G, E, OT, EM>(
|
||||
&mut self,
|
||||
executor: &mut E,
|
||||
corpus: &mut C,
|
||||
generator: &mut G,
|
||||
manager: &mut EM,
|
||||
in_dir: &Path,
|
||||
@ -86,22 +115,21 @@ where
|
||||
println!("Loading file {:?} ...", &path);
|
||||
let bytes = fs::read(&path)?;
|
||||
let input = BytesInput::new(bytes);
|
||||
let fitness = self.evaluate_input(&input, executor, corpus, manager)?;
|
||||
if self.add_if_interesting(corpus, input, fitness)?.is_none() {
|
||||
let fitness = self.evaluate_input(&input, executor, manager)?;
|
||||
if self.add_if_interesting(input, fitness)?.is_none() {
|
||||
println!("File {:?} was not interesting, skipped.", &path);
|
||||
}
|
||||
} else if attr.is_dir() {
|
||||
self.load_from_directory(executor, corpus, generator, manager, &path)?;
|
||||
self.load_from_directory(executor, generator, manager, &path)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_initial_inputs<G, C, E, OT, EM>(
|
||||
pub fn load_initial_inputs<G, E, OT, EM>(
|
||||
&mut self,
|
||||
executor: &mut E,
|
||||
corpus: &mut C,
|
||||
generator: &mut G,
|
||||
manager: &mut EM,
|
||||
in_dirs: &[PathBuf],
|
||||
@ -114,19 +142,59 @@ where
|
||||
EM: EventManager<BytesInput>,
|
||||
{
|
||||
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(
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, R, FT> State<I, R, FT>
|
||||
impl<C, I, R, FT> HasCorpus<C> for State<C, I, R, FT>
|
||||
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,
|
||||
R: Rand,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -151,7 +219,6 @@ where
|
||||
pub fn set_start_time(&mut self, ms: u64) {
|
||||
self.start_time = ms
|
||||
}
|
||||
|
||||
// TODO as this is done in the event manager, we can remove it
|
||||
#[inline]
|
||||
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
|
||||
#[inline]
|
||||
pub fn feedbacks(&self) -> &FT {
|
||||
@ -210,11 +256,10 @@ where
|
||||
}
|
||||
|
||||
/// 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,
|
||||
input: &I,
|
||||
executor: &mut E,
|
||||
corpus: &C,
|
||||
event_mgr: &mut EM,
|
||||
) -> Result<u32, AflError>
|
||||
where
|
||||
@ -225,9 +270,9 @@ where
|
||||
{
|
||||
executor.pre_exec_observers()?;
|
||||
|
||||
executor.pre_exec(&self, corpus, event_mgr, input)?;
|
||||
executor.pre_exec(&self, event_mgr, 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);
|
||||
executor.post_exec_observers()?;
|
||||
@ -270,29 +315,23 @@ where
|
||||
|
||||
/// Adds this input to the corpus, if it's intersting
|
||||
#[inline]
|
||||
pub fn add_if_interesting<C>(
|
||||
&mut self,
|
||||
corpus: &mut C,
|
||||
input: I,
|
||||
fitness: u32,
|
||||
) -> Result<Option<usize>, AflError>
|
||||
pub fn add_if_interesting(&mut self, input: I, fitness: u32) -> Result<Option<usize>, AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
{
|
||||
if fitness > 0 {
|
||||
let testcase = self.input_to_testcase(input, fitness)?;
|
||||
Ok(Some(corpus.add(testcase)))
|
||||
Ok(Some(self.corpus_mut().add(testcase)))
|
||||
} else {
|
||||
self.discard_input(&input)?;
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_initial_inputs<G, C, E, OT, EM>(
|
||||
pub fn generate_initial_inputs<G, E, OT, EM>(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
corpus: &mut C,
|
||||
generator: &mut G,
|
||||
manager: &mut EM,
|
||||
num: usize,
|
||||
@ -307,8 +346,8 @@ where
|
||||
let mut added = 0;
|
||||
for _ in 0..num {
|
||||
let input = generator.generate(rand)?;
|
||||
let fitness = self.evaluate_input(&input, executor, corpus, manager)?;
|
||||
if !self.add_if_interesting(corpus, input, fitness)?.is_none() {
|
||||
let fitness = self.evaluate_input(&input, executor, manager)?;
|
||||
if !self.add_if_interesting(input, fitness)?.is_none() {
|
||||
added += 1;
|
||||
}
|
||||
}
|
||||
@ -316,15 +355,16 @@ where
|
||||
0,
|
||||
format!("Loaded {} over {} initial testcases", added, num),
|
||||
)?;
|
||||
manager.process(self, corpus)?;
|
||||
manager.process(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn new(feedbacks: FT) -> Self {
|
||||
pub fn new(corpus: C, feedbacks: FT) -> Self {
|
||||
Self {
|
||||
corpus,
|
||||
executions: 0,
|
||||
start_time: current_milliseconds(),
|
||||
metadatas: SerdeAnyMap::default(),
|
||||
metadata: SerdeAnyMap::default(),
|
||||
feedbacks: feedbacks,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
@ -350,16 +390,15 @@ where
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
) -> Result<usize, AflError> {
|
||||
let (_, idx) = corpus.next(rand)?;
|
||||
let (_, idx) = state.corpus_mut().next(rand)?;
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@ -367,13 +406,12 @@ where
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<I, R, FT>,
|
||||
corpus: &mut C,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
) -> Result<(), AflError> {
|
||||
let mut last = current_milliseconds();
|
||||
loop {
|
||||
self.fuzz_one(rand, executor, state, corpus, manager)?;
|
||||
self.fuzz_one(rand, executor, state, manager)?;
|
||||
let cur = current_milliseconds();
|
||||
if cur - last > 60 * 100 {
|
||||
last = cur;
|
||||
@ -458,6 +496,8 @@ mod tests {
|
||||
#[cfg(feature = "std")]
|
||||
use crate::events::{LoggerEventManager, SimpleStats};
|
||||
|
||||
use super::HasCorpus;
|
||||
|
||||
fn harness<E: Executor<I>, I: Input>(_executor: &E, _buf: &[u8]) -> ExitKind {
|
||||
ExitKind::Ok
|
||||
}
|
||||
@ -470,7 +510,7 @@ mod tests {
|
||||
let testcase = Testcase::new(vec![0; 4]).into();
|
||||
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| {
|
||||
println!("{}", s);
|
||||
@ -481,8 +521,7 @@ mod tests {
|
||||
harness,
|
||||
tuple_list!(),
|
||||
//Box::new(|_, _, _, _, _| ()),
|
||||
&state,
|
||||
&corpus,
|
||||
&mut state,
|
||||
&mut event_manager,
|
||||
);
|
||||
|
||||
@ -493,24 +532,18 @@ mod tests {
|
||||
|
||||
for i in 0..1000 {
|
||||
fuzzer
|
||||
.fuzz_one(
|
||||
&mut rand,
|
||||
&mut executor,
|
||||
&mut state,
|
||||
&mut corpus,
|
||||
&mut event_manager,
|
||||
)
|
||||
.fuzz_one(&mut rand, &mut executor, &mut state, &mut event_manager)
|
||||
.expect(&format!("Error in iter {}", i));
|
||||
}
|
||||
|
||||
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();
|
||||
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> =
|
||||
postcard::from_bytes(corpus_serialized.as_slice()).unwrap();
|
||||
assert_eq!(corpus.count(), corpus_deserialized.count());
|
||||
assert_eq!(state.corpus().count(), corpus_deserialized.count());
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,7 @@ pub type StdRand = RomuTrioRand;
|
||||
/// 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.
|
||||
pub fn serialize_state_corpus_mgr<C, FT, I, R, SH, ST>(
|
||||
state: &State<I, R, FT>,
|
||||
corpus: &C,
|
||||
state: &State<C, I, R, FT>,
|
||||
mgr: &LlmpEventManager<I, SH, ST>,
|
||||
) -> Result<Vec<u8>, AflError>
|
||||
where
|
||||
@ -37,7 +36,7 @@ where
|
||||
SH: ShMem,
|
||||
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();
|
||||
|
||||
//println!("fun");
|
||||
@ -58,7 +57,7 @@ where
|
||||
pub fn deserialize_state_corpus_mgr<C, FT, I, R, SH, ST>(
|
||||
state_corpus_serialized: &[u8],
|
||||
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
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
@ -67,11 +66,10 @@ where
|
||||
SH: ShMem,
|
||||
ST: Stats,
|
||||
{
|
||||
let tuple: (Vec<u8>, Vec<u8>, Vec<u8>) = postcard::from_bytes(&state_corpus_serialized)?;
|
||||
let client_description = postcard::from_bytes(&tuple.2)?;
|
||||
let tuple: (Vec<u8>, Vec<u8>) = postcard::from_bytes(&state_corpus_serialized)?;
|
||||
let client_description = postcard::from_bytes(&tuple.1)?;
|
||||
Ok((
|
||||
postcard::from_bytes(&tuple.0)?,
|
||||
postcard::from_bytes(&tuple.1)?,
|
||||
LlmpEventManager::existing_client_from_description(&client_description, stats)?,
|
||||
))
|
||||
}
|
||||
@ -79,7 +77,7 @@ where
|
||||
/// Serialize the current state and corpus during an executiont to bytes.
|
||||
/// This method is needed when the fuzzer run crashes and has to restart.
|
||||
pub fn serialize_state_corpus<C, FT, I, R>(
|
||||
state: &State<I, R, FT>,
|
||||
state: &State<C, I, R, FT>,
|
||||
corpus: &C,
|
||||
) -> Result<Vec<u8>, AflError>
|
||||
where
|
||||
@ -96,7 +94,7 @@ where
|
||||
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
|
||||
pub fn deserialize_state_corpus<C, FT, I, R>(
|
||||
state_corpus_serialized: &[u8],
|
||||
) -> Result<(State<I, R, FT>, C), AflError>
|
||||
) -> Result<(State<C, I, R, FT>, C), AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
|
@ -16,7 +16,7 @@ use afl::{
|
||||
observers::StdMapObserver,
|
||||
shmem::{AflShmem, ShMem},
|
||||
stages::mutational::StdMutationalStage,
|
||||
state::{Fuzzer, State, StdFuzzer},
|
||||
state::{Fuzzer, HasCorpus, State, StdFuzzer},
|
||||
tuples::tuple_list,
|
||||
utils::{deserialize_state_corpus_mgr, StdRand},
|
||||
AflError,
|
||||
@ -185,7 +185,7 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
|
||||
}
|
||||
|
||||
// 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 => {
|
||||
println!("First run. Let's set it all up");
|
||||
// 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
|
||||
let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer);
|
||||
let state = State::new(tuple_list!(edges_feedback));
|
||||
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.
|
||||
Some((_sender, _tag, msg)) => {
|
||||
@ -233,34 +233,26 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
|
||||
"Libfuzzer",
|
||||
harness,
|
||||
tuple_list!(edges_observer),
|
||||
&state,
|
||||
&corpus,
|
||||
&mut state,
|
||||
&mut mgr,
|
||||
);
|
||||
|
||||
// in case the corpus is empty (on first run), reset
|
||||
if corpus.count() < 1 {
|
||||
if state.corpus().count() < 1 {
|
||||
match input {
|
||||
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)),
|
||||
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");
|
||||
state
|
||||
.generate_initial_inputs(
|
||||
&mut rand,
|
||||
&mut executor,
|
||||
&mut corpus,
|
||||
&mut generator,
|
||||
&mut mgr,
|
||||
4,
|
||||
)
|
||||
.generate_initial_inputs(&mut rand, &mut executor, &mut generator, &mut mgr, 4)
|
||||
.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();
|
||||
@ -269,5 +261,5 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
|
||||
let stage = StdMutationalStage::new(mutator);
|
||||
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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user