TracingStage

This commit is contained in:
Andrea Fioraldi 2021-05-20 08:54:03 +02:00 committed by Omree
parent b28306519f
commit f61140bdcf

View File

@ -1,142 +1,54 @@
use core::{marker::PhantomData, mem::drop}; use core::{marker::PhantomData, mem::drop};
use crate::{ use crate::{
bolts::rands::Rand,
corpus::Corpus, corpus::Corpus,
fuzzer::Evaluator, executors::{Executor, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks},
inputs::Input, inputs::Input,
mark_feature_time, mark_feature_time,
mutators::Mutator, observers::ObserversTuple,
stages::Stage, stages::Stage,
start_timer, start_timer,
state::{HasClientPerfStats, HasCorpus, HasRand}, state::{HasClientPerfStats, HasCorpus, HasExecutions},
Error, Error,
}; };
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::stats::PerfFeature; use crate::stats::PerfFeature;
// TODO multi mutators stage
/// 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 TracingStage<C, E, EM, I, M, S, Z>: Stage<E, EM, S, Z>
where
C: Corpus<I>,
M: Mutator<I, S>,
I: Input,
S: HasClientPerfStats + HasCorpus<C, I>,
Z: Evaluator<E, EM, I, S>,
{
/// The mutator registered for this stage
fn mutator(&self) -> &M;
/// The mutator registered for this stage (mutable)
fn mutator_mut(&mut self) -> &mut M;
/// Gets the number of iterations this mutator should run for.
fn iterations(&self, state: &mut S) -> usize;
/// Runs this (mutational) stage for the given testcase
#[allow(clippy::cast_possible_wrap)] // more than i32 stages on 32 bit system - highly unlikely...
fn perform_mutational(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut S,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), Error> {
let num = self.iterations(state);
for i in 0..num {
start_timer!(state);
let mut input = state
.corpus()
.get(corpus_idx)?
.borrow_mut()
.load_input()?
.clone();
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
start_timer!(state);
self.mutator_mut().mutate(state, &mut input, i as i32)?;
mark_feature_time!(state, PerfFeature::Mutate);
// Time is measured directly the `evaluate_input` function
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, input)?;
start_timer!(state);
self.mutator_mut().post_exec(state, i as i32, corpus_idx)?;
mark_feature_time!(state, PerfFeature::MutatePostExec);
}
Ok(())
}
}
/// Default value, how many iterations each stage gets, as an upper bound
/// It may randomly continue earlier.
pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: u64 = 128;
/// The default mutational stage /// The default mutational stage
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct StdMutationalStage<C, E, EM, I, M, R, S, Z> pub struct TracingStage<C, EM, I, OT, S, TE, Z>
where where
C: Corpus<I>,
M: Mutator<I, S>,
I: Input, I: Input,
R: Rand, C: Corpus<I>,
S: HasClientPerfStats + HasCorpus<C, I> + HasRand<R>, TE: Executor<I>
Z: Evaluator<E, EM, I, S>, + HasObservers<OT>
+ HasExecHooks<EM, I, S, Z>
+ HasObserversHooks<EM, I, OT, S, Z>,
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
{ {
mutator: M, tracer_executor: TE,
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
phantom: PhantomData<(C, E, EM, I, R, S, Z)>, phantom: PhantomData<(C, EM, I, OT, S, TE, Z)>,
} }
impl<C, E, EM, I, M, R, S, Z> MutationalStage<C, E, EM, I, M, S, Z> impl<E, C, EM, I, OT, S, TE, Z> Stage<E, EM, S, Z> for TracingStage<C, EM, I, OT, S, TE, Z>
for StdMutationalStage<C, E, EM, I, M, R, S, Z>
where where
C: Corpus<I>,
M: Mutator<I, S>,
I: Input, I: Input,
R: Rand,
S: HasClientPerfStats + HasCorpus<C, I> + HasRand<R>,
Z: Evaluator<E, EM, I, S>,
{
/// The mutator, added to this stage
#[inline]
fn mutator(&self) -> &M {
&self.mutator
}
/// The list of mutators, added to this stage (as mutable ref)
#[inline]
fn mutator_mut(&mut self) -> &mut M {
&mut self.mutator
}
/// Gets the number of iterations as a random number
fn iterations(&self, state: &mut S) -> usize {
1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS) as usize
}
}
impl<C, E, EM, I, M, R, S, Z> Stage<E, EM, S, Z> for StdMutationalStage<C, E, EM, I, M, R, S, Z>
where
C: Corpus<I>, C: Corpus<I>,
M: Mutator<I, S>, TE: Executor<I>
I: Input, + HasObservers<OT>
R: Rand, + HasExecHooks<EM, I, S, Z>
S: HasClientPerfStats + HasCorpus<C, I> + HasRand<R>, + HasObserversHooks<EM, I, OT, S, Z>,
Z: Evaluator<E, EM, I, S>, OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
{ {
#[inline] #[inline]
fn perform( fn perform(
&mut self, &mut self,
fuzzer: &mut Z, fuzzer: &mut Z,
executor: &mut E, _executor: &mut E,
state: &mut S, state: &mut S,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
@ -161,7 +73,7 @@ where
mark_feature_time!(state, PerfFeature::PreExec); mark_feature_time!(state, PerfFeature::PreExec);
start_timer!(state); start_timer!(state);
drop(self.tracer_executor.run_target(&input)?); let _ = self.tracer_executor.run_target(&input)?;
mark_feature_time!(state, PerfFeature::TargetExecution); mark_feature_time!(state, PerfFeature::TargetExecution);
start_timer!(state); start_timer!(state);
@ -180,19 +92,21 @@ where
} }
} }
impl<C, E, EM, I, M, R, S, Z> StdMutationalStage<C, E, EM, I, M, R, S, Z> impl<C, EM, I, OT, S, TE, Z> TracingStage<C, EM, I, OT, S, TE, Z>
where where
C: Corpus<I>,
M: Mutator<I, S>,
I: Input, I: Input,
R: Rand, C: Corpus<I>,
S: HasClientPerfStats + HasCorpus<C, I> + HasRand<R>, TE: Executor<I>
Z: Evaluator<E, EM, I, S>, + HasObservers<OT>
+ HasExecHooks<EM, I, S, Z>
+ HasObserversHooks<EM, I, OT, S, Z>,
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
{ {
/// Creates a new default mutational stage /// Creates a new default mutational stage
pub fn new(mutator: M) -> Self { pub fn new(tracer_executor: TE) -> Self {
Self { Self {
mutator, tracer_executor,
phantom: PhantomData, phantom: PhantomData,
} }
} }