merged state and corpus

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

1
.gitignore vendored
View File

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

View File

@ -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,

View File

@ -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();
}

View File

@ -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>

View File

@ -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,

View File

@ -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");
}
}

View File

@ -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());

View File

@ -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)
}

View File

@ -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,

View File

@ -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());
}
}

View File

@ -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>,

View File

@ -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)
}