Fix usage of TracingStage (#3062)

* real fix

* more

* debug

* fix

* fixer

* mmmm

* mm

* mm

* mm

* fix

* fix atheris

* ?
This commit is contained in:
Dongjia "toka" Zhang 2025-03-11 14:37:19 +01:00 committed by GitHub
parent f4cb9a827d
commit 226a20e6cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 186 additions and 199 deletions

View File

@ -370,7 +370,7 @@ unsafe fn fuzz(
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(

View File

@ -218,7 +218,7 @@ fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = let i2s =

View File

@ -344,7 +344,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(

View File

@ -391,7 +391,7 @@ fn fuzz(
println!("We imported {} inputs from disk.", state.corpus().count()); println!("We imported {} inputs from disk.", state.corpus().count());
} }
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, power); let mut stages = tuple_list!(calibration, tracing, i2s, power);

View File

@ -403,7 +403,7 @@ fn fuzz(
println!("We imported {} input(s) from disk.", state.corpus().count()); println!("We imported {} input(s) from disk.", state.corpus().count());
} }
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, power); let mut stages = tuple_list!(calibration, tracing, i2s, power);

View File

@ -316,7 +316,7 @@ impl<M: Monitor> Instance<'_, M> {
let mut shadow_executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); let mut shadow_executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
let tracing = ShadowTracingStage::new(&mut shadow_executor); let tracing = ShadowTracingStage::new();
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(

View File

@ -192,7 +192,7 @@ impl<M: Monitor> Instance<'_, M> {
I2SRandReplace::new() I2SRandReplace::new()
))); )));
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new(

View File

@ -232,7 +232,7 @@ pub fn fuzz() {
))); )));
// Setup an havoc mutator with a mutational stage // Setup an havoc mutator with a mutational stage
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
let mutator = StdScheduledMutator::new(havoc_mutations()); let mutator = StdScheduledMutator::new(havoc_mutations());
let mut stages = tuple_list!(tracing, i2s, StdMutationalStage::new(mutator),); let mut stages = tuple_list!(tracing, i2s, StdMutationalStage::new(mutator),);

View File

@ -240,7 +240,7 @@ pub fn fuzz() {
))); )));
// Setup an havoc mutator with a mutational stage // Setup an havoc mutator with a mutational stage
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
let mutator = StdScheduledMutator::new(havoc_mutations()); let mutator = StdScheduledMutator::new(havoc_mutations());
let mut stages = tuple_list!(tracing, i2s, StdMutationalStage::new(mutator),); let mut stages = tuple_list!(tracing, i2s, StdMutationalStage::new(mutator),);

View File

@ -14,7 +14,7 @@ use clap::{Arg, ArgAction, Command};
use libafl::{ use libafl::{
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::{launcher::Launcher, EventConfig}, events::{launcher::Launcher, EventConfig},
executors::{inprocess::InProcessExecutor, ExitKind}, executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
feedback_or, feedback_or,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
@ -28,7 +28,7 @@ use libafl::{
}, },
observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::{StdMutationalStage, TracingStage}, stages::{ShadowTracingStage, StdMutationalStage, TracingStage},
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
Error, HasMetadata, Error, HasMetadata,
}; };
@ -216,14 +216,9 @@ pub extern "C" fn LLVMFuzzerRunDriver(
ExitKind::Ok ExitKind::Ok
}; };
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = TracingStage::new(InProcessExecutor::new( let tracing = ShadowTracingStage::new();
&mut harness,
tuple_list!(cmplog_observer),
&mut fuzzer,
&mut state,
&mut mgr,
)?);
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = let i2s =

View File

