splitted events rand and state, works again
This commit is contained in:
parent
1ec34dbaa8
commit
a3501cfb43
@ -200,9 +200,9 @@ where
|
|||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
corpus: C,
|
corpus: C,
|
||||||
phantom: PhantomData<(I, R)>,
|
|
||||||
pos: usize,
|
pos: usize,
|
||||||
cycles: u64,
|
cycles: u64,
|
||||||
|
phantom: PhantomData<(I, R)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R> HasTestcaseVec<I> for QueueCorpus<C, I, R>
|
impl<C, I, R> HasTestcaseVec<I> for QueueCorpus<C, I, R>
|
||||||
|
@ -5,6 +5,7 @@ use alloc::rc::Rc;
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ use crate::feedbacks::Feedback;
|
|||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::observers::Observer;
|
use crate::observers::Observer;
|
||||||
use crate::stages::Stage;
|
use crate::stages::Stage;
|
||||||
|
use crate::utils::Rand;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
// TODO FeedbackMetadata to store histroy_map
|
// TODO FeedbackMetadata to store histroy_map
|
||||||
@ -29,6 +31,7 @@ where
|
|||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
{
|
{
|
||||||
/// Get executions
|
/// Get executions
|
||||||
fn executions(&self) -> usize;
|
fn executions(&self) -> usize;
|
||||||
@ -120,9 +123,10 @@ where
|
|||||||
|
|
||||||
pub struct StdState<C, E, I, R>
|
pub struct StdState<C, E, I, R>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I, R>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
{
|
{
|
||||||
executions: usize,
|
executions: usize,
|
||||||
metadatas: HashMap<&'static str, Box<dyn StateMetadata>>,
|
metadatas: HashMap<&'static str, Box<dyn StateMetadata>>,
|
||||||
@ -131,9 +135,10 @@ where
|
|||||||
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
||||||
corpus: C,
|
corpus: C,
|
||||||
executor: E,
|
executor: E,
|
||||||
|
phantom: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, E, I, R> HasCorpus<C, I, R> for DefaultState<C, E, I, R>
|
impl<C, E, I, R> HasCorpus<C, I, R> for StdState<C, E, I, R>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
@ -152,9 +157,10 @@ where
|
|||||||
|
|
||||||
impl<C, E, I, R> State<C, E, I, R> for StdState<C, E, I, R>
|
impl<C, E, I, R> State<C, E, I, R> for StdState<C, E, I, R>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I, R>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn executions(&self) -> usize {
|
fn executions(&self) -> usize {
|
||||||
self.executions
|
self.executions
|
||||||
@ -199,9 +205,10 @@ where
|
|||||||
|
|
||||||
impl<C, E, I, R> StdState<C, E, I, R>
|
impl<C, E, I, R> StdState<C, E, I, R>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I, R>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
{
|
{
|
||||||
pub fn new(corpus: C, executor: E) -> Self {
|
pub fn new(corpus: C, executor: E) -> Self {
|
||||||
StdState {
|
StdState {
|
||||||
@ -211,22 +218,25 @@ where
|
|||||||
feedbacks: vec![],
|
feedbacks: vec![],
|
||||||
corpus: corpus,
|
corpus: corpus,
|
||||||
executor: executor,
|
executor: executor,
|
||||||
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Engine<S, C, E, I>
|
pub trait Engine<S, EM, E, C, I, R>
|
||||||
where
|
where
|
||||||
S: State<C, E, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
EM: EventManager,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn stages(&self) -> &[Box<dyn Stage<S, C, E, I, R>>];
|
fn stages(&self) -> &[Box<dyn Stage<S, EM, E, C, I, R>>];
|
||||||
|
|
||||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<S, C, E, I, R>>>;
|
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<S, EM, E, C, I, R>>>;
|
||||||
|
|
||||||
fn add_stage(&mut self, stage: Box<dyn Stage<S, C, E, I, R>>) {
|
fn add_stage(&mut self, stage: Box<dyn Stage<S, EM, E, C, I, R>>) {
|
||||||
self.stages_mut().push(stage);
|
self.stages_mut().push(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,52 +244,62 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
events_manager: &mut EM,
|
events: &mut EM,
|
||||||
) -> Result<usize, AflError> {
|
) -> Result<usize, AflError> {
|
||||||
let (testcase, idx) = state.corpus_mut().next(rand)?;
|
let (testcase, idx) = state.corpus_mut().next(rand)?;
|
||||||
println!("Cur entry: {}\tExecutions: {}", idx, state.executions());
|
println!("Cur entry: {}\tExecutions: {}", idx, state.executions());
|
||||||
for stage in self.stages_mut() {
|
for stage in self.stages_mut() {
|
||||||
stage.perform(testcase.clone(), state)?;
|
stage.perform(rand, state, events, testcase.clone())?;
|
||||||
}
|
}
|
||||||
Ok(idx)
|
Ok(idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StdEngine<S, C, E, I>
|
pub struct StdEngine<S, EM, E, C, I, R>
|
||||||
where
|
|
||||||
S: State<C, E, I>,
|
|
||||||
C: Corpus<I>,
|
|
||||||
E: Executor<I>,
|
|
||||||
I: Input,
|
|
||||||
{
|
|
||||||
stages: Vec<Box<dyn Stage<S, C, E, I, R>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, C, E, I> Engine<S, C, E, I> for StdEngine<S, C, E, I>
|
|
||||||
where
|
where
|
||||||
S: State<C, E, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
EM: EventManager,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn stages(&self) -> &[Box<dyn Stage<S, C, E, I, R>>] {
|
stages: Vec<Box<dyn Stage<S, EM, E, C, I, R>>>,
|
||||||
|
phantom: PhantomData<EM>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, EM, E, C, I, R> Engine<S, EM, E, C, I, R> for StdEngine<S, EM, E, C, I, R>
|
||||||
|
where
|
||||||
|
S: State<C, E, I, R>,
|
||||||
|
EM: EventManager,
|
||||||
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
{
|
||||||
|
fn stages(&self) -> &[Box<dyn Stage<S, EM, E, C, I, R>>] {
|
||||||
&self.stages
|
&self.stages
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<S, C, E, I, R>>> {
|
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<S, EM, E, C, I, R>>> {
|
||||||
&mut self.stages
|
&mut self.stages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, C, E, I> StdEngine<S, C, E, I>
|
impl<S, EM, E, C, I, R> StdEngine<S, EM, E, C, I, R>
|
||||||
where
|
where
|
||||||
S: State<C, E, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
EM: EventManager,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
{
|
{
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
StdEngine { stages: vec![] }
|
StdEngine {
|
||||||
|
stages: vec![],
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,6 +310,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
|
use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
|
||||||
use crate::engines::{Engine, StdEngine, StdState};
|
use crate::engines::{Engine, StdEngine, StdState};
|
||||||
|
use crate::events::LoggerEventManager;
|
||||||
use crate::executors::inmemory::InMemoryExecutor;
|
use crate::executors::inmemory::InMemoryExecutor;
|
||||||
use crate::executors::{Executor, ExitKind};
|
use crate::executors::{Executor, ExitKind};
|
||||||
use crate::inputs::bytes::BytesInput;
|
use crate::inputs::bytes::BytesInput;
|
||||||
@ -303,26 +324,28 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_engine() {
|
fn test_engine() {
|
||||||
let rand = StdRand::new(0).into();
|
let mut rand = StdRand::new(0);
|
||||||
|
|
||||||
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
|
let mut corpus = InMemoryCorpus::<BytesInput, StdRand>::new();
|
||||||
let testcase = Testcase::new(vec![0; 4]).into();
|
let testcase = Testcase::new(vec![0; 4]).into();
|
||||||
corpus.add(testcase);
|
corpus.add(testcase);
|
||||||
|
|
||||||
let executor = InMemoryExecutor::<BytesInput>::new(harness);
|
let executor = InMemoryExecutor::<BytesInput>::new(harness);
|
||||||
let mut state = StdState::new(corpus, executor);
|
let mut state = StdState::new(corpus, executor);
|
||||||
|
|
||||||
|
let mut events_manager = LoggerEventManager::new();
|
||||||
|
|
||||||
let mut engine = StdEngine::new();
|
let mut engine = StdEngine::new();
|
||||||
let mut mutator = StdScheduledMutator::new(&rand);
|
let mut mutator = StdScheduledMutator::new();
|
||||||
mutator.add_mutation(mutation_bitflip);
|
mutator.add_mutation(mutation_bitflip);
|
||||||
let stage = StdMutationalStage::new(&rand, mutator);
|
let stage = StdMutationalStage::new(mutator);
|
||||||
engine.add_stage(Box::new(stage));
|
engine.add_stage(Box::new(stage));
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
for i in 0..1000 {
|
for i in 0..1000 {
|
||||||
engine
|
engine
|
||||||
.fuzz_one(&mut state)
|
.fuzz_one(&mut rand, &mut state, &mut events_manager)
|
||||||
.expect(&format!("Error in iter {}", i));
|
.expect(&format!("Error in iter {}", i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,28 @@
|
|||||||
pub mod scheduled;
|
pub mod scheduled;
|
||||||
pub use scheduled::ComposedByMutations;
|
pub use scheduled::ComposedByMutations;
|
||||||
pub use scheduled::StdScheduledMutator;
|
|
||||||
pub use scheduled::HavocBytesMutator;
|
pub use scheduled::HavocBytesMutator;
|
||||||
pub use scheduled::ScheduledMutator;
|
pub use scheduled::ScheduledMutator;
|
||||||
|
pub use scheduled::StdScheduledMutator;
|
||||||
|
|
||||||
use crate::corpus::{Corpus, HasCorpus};
|
use crate::corpus::Corpus;
|
||||||
//use crate::engines::State;
|
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::utils::{HasRand, Rand};
|
use crate::utils::Rand;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
pub trait Mutator<S, C, I, R>
|
pub trait Mutator<C, I, R>
|
||||||
where
|
where
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
/// Mutate a given input
|
/// Mutate a given input
|
||||||
fn mutate(&mut self, state: &mut S, input: &mut I, stage_idx: i32) -> Result<(), AflError>;
|
fn mutate(
|
||||||
|
&mut self,
|
||||||
|
rand: &mut R,
|
||||||
|
corpus: &mut C,
|
||||||
|
input: &mut I,
|
||||||
|
stage_idx: i32,
|
||||||
|
) -> Result<(), AflError>;
|
||||||
|
|
||||||
/// Post-process given the outcome of the execution
|
/// Post-process given the outcome of the execution
|
||||||
fn post_exec(&mut self, _is_interesting: bool, _stage_idx: i32) -> Result<(), AflError> {
|
fn post_exec(&mut self, _is_interesting: bool, _stage_idx: i32) -> Result<(), AflError> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::inputs::{HasBytesVec, Input};
|
use crate::inputs::{HasBytesVec, Input};
|
||||||
|
use crate::mutators::Corpus;
|
||||||
use crate::mutators::Mutator;
|
use crate::mutators::Mutator;
|
||||||
use crate::mutators::{Corpus, HasCorpus};
|
use crate::utils::Rand;
|
||||||
use crate::utils::{HasRand, Rand};
|
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
@ -14,29 +14,27 @@ 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
|
||||||
type MutationFunction<M, S, I> = fn(&mut M, &mut S, &mut I) -> Result<MutationResult, AflError>;
|
type MutationFunction<M, C, I, R> =
|
||||||
|
fn(&mut M, &mut R, &mut C, &mut I) -> Result<MutationResult, AflError>;
|
||||||
|
|
||||||
pub trait ComposedByMutations<S, C, I, R>
|
pub trait ComposedByMutations<C, I, R>
|
||||||
where
|
where
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
/// Get a mutation by index
|
/// Get a mutation by index
|
||||||
fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<Self, S, I>, AflError>;
|
fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<Self, C, I, R>, AflError>;
|
||||||
|
|
||||||
/// 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, S, I>);
|
fn add_mutation(&mut self, mutation: MutationFunction<Self, C, I, R>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ScheduledMutator<S, C, I, R>:
|
pub trait ScheduledMutator<C, I, R>: Mutator<C, I, R> + ComposedByMutations<C, I, R>
|
||||||
Mutator<S, C, I, R> + ComposedByMutations<S, C, I, R>
|
|
||||||
where
|
where
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
@ -51,7 +49,7 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
) -> Result<MutationFunction<Self, S, I>, AflError> {
|
) -> Result<MutationFunction<Self, C, I, R>, AflError> {
|
||||||
let count = self.mutations_count() as u64;
|
let count = self.mutations_count() as u64;
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return Err(AflError::Empty("no mutations".into()));
|
return Err(AflError::Empty("no mutations".into()));
|
||||||
@ -67,47 +65,52 @@ where
|
|||||||
/// Implementations must forward mutate() to this method
|
/// Implementations must forward mutate() to this method
|
||||||
fn scheduled_mutate(
|
fn scheduled_mutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
rand: &mut R,
|
||||||
|
corpus: &mut C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
_stage_idx: i32,
|
_stage_idx: i32,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
let num = self.iterations(state.rand_mut(), input);
|
let num = self.iterations(rand, input);
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
self.schedule(state.rand_mut(), input)?(self, state, input)?;
|
self.schedule(rand, input)?(self, rand, corpus, input)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StdScheduledMutator<S, C, I, R>
|
pub struct StdScheduledMutator<C, I, R>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
mutations: Vec<MutationFunction<Self, S, I>>,
|
mutations: Vec<MutationFunction<Self, C, I, R>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, C, I, R> Mutator<S, C, I, R> for StdScheduledMutator<S, C, I, R>
|
impl<C, I, R> Mutator<C, I, R> for StdScheduledMutator<C, I, R>
|
||||||
where
|
where
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn mutate(&mut self, state: &mut S, input: &mut I, _stage_idx: i32) -> Result<(), AflError> {
|
fn mutate(
|
||||||
self.scheduled_mutate(state, input, _stage_idx)
|
&mut self,
|
||||||
|
rand: &mut R,
|
||||||
|
corpus: &mut C,
|
||||||
|
input: &mut I,
|
||||||
|
_stage_idx: i32,
|
||||||
|
) -> Result<(), AflError> {
|
||||||
|
self.scheduled_mutate(rand, corpus, input, _stage_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, C, I, R> ComposedByMutations<S, C, I, R> for StdScheduledMutator<S, C, I, R>
|
impl<C, I, R> ComposedByMutations<C, I, R> for StdScheduledMutator<C, I, R>
|
||||||
where
|
where
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<Self, S, I>, AflError> {
|
fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<Self, C, I, R>, AflError> {
|
||||||
if index >= self.mutations.len() {
|
if index >= self.mutations.len() {
|
||||||
return Err(AflError::Unknown("oob".into()));
|
return Err(AflError::Unknown("oob".into()));
|
||||||
}
|
}
|
||||||
@ -118,14 +121,13 @@ where
|
|||||||
self.mutations.len()
|
self.mutations.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_mutation(&mut self, mutation: MutationFunction<Self, S, I>) {
|
fn add_mutation(&mut self, mutation: MutationFunction<Self, C, I, R>) {
|
||||||
self.mutations.push(mutation)
|
self.mutations.push(mutation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, C, I, R> ScheduledMutator<S, C, I, R> for DefaultScheduledMutator<S, C, I, R>
|
impl<C, I, R> ScheduledMutator<C, I, R> for StdScheduledMutator<C, I, R>
|
||||||
where
|
where
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
@ -133,9 +135,8 @@ where
|
|||||||
// Just use the default methods
|
// Just use the default methods
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, C, I, R> DefaultScheduledMutator<S, C, I, R>
|
impl<C, I, R> StdScheduledMutator<C, I, R>
|
||||||
where
|
where
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
@ -145,8 +146,8 @@ where
|
|||||||
StdScheduledMutator { mutations: vec![] }
|
StdScheduledMutator { mutations: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new StdScheduledMutator instance specifying mutations and corpus too
|
/// Create a new StdScheduledMutator instance specifying mutations
|
||||||
pub fn new_all(mutations: Vec<MutationFunction<Self, S, I>>) -> Self {
|
pub fn with_mutations(mutations: Vec<MutationFunction<Self, C, I, R>>) -> Self {
|
||||||
StdScheduledMutator {
|
StdScheduledMutator {
|
||||||
mutations: mutations,
|
mutations: mutations,
|
||||||
}
|
}
|
||||||
@ -154,19 +155,19 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Bitflip mutation for inputs with a bytes vector
|
/// Bitflip mutation for inputs with a bytes vector
|
||||||
pub fn mutation_bitflip<M, S, C, R, I>(
|
pub fn mutation_bitflip<M, C, I, R>(
|
||||||
mutator: &mut M,
|
mutator: &mut M,
|
||||||
state: &mut S,
|
rand: &mut R,
|
||||||
|
_corpus: &mut C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
M: Mutator<S, C, I, R>,
|
M: Mutator<C, I, R>,
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let bit = state.rand_mut().below((input.bytes().len() * 8) as u64) as usize;
|
let bit = rand.below((input.bytes().len() * 8) as u64) as usize;
|
||||||
input.bytes_mut()[bit >> 3] ^= (128 >> (bit & 7)) as u8;
|
input.bytes_mut()[bit >> 3] ^= (128 >> (bit & 7)) as u8;
|
||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
@ -188,14 +189,14 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Splicing mutator
|
/// Splicing mutator
|
||||||
pub fn mutation_splice<M, S, C, R, I>(
|
pub fn mutation_splice<M, C, I, R>(
|
||||||
mutator: &mut M,
|
mutator: &mut M,
|
||||||
state: &mut S,
|
rand: &mut R,
|
||||||
|
corpus: &mut C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
M: Mutator<S, C, I, R>,
|
M: Mutator<C, I, R>,
|
||||||
S: HasRand<R> + HasCorpus<C, I, R>,
|
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
@ -204,7 +205,7 @@ where
|
|||||||
// 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_rr = loop {
|
let other_rr = loop {
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
let (other_rr, _) = state.corpus_mut().random_entry(state.rand_mut())?.clone();
|
let (other_rr, _) = corpus.random_entry(rand)?.clone();
|
||||||
match other_rr.try_borrow_mut() {
|
match other_rr.try_borrow_mut() {
|
||||||
Ok(_) => found = true,
|
Ok(_) => found = true,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@ -251,42 +252,41 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule some selected byte level mutations given a ScheduledMutator type
|
/// Schedule some selected byte level mutations given a ScheduledMutator type
|
||||||
pub struct HavocBytesMutator<C, I, SM, R>
|
pub struct HavocBytesMutator<SM, C, I, R>
|
||||||
where
|
where
|
||||||
|
SM: ScheduledMutator<C, I, R>,
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
SM: ScheduledMutator<C, I, R>,
|
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
scheduled: SM,
|
scheduled: SM,
|
||||||
phantom: PhantomData<(I, R)>,
|
phantom: PhantomData<(I, R, C)>,
|
||||||
_phantom_corpus: PhantomData<C>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, SM, R> Mutator<C, I, R> for HavocBytesMutator<C, I, SM, R>
|
impl<SM, C, I, R> Mutator<C, I, R> for HavocBytesMutator<SM, C, I, R>
|
||||||
where
|
where
|
||||||
|
SM: ScheduledMutator<C, I, R>,
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
SM: ScheduledMutator<C, I, R>,
|
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
/// Mutate bytes
|
/// Mutate bytes
|
||||||
fn mutate(
|
fn mutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
corpus: &mut C,
|
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
|
corpus: &mut C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
stage_idx: i32,
|
stage_idx: i32,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
self.scheduled.mutate(corpus, rand, input, stage_idx)
|
self.scheduled.mutate(rand, corpus, input, stage_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, SM, R> HavocBytesMutator<C, I, SM, R>
|
impl<SM, C, I, R> HavocBytesMutator<SM, C, I, R>
|
||||||
where
|
where
|
||||||
|
SM: ScheduledMutator<C, I, R>,
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
SM: ScheduledMutator<C, I, R>,
|
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
/// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap
|
/// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap
|
||||||
@ -296,12 +296,11 @@ where
|
|||||||
HavocBytesMutator {
|
HavocBytesMutator {
|
||||||
scheduled: scheduled,
|
scheduled: scheduled,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
_phantom_corpus: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R> HavocBytesMutator<C, I, StdScheduledMutator<C, I, R>, R>
|
impl<C, I, R> HavocBytesMutator<StdScheduledMutator<C, I, R>, C, I, R>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
@ -315,7 +314,6 @@ where
|
|||||||
HavocBytesMutator {
|
HavocBytesMutator {
|
||||||
scheduled: scheduled,
|
scheduled: scheduled,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
_phantom_corpus: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -334,7 +332,7 @@ mod tests {
|
|||||||
fn test_mut_splice() {
|
fn test_mut_splice() {
|
||||||
// With the current impl, seed of 1 will result in a split at pos 2.
|
// With the current impl, seed of 1 will result in a split at pos 2.
|
||||||
let mut rand = XKCDRand::new();
|
let mut rand = XKCDRand::new();
|
||||||
let mut corpus: InMemoryCorpus<BytesInput, _> = InMemoryCorpus::new();
|
let mut corpus: InMemoryCorpus<BytesInput, XKCDRand> = InMemoryCorpus::new();
|
||||||
corpus.add(Testcase::new(vec!['a' as u8, 'b' as u8, 'c' as u8]).into());
|
corpus.add(Testcase::new(vec!['a' as u8, 'b' as u8, 'c' as u8]).into());
|
||||||
corpus.add(Testcase::new(vec!['d' as u8, 'e' as u8, 'f' as u8]).into());
|
corpus.add(Testcase::new(vec!['d' as u8, 'e' as u8, 'f' as u8]).into());
|
||||||
|
|
||||||
@ -345,9 +343,9 @@ mod tests {
|
|||||||
let mut input = testcase.load_input().expect("No input in testcase").clone();
|
let mut input = testcase.load_input().expect("No input in testcase").clone();
|
||||||
|
|
||||||
rand.set_seed(5);
|
rand.set_seed(5);
|
||||||
let mut mutator = StdScheduledMutator::<InMemoryCorpus<_, _>, BytesInput, XKCDRand>::new();
|
let mut mutator = StdScheduledMutator::new();
|
||||||
|
|
||||||
mutation_splice(&mut mutator, &mut corpus, &mut rand, &mut input).unwrap();
|
mutation_splice(&mut mutator, &mut rand, &mut corpus, &mut input).unwrap();
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
println!("{:?}", input.bytes());
|
println!("{:?}", input.bytes());
|
||||||
|
@ -4,6 +4,7 @@ pub use mutational::StdMutationalStage;
|
|||||||
use crate::corpus::testcase::Testcase;
|
use crate::corpus::testcase::Testcase;
|
||||||
use crate::corpus::Corpus;
|
use crate::corpus::Corpus;
|
||||||
use crate::engines::State;
|
use crate::engines::State;
|
||||||
|
use crate::events::EventManager;
|
||||||
use crate::executors::Executor;
|
use crate::executors::Executor;
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::utils::Rand;
|
use crate::utils::Rand;
|
||||||
@ -11,11 +12,12 @@ use crate::AflError;
|
|||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
|
||||||
pub trait Stage<S, C, E, I, R>
|
pub trait Stage<S, EM, E, C, I, R>
|
||||||
where
|
where
|
||||||
S: State<C, E, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
EM: EventManager,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
@ -24,6 +26,7 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
events: &mut EM,
|
||||||
testcase: Rc<RefCell<Testcase<I>>>,
|
testcase: Rc<RefCell<Testcase<I>>>,
|
||||||
) -> Result<(), AflError>;
|
) -> Result<(), AflError>;
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,13 @@ use crate::AflError;
|
|||||||
|
|
||||||
// TODO multi mutators stage
|
// TODO multi mutators stage
|
||||||
|
|
||||||
pub trait MutationalStage<M, S, C, E, I, R>: Stage<S, C, E, I, R>
|
pub trait MutationalStage<M, S, EM, E, C, I, R>: Stage<S, EM, E, C, I, R>
|
||||||
where
|
where
|
||||||
M: Mutator<C, I, R>,
|
M: Mutator<C, I, R>,
|
||||||
S: State<C, E, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
EM: EventManager,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
@ -41,6 +42,7 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
events: &mut EM,
|
||||||
testcase: Rc<RefCell<Testcase<I>>>,
|
testcase: Rc<RefCell<Testcase<I>>>,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
let num = self.iterations(rand);
|
let num = self.iterations(rand);
|
||||||
@ -49,7 +51,7 @@ where
|
|||||||
for i in 0..num {
|
for i in 0..num {
|
||||||
let mut input_tmp = input.clone();
|
let mut input_tmp = input.clone();
|
||||||
self.mutator_mut()
|
self.mutator_mut()
|
||||||
.mutate(rand, state, &mut input_tmp, i as i32)?;
|
.mutate(rand, state.corpus_mut(), &mut input_tmp, i as i32)?;
|
||||||
|
|
||||||
let interesting = state.evaluate_input(&input_tmp)?;
|
let interesting = state.evaluate_input(&input_tmp)?;
|
||||||
|
|
||||||
@ -64,28 +66,28 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The default mutational stage
|
/// The default mutational stage
|
||||||
pub struct StdMutationalStage<M, S, C, E, EM, I, R>
|
pub struct StdMutationalStage<M, S, EM, E, C, I, R>
|
||||||
where
|
where
|
||||||
M: Mutator<C, I, R>,
|
M: Mutator<C, I, R>,
|
||||||
S: State<C, E, EM, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
|
||||||
E: Executor<I>,
|
|
||||||
EM: EventManager,
|
EM: EventManager,
|
||||||
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
mutator: M,
|
mutator: M,
|
||||||
phantom: PhantomData<(S, C, E, EM, I, R)>,
|
phantom: PhantomData<(S, EM, E, C, I, R)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, S, C, E, EM, I, R> MutationalStage<M, S, C, E, EM, I, R>
|
impl<M, S, EM, E, C, I, R> MutationalStage<M, S, EM, E, C, I, R>
|
||||||
for StdMutationalStage<M, S, C, E, EM, I, R>
|
for StdMutationalStage<M, S, EM, E, C, I, R>
|
||||||
where
|
where
|
||||||
M: Mutator<C, I, R>,
|
M: Mutator<C, I, R>,
|
||||||
S: State<C, E, EM, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
|
||||||
E: Executor<I>,
|
|
||||||
EM: EventManager,
|
EM: EventManager,
|
||||||
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
@ -100,32 +102,34 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, S, C, E, EM, I, R> Stage<S, C, E, EM, I, R> for StdMutationalStage<M, S, C, E, EM, I, R>
|
impl<M, S, EM, E, C, I, R> Stage<S, EM, E, C, I, R> for StdMutationalStage<M, S, EM, E, C, I, R>
|
||||||
where
|
where
|
||||||
M: Mutator<C, I, R>,
|
M: Mutator<C, I, R>,
|
||||||
S: State<C, E, EM, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
|
||||||
E: Executor<I>,
|
|
||||||
EM: EventManager,
|
EM: EventManager,
|
||||||
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn perform(
|
fn perform(
|
||||||
&mut self,
|
&mut self,
|
||||||
testcase: Rc<RefCell<Testcase<I>>>,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
events: &mut EM,
|
||||||
|
testcase: Rc<RefCell<Testcase<I>>>,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
self.perform_mutational(testcase, state)
|
self.perform_mutational(rand, state, events, testcase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, S, C, E, EM, I, R> StdMutationalStage<M, S, C, E, EM, I, R>
|
impl<M, S, EM, E, C, I, R> StdMutationalStage<M, S, EM, E, C, I, R>
|
||||||
where
|
where
|
||||||
M: Mutator<C, I, R>,
|
M: Mutator<C, I, R>,
|
||||||
S: State<C, E, EM, I, R>,
|
S: State<C, E, I, R>,
|
||||||
C: Corpus<I, R>,
|
|
||||||
E: Executor<I>,
|
|
||||||
EM: EventManager,
|
EM: EventManager,
|
||||||
|
E: Executor<I>,
|
||||||
|
C: Corpus<I, R>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,8 @@ use alloc::rc::Rc;
|
|||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
|
||||||
use afl::corpus::{Corpus, InMemoryCorpus, Testcase};
|
use afl::corpus::{Corpus, InMemoryCorpus, Testcase};
|
||||||
use afl::engines::{StdEngine, StdState, Engine, State};
|
use afl::engines::{Engine, State, StdEngine, StdState};
|
||||||
|
use afl::events::LoggerEventManager;
|
||||||
use afl::executors::inmemory::InMemoryExecutor;
|
use afl::executors::inmemory::InMemoryExecutor;
|
||||||
use afl::executors::{Executor, ExitKind};
|
use afl::executors::{Executor, ExitKind};
|
||||||
use afl::feedbacks::{create_history_map, MaxMapFeedback};
|
use afl::feedbacks::{create_history_map, MaxMapFeedback};
|
||||||
@ -39,9 +40,9 @@ fn harness<I>(_executor: &dyn Executor<I>, buf: &[u8]) -> ExitKind {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn afl_libfuzzer_main() {
|
pub extern "C" fn afl_libfuzzer_main() {
|
||||||
let rand = StdRand::new(0).into();
|
let mut rand = StdRand::new(0);
|
||||||
|
|
||||||
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
|
let mut corpus = InMemoryCorpus::new();
|
||||||
let testcase = Testcase::new(vec![0; 4]).into();
|
let testcase = Testcase::new(vec![0; 4]).into();
|
||||||
corpus.add(testcase);
|
corpus.add(testcase);
|
||||||
|
|
||||||
@ -58,16 +59,17 @@ pub extern "C" fn afl_libfuzzer_main() {
|
|||||||
state.add_feedback(Box::new(edges_feedback));
|
state.add_feedback(Box::new(edges_feedback));
|
||||||
|
|
||||||
let mut engine = StdEngine::new();
|
let mut engine = StdEngine::new();
|
||||||
let mutator = HavocBytesMutator::new_default(&rand);
|
let mutator = HavocBytesMutator::new_default();
|
||||||
let stage = StdMutationalStage::new(&rand, mutator);
|
let stage = StdMutationalStage::new(mutator);
|
||||||
engine.add_stage(Box::new(stage));
|
engine.add_stage(Box::new(stage));
|
||||||
|
|
||||||
|
let mut events = LoggerEventManager::new();
|
||||||
|
|
||||||
for i in 0..1000 {
|
for i in 0..1000 {
|
||||||
engine
|
engine
|
||||||
.fuzz_one(&mut state)
|
.fuzz_one(&mut rand, &mut state, &mut events)
|
||||||
.expect(&format!("Error in iter {}", i));
|
.expect(&format!("Error in iter {}", i));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
println!("OK");
|
println!("OK");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user