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
|
perf.data.old
|
||||||
|
|
||||||
.vscode
|
.vscode
|
||||||
|
test.dict
|
@ -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,
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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,
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>,
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user