@ -19,7 +19,7 @@ use libafl::{
Error, HasMetadata, Error, HasMetadata,
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
events::SimpleRestartingEventManager, events::SimpleRestartingEventManager,
executors::{ExitKind, inprocess::InProcessExecutor}, executors::{ExitKind, ShadowExecutor, inprocess::InProcessExecutor},
feedback_or, feedback_or,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
@ -34,7 +34,7 @@ use libafl::{
IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, powersched::PowerSchedule,
}, },
stages::{ stages::{
StdMutationalStage, TracingStage, calibrate::CalibrationStage, ShadowTracingStage, StdMutationalStage, calibrate::CalibrationStage,
power::StdPowerMutationalStage, power::StdPowerMutationalStage,
}, },
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
@ -331,8 +331,6 @@ fn fuzz(
ExitKind::Ok ExitKind::Ok
}; };
let mut tracing_harness = harness;
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time // Create the executor for an in-process function with one observer for edge coverage and one for the execution time
let mut executor = InProcessExecutor::with_timeout( let mut executor = InProcessExecutor::with_timeout(
&mut harness, &mut harness,
@ -343,18 +341,10 @@ fn fuzz(
timeout, timeout,
)?; )?;
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = TracingStage::new( let tracing = ShadowTracingStage::new();
InProcessExecutor::with_timeout(
&mut tracing_harness,
tuple_list!(cmplog_observer),
&mut fuzzer,
&mut state,
&mut mgr,
timeout * 10,
)?,
// Give it more time!
);
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, power); let mut stages = tuple_list!(calibration, tracing, i2s, power);

View File

@ -18,10 +18,7 @@ use clap::{Arg, Command};
use libafl::{ use libafl::{
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
events::SimpleRestartingEventManager, events::SimpleRestartingEventManager,
executors::{ executors::{inprocess::HookableInProcessExecutor, ExitKind, ShadowExecutor},
inprocess::{HookableInProcessExecutor, InProcessExecutor},
ExitKind,
},
feedback_or, feedback_or,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
@ -36,8 +33,8 @@ use libafl::{
powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler,
}, },
stages::{ stages::{
calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, calibrate::CalibrationStage, power::StdPowerMutationalStage, ShadowTracingStage,
TracingStage, StdMutationalStage,
}, },
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
Error, HasMetadata, Error, HasMetadata,
@ -343,24 +340,10 @@ fn fuzz(
ExitKind::Ok ExitKind::Ok
}; };
let mut tracing_harness = harness;
let ctx_hook = CtxHook::new(); let ctx_hook = CtxHook::new();
// Setup a tracing stage in which we log comparisons
let tracing = TracingStage::new(
InProcessExecutor::with_timeout(
&mut tracing_harness,
tuple_list!(cmplog_observer),
&mut fuzzer,
&mut state,
&mut mgr,
timeout * 10,
)?,
// Give it more time!
);
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time // Create the executor for an in-process function with one observer for edge coverage and one for the execution time
let mut executor = HookableInProcessExecutor::with_timeout_generic( let executor = HookableInProcessExecutor::with_timeout_generic(
tuple_list!(ctx_hook), tuple_list!(ctx_hook),
&mut harness, &mut harness,
tuple_list!(edges_observer, time_observer), tuple_list!(edges_observer, time_observer),
@ -370,6 +353,10 @@ fn fuzz(
timeout, timeout,
)?; )?;
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
// Setup a tracing stage in which we log comparisons
let tracing = ShadowTracingStage::new();
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, power); let mut stages = tuple_list!(calibration, tracing, i2s, power);

View File

@ -19,7 +19,7 @@ use content_inspector::inspect;
use libafl::{ use libafl::{
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
events::SimpleRestartingEventManager, events::SimpleRestartingEventManager,
executors::{inprocess::InProcessExecutor, ExitKind}, executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
feedback_or, feedback_or,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
@ -40,7 +40,7 @@ use libafl::{
}, },
stages::{ stages::{
calibrate::CalibrationStage, power::StdPowerMutationalStage, GeneralizationStage, calibrate::CalibrationStage, power::StdPowerMutationalStage, GeneralizationStage,
StdMutationalStage, TracingStage, ShadowTracingStage, StdMutationalStage,
}, },
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
Error, HasMetadata, Error, HasMetadata,
@ -400,8 +400,6 @@ fn fuzz_binary(
ExitKind::Ok ExitKind::Ok
}; };
let mut tracing_harness = harness;
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time // Create the executor for an in-process function with one observer for edge coverage and one for the execution time
let mut executor = InProcessExecutor::with_timeout( let mut executor = InProcessExecutor::with_timeout(
&mut harness, &mut harness,
@ -413,14 +411,9 @@ fn fuzz_binary(
)?; )?;
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = TracingStage::new(InProcessExecutor::with_timeout( let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
&mut tracing_harness,
tuple_list!(cmplog_observer), let tracing = ShadowTracingStage::new();
&mut fuzzer,
&mut state,
&mut mgr,
timeout * 10,
)?);
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, power); let mut stages = tuple_list!(calibration, tracing, i2s, power);
@ -632,8 +625,6 @@ fn fuzz_text(
ExitKind::Ok ExitKind::Ok
}; };
let mut tracing_harness = harness;
let generalization = GeneralizationStage::new(&edges_observer); let generalization = GeneralizationStage::new(&edges_observer);
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time // Create the executor for an in-process function with one observer for edge coverage and one for the execution time
@ -646,15 +637,8 @@ fn fuzz_text(
timeout, timeout,
)?; )?;
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = TracingStage::new(InProcessExecutor::with_timeout( let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
&mut tracing_harness, let tracing = ShadowTracingStage::new();
tuple_list!(cmplog_observer),
&mut fuzzer,
&mut state,
&mut mgr,
// Give it more time!
timeout * 10,
)?);
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!(generalization, calibration, tracing, i2s, power, grimoire); let mut stages = tuple_list!(generalization, calibration, tracing, i2s, power, grimoire);

View File

@ -152,7 +152,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
} }
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));

View File

@ -190,7 +190,7 @@ fn fuzz(
} }
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));

View File

@ -37,7 +37,7 @@ pub use sync::*;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use time_tracker::TimeTrackingStageWrapper; pub use time_tracker::TimeTrackingStageWrapper;
pub use tmin::{ObserverEqualityFactory, ObserverEqualityFeedback, StdTMinMutationalStage}; pub use tmin::{ObserverEqualityFactory, ObserverEqualityFeedback, StdTMinMutationalStage};
pub use tracing::{ShadowTracingStage, TracingStage}; pub use tracing::TracingStage;
pub use tuneable::*; pub use tuneable::*;
use tuple_list::NonEmptyTuple; use tuple_list::NonEmptyTuple;
#[cfg(feature = "unicode")] #[cfg(feature = "unicode")]
@ -57,6 +57,9 @@ pub mod mutational;
pub mod push; pub mod push;
pub mod tmin; pub mod tmin;
pub mod shadow;
pub use shadow::*;
pub mod replay; pub mod replay;
pub use replay::*; pub use replay::*;

139
libafl/src/stages/shadow.rs Normal file
View File

@ -0,0 +1,139 @@
//! A stage that runs the shadow executor using also the shadow observers. Unlike tracing stage, this
//! stage *CAN* be used with inprocess executor.
use alloc::{
borrow::{Cow, ToOwned},
string::ToString,
};
use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::Named;
#[cfg(feature = "introspection")]
use crate::monitors::stats::PerfFeature;
use crate::{
Error, HasNamedMetadata,
corpus::HasCurrentCorpusId,
executors::{Executor, HasObservers, ShadowExecutor},
mark_feature_time,
observers::ObserversTuple,
stages::{Restartable, RetryCountRestartHelper, Stage},
start_timer,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, MaybeHasClientPerfMonitor},
};
/// A stage that runs the shadow executor using also the shadow observers
#[derive(Clone, Debug)]
pub struct ShadowTracingStage<E, EM, I, SOT, S, Z> {
name: Cow<'static, str>,
phantom: PhantomData<(E, EM, I, SOT, S, Z)>,
}
impl<E, EM, I, SOT, S, Z> Default for ShadowTracingStage<E, EM, I, SOT, S, Z>
where
E: Executor<EM, I, S, Z> + HasObservers,
S: HasExecutions + HasCorpus<I>,
SOT: ObserversTuple<I, S>,
{
fn default() -> Self {
Self::new()
}
}
/// The counter for giving this stage unique id
static mut SHADOW_TRACING_STAGE_ID: usize = 0;
/// Name for shadow tracing stage
pub static SHADOW_TRACING_STAGE_NAME: &str = "shadow";
impl<E, EM, I, SOT, S, Z> Named for ShadowTracingStage<E, EM, I, SOT, S, Z> {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl<E, EM, I, SOT, S, Z> Stage<ShadowExecutor<E, I, S, SOT>, EM, S, Z>
for ShadowTracingStage<E, EM, I, SOT, S, Z>
where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
SOT: ObserversTuple<I, S>,
S: HasExecutions
+ HasCorpus<I>
+ HasNamedMetadata
+ Debug
+ HasCurrentTestcase<I>
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor,
{
#[inline]
fn perform(
&mut self,
fuzzer: &mut Z,
executor: &mut ShadowExecutor<E, I, S, SOT>,
state: &mut S,
manager: &mut EM,
) -> Result<(), Error> {
start_timer!(state);
let input = state.current_input_cloned()?;
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
start_timer!(state);
executor
.shadow_observers_mut()
.pre_exec_all(state, &input)?;
executor.observers_mut().pre_exec_all(state, &input)?;
mark_feature_time!(state, PerfFeature::PreExecObservers);
start_timer!(state);
let exit_kind = executor.run_target(fuzzer, state, manager, &input)?;
mark_feature_time!(state, PerfFeature::TargetExecution);
start_timer!(state);
executor
.shadow_observers_mut()
.post_exec_all(state, &input, &exit_kind)?;
executor
.observers_mut()
.post_exec_all(state, &input, &exit_kind)?;
mark_feature_time!(state, PerfFeature::PostExecObservers);
Ok(())
}
}
impl<E, EM, I, SOT, S, Z> Restartable<S> for ShadowTracingStage<E, EM, I, SOT, S, Z>
where
S: HasNamedMetadata + HasCurrentCorpusId,
{
fn should_restart(&mut self, state: &mut S) -> Result<bool, Error> {
RetryCountRestartHelper::no_retry(state, &self.name)
}
fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> {
RetryCountRestartHelper::clear_progress(state, &self.name)
}
}
impl<E, EM, I, SOT, S, Z> ShadowTracingStage<E, EM, I, SOT, S, Z>
where
E: Executor<EM, I, S, Z> + HasObservers,
S: HasExecutions + HasCorpus<I>,
SOT: ObserversTuple<I, S>,
{
/// Creates a new default stage
pub fn new() -> Self {
// unsafe but impossible that you create two threads both instantiating this instance
let stage_id = unsafe {
let ret = SHADOW_TRACING_STAGE_ID;
SHADOW_TRACING_STAGE_ID += 1;
ret
};
Self {
name: Cow::Owned(
SHADOW_TRACING_STAGE_NAME.to_owned() + ":" + stage_id.to_string().as_str(),
),
phantom: PhantomData,
}
}
}

View File

@ -13,7 +13,7 @@ use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
Error, HasNamedMetadata, Error, HasNamedMetadata,
corpus::HasCurrentCorpusId, corpus::HasCurrentCorpusId,
executors::{Executor, HasObservers, ShadowExecutor}, executors::{Executor, HasObservers},
inputs::Input, inputs::Input,
mark_feature_time, mark_feature_time,
observers::ObserversTuple, observers::ObserversTuple,
@ -23,6 +23,7 @@ use crate::{
}; };
/// A stage that runs a tracer executor /// A stage that runs a tracer executor
/// This should *NOT* be used with inprocess executor
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TracingStage<EM, I, TE, S, Z> { pub struct TracingStage<EM, I, TE, S, Z> {
name: Cow<'static, str>, name: Cow<'static, str>,
@ -146,108 +147,3 @@ impl<EM, I, TE, S, Z> TracingStage<EM, I, TE, S, Z> {
&mut self.tracer_executor &mut self.tracer_executor
} }
} }
/// A stage that runs the shadow executor using also the shadow observers
#[derive(Clone, Debug)]
pub struct ShadowTracingStage<E, EM, I, SOT, S, Z> {
name: Cow<'static, str>,
phantom: PhantomData<(E, EM, I, SOT, S, Z)>,
}
/// The counter for giving this stage unique id
static mut SHADOW_TRACING_STAGE_ID: usize = 0;
/// Name for shadow tracing stage
pub static SHADOW_TRACING_STAGE_NAME: &str = "shadow";
impl<E, EM, I, SOT, S, Z> Named for ShadowTracingStage<E, EM, I, SOT, S, Z> {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl<E, EM, I, SOT, S, Z> Stage<ShadowExecutor<E, I, S, SOT>, EM, S, Z>
for ShadowTracingStage<E, EM, I, SOT, S, Z>
where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
SOT: ObserversTuple<I, S>,
S: HasExecutions
+ HasCorpus<I>
+ HasNamedMetadata
+ Debug
+ HasCurrentTestcase<I>
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor,
{
#[inline]
fn perform(
&mut self,
fuzzer: &mut Z,
executor: &mut ShadowExecutor<E, I, S, SOT>,
state: &mut S,
manager: &mut EM,
) -> Result<(), Error> {
start_timer!(state);
let input = state.current_input_cloned()?;
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
start_timer!(state);
executor
.shadow_observers_mut()
.pre_exec_all(state, &input)?;
executor.observers_mut().pre_exec_all(state, &input)?;
mark_feature_time!(state, PerfFeature::PreExecObservers);
start_timer!(state);
let exit_kind = executor.run_target(fuzzer, state, manager, &input)?;
mark_feature_time!(state, PerfFeature::TargetExecution);
start_timer!(state);
executor
.shadow_observers_mut()
.post_exec_all(state, &input, &exit_kind)?;
executor
.observers_mut()
.post_exec_all(state, &input, &exit_kind)?;
mark_feature_time!(state, PerfFeature::PostExecObservers);
Ok(())
}
}
impl<E, EM, I, SOT, S, Z> Restartable<S> for ShadowTracingStage<E, EM, I, SOT, S, Z>
where
S: HasNamedMetadata + HasCurrentCorpusId,
{
fn should_restart(&mut self, state: &mut S) -> Result<bool, Error> {
RetryCountRestartHelper::no_retry(state, &self.name)
}
fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> {
RetryCountRestartHelper::clear_progress(state, &self.name)
}
}
impl<E, EM, I, SOT, S, Z> ShadowTracingStage<E, EM, I, SOT, S, Z>
where
E: Executor<EM, I, S, Z> + HasObservers,
S: HasExecutions + HasCorpus<I>,
SOT: ObserversTuple<I, S>,
{
/// Creates a new default stage
pub fn new(_executor: &mut ShadowExecutor<E, I, S, SOT>) -> Self {
// unsafe but impossible that you create two threads both instantiating this instance
let stage_id = unsafe {
let ret = SHADOW_TRACING_STAGE_ID;
SHADOW_TRACING_STAGE_ID += 1;
ret
};
Self {
name: Cow::Owned(
SHADOW_TRACING_STAGE_NAME.to_owned() + ":" + stage_id.to_string().as_str(),
),
phantom: PhantomData,
}
}
}

View File

@ -148,7 +148,7 @@ macro_rules! fuzz_with {
}; };
use libafl::{ use libafl::{
corpus::Corpus, corpus::Corpus,
executors::{ExitKind, InProcessExecutor}, executors::{ExitKind, InProcessExecutor, ShadowExecutor},
feedback_and_fast, feedback_not, feedback_or, feedback_or_fast, feedback_and_fast, feedback_not, feedback_or, feedback_or_fast,
feedbacks::{ConstFeedback, CrashFeedback, MaxMapFeedback, NewHashFeedback, TimeFeedback, TimeoutFeedback}, feedbacks::{ConstFeedback, CrashFeedback, MaxMapFeedback, NewHashFeedback, TimeFeedback, TimeoutFeedback},
generators::RandBytesGenerator, generators::RandBytesGenerator,
@ -166,7 +166,7 @@ macro_rules! fuzz_with {
}, },
stages::{ stages::{
CalibrationStage, GeneralizationStage, IfStage, StdMutationalStage, CalibrationStage, GeneralizationStage, IfStage, StdMutationalStage,
StdPowerMutationalStage, UnicodeIdentificationStage, TracingStage, StdPowerMutationalStage, UnicodeIdentificationStage, ShadowTracingStage,
}, },
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
StdFuzzer, StdFuzzer,
@ -438,8 +438,6 @@ macro_rules! fuzz_with {
} }
}; };
let mut tracing_harness = harness;
let add_extra_observer = $extra_obsv; let add_extra_observer = $extra_obsv;
let observers = add_extra_observer( let observers = add_extra_observer(
tuple_list!(edges_observer, size_edges_observer, time_observer, backtrace_observer, oom_observer), tuple_list!(edges_observer, size_edges_observer, time_observer, backtrace_observer, oom_observer),
@ -488,14 +486,9 @@ macro_rules! fuzz_with {
} }
} }
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = IfStage::new(|_, _, _, _| Ok(!$options.skip_tracing()), (TracingStage::new(InProcessExecutor::new( let tracing = IfStage::new(|_, _, _, _| Ok(!$options.skip_tracing()), (ShadowTracingStage::new(), ()));
&mut tracing_harness,
tuple_list!(cmplog_observer),
&mut fuzzer,
&mut state,
&mut mgr,
)?), ()));
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!( let mut stages = tuple_list!(

View File

@ -261,7 +261,7 @@ where
} }
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(

View File

@ -299,7 +299,7 @@ where
} }
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = ShadowTracingStage::new(&mut executor); let tracing = ShadowTracingStage::new();
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(