diff --git a/libafl/src/stages/tracing.rs b/libafl/src/stages/tracing.rs index 25c654780d..0ba71f6259 100644 --- a/libafl/src/stages/tracing.rs +++ b/libafl/src/stages/tracing.rs @@ -1,142 +1,54 @@ use core::{marker::PhantomData, mem::drop}; use crate::{ - bolts::rands::Rand, corpus::Corpus, - fuzzer::Evaluator, + executors::{Executor, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks}, inputs::Input, mark_feature_time, - mutators::Mutator, + observers::ObserversTuple, stages::Stage, start_timer, - state::{HasClientPerfStats, HasCorpus, HasRand}, + state::{HasClientPerfStats, HasCorpus, HasExecutions}, Error, }; #[cfg(feature = "introspection")] 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: Stage -where - C: Corpus, - M: Mutator, - I: Input, - S: HasClientPerfStats + HasCorpus, - Z: Evaluator, -{ - /// 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 #[derive(Clone, Debug)] -pub struct StdMutationalStage +pub struct TracingStage where - C: Corpus, - M: Mutator, I: Input, - R: Rand, - S: HasClientPerfStats + HasCorpus + HasRand, - Z: Evaluator, + C: Corpus, + TE: Executor + + HasObservers + + HasExecHooks + + HasObserversHooks, + OT: ObserversTuple + HasExecHooksTuple, + S: HasClientPerfStats + HasExecutions + HasCorpus, { - mutator: M, + tracer_executor: TE, #[allow(clippy::type_complexity)] - phantom: PhantomData<(C, E, EM, I, R, S, Z)>, + phantom: PhantomData<(C, EM, I, OT, S, TE, Z)>, } -impl MutationalStage - for StdMutationalStage +impl Stage for TracingStage where - C: Corpus, - M: Mutator, I: Input, - R: Rand, - S: HasClientPerfStats + HasCorpus + HasRand, - Z: Evaluator, -{ - /// 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 Stage for StdMutationalStage -where C: Corpus, - M: Mutator, - I: Input, - R: Rand, - S: HasClientPerfStats + HasCorpus + HasRand, - Z: Evaluator, + TE: Executor + + HasObservers + + HasExecHooks + + HasObserversHooks, + OT: ObserversTuple + HasExecHooksTuple, + S: HasClientPerfStats + HasExecutions + HasCorpus, { #[inline] fn perform( &mut self, fuzzer: &mut Z, - executor: &mut E, + _executor: &mut E, state: &mut S, manager: &mut EM, corpus_idx: usize, @@ -161,7 +73,7 @@ where mark_feature_time!(state, PerfFeature::PreExec); start_timer!(state); - drop(self.tracer_executor.run_target(&input)?); + let _ = self.tracer_executor.run_target(&input)?; mark_feature_time!(state, PerfFeature::TargetExecution); start_timer!(state); @@ -180,19 +92,21 @@ where } } -impl StdMutationalStage +impl TracingStage where - C: Corpus, - M: Mutator, I: Input, - R: Rand, - S: HasClientPerfStats + HasCorpus + HasRand, - Z: Evaluator, + C: Corpus, + TE: Executor + + HasObservers + + HasExecHooks + + HasObserversHooks, + OT: ObserversTuple + HasExecHooksTuple, + S: HasClientPerfStats + HasExecutions + HasCorpus, { /// Creates a new default mutational stage - pub fn new(mutator: M) -> Self { + pub fn new(tracer_executor: TE) -> Self { Self { - mutator, + tracer_executor, phantom: PhantomData, } }