TracingStage
This commit is contained in:
parent
b28306519f
commit
f61140bdcf
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user