Merge branch 'main' into cmplog_instrumentation
This commit is contained in:
commit
f1c646dd1c
@ -10,7 +10,7 @@ use libafl::{
|
|||||||
QueueCorpusScheduler,
|
QueueCorpusScheduler,
|
||||||
},
|
},
|
||||||
events::setup_restarting_mgr_std,
|
events::setup_restarting_mgr_std,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
@ -18,7 +18,7 @@ use libafl::{
|
|||||||
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
||||||
mutators::token_mutations::I2SRandReplace,
|
mutators::token_mutations::I2SRandReplace,
|
||||||
observers::{StdMapObserver, TimeObserver},
|
observers::{StdMapObserver, TimeObserver},
|
||||||
stages::{StdMutationalStage, TracingStage},
|
stages::{ShadowTracingStage, StdMutationalStage},
|
||||||
state::{HasCorpus, StdState},
|
state::{HasCorpus, StdState},
|
||||||
stats::MultiStats,
|
stats::MultiStats,
|
||||||
Error,
|
Error,
|
||||||
@ -123,13 +123,16 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create the executor for an in-process function with just one observer for edge coverage
|
// Create the executor for an in-process function with just one observer for edge coverage
|
||||||
let mut executor = InProcessExecutor::new(
|
let mut executor = ShadowExecutor::new(
|
||||||
|
InProcessExecutor::new(
|
||||||
&mut harness,
|
&mut harness,
|
||||||
tuple_list!(edges_observer, time_observer),
|
tuple_list!(edges_observer, time_observer),
|
||||||
&mut fuzzer,
|
&mut fuzzer,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut restarting_mgr,
|
&mut restarting_mgr,
|
||||||
)?;
|
)?,
|
||||||
|
tuple_list!(cmplog_observer),
|
||||||
|
);
|
||||||
|
|
||||||
// The actual target run starts here.
|
// The actual target run starts here.
|
||||||
// Call LLVMFUzzerInitialize() if present.
|
// Call LLVMFUzzerInitialize() if present.
|
||||||
@ -151,22 +154,8 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
println!("We imported {} inputs from disk.", state.corpus().count());
|
println!("We imported {} inputs from disk.", state.corpus().count());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Secondary harness due to mut ownership
|
|
||||||
let mut harness = |input: &BytesInput| {
|
|
||||||
let target = input.target_bytes();
|
|
||||||
let buf = target.as_slice();
|
|
||||||
libfuzzer_test_one_input(buf);
|
|
||||||
ExitKind::Ok
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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 executor);
|
||||||
&mut harness,
|
|
||||||
tuple_list!(cmplog_observer),
|
|
||||||
&mut fuzzer,
|
|
||||||
&mut state,
|
|
||||||
&mut restarting_mgr,
|
|
||||||
)?);
|
|
||||||
|
|
||||||
// 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())));
|
||||||
|
@ -15,7 +15,12 @@ pub struct CombinedExecutor<A, B> {
|
|||||||
|
|
||||||
impl<A, B> CombinedExecutor<A, B> {
|
impl<A, B> CombinedExecutor<A, B> {
|
||||||
/// Create a new `CombinedExecutor`, wrapping the given `executor`s.
|
/// Create a new `CombinedExecutor`, wrapping the given `executor`s.
|
||||||
pub fn new<EM, I, S, Z>(primary: A, secondary: B) -> Self {
|
pub fn new<EM, I, S, Z>(primary: A, secondary: B) -> Self
|
||||||
|
where
|
||||||
|
A: Executor<EM, I, S, Z>,
|
||||||
|
B: Executor<EM, I, S, Z>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
Self { primary, secondary }
|
Self { primary, secondary }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,9 @@ pub use forkserver::{Forkserver, ForkserverExecutor, OutFile, TimeoutForkserverE
|
|||||||
pub mod combined;
|
pub mod combined;
|
||||||
pub use combined::CombinedExecutor;
|
pub use combined::CombinedExecutor;
|
||||||
|
|
||||||
|
pub mod shadow;
|
||||||
|
pub use shadow::{HasShadowObserverHooks, ShadowExecutor};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::serdeany::SerdeAny,
|
bolts::serdeany::SerdeAny,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
|
186
libafl/src/executors/shadow.rs
Normal file
186
libafl/src/executors/shadow.rs
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
//! A `ShadowExecutor` wraps an executor to have shadow observer that will not be considered by the feedbacks and the manager
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
||||||
|
inputs::Input,
|
||||||
|
observers::ObserversTuple,
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait HasShadowObserverHooks<EM, I, S, SOT, Z> {
|
||||||
|
/// Run the pre exec hook for all the shadow [`crate::observers::Observer`]`s`
|
||||||
|
fn pre_exec_shadow_observers(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Run the post exec hook for all the shadow [`crate::observers::Observer`]`s`
|
||||||
|
fn post_exec_shadow_observers(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A [`ShadowExecutor`] wraps an executor and a set of shadow observers
|
||||||
|
pub struct ShadowExecutor<E, SOT> {
|
||||||
|
executor: E,
|
||||||
|
shadow_observers: SOT,
|
||||||
|
// Enable the execution of the shadow observers hooks with the regular observers hooks
|
||||||
|
shadow_hooks: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, SOT> ShadowExecutor<E, SOT>
|
||||||
|
where
|
||||||
|
SOT: ObserversTuple,
|
||||||
|
{
|
||||||
|
/// Create a new `ShadowExecutor`, wrapping the given `executor`.
|
||||||
|
pub fn new(executor: E, shadow_observers: SOT) -> Self {
|
||||||
|
Self {
|
||||||
|
executor,
|
||||||
|
shadow_observers,
|
||||||
|
shadow_hooks: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new `ShadowExecutor`, wrapping the given `executor`.
|
||||||
|
pub fn with_shadow_hooks<EM, I, S, Z>(
|
||||||
|
executor: E,
|
||||||
|
shadow_observers: SOT,
|
||||||
|
shadow_hooks: bool,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
executor,
|
||||||
|
shadow_observers,
|
||||||
|
shadow_hooks,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn shadow_observers(&self) -> &SOT {
|
||||||
|
&self.shadow_observers
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn shadow_observers_mut(&mut self) -> &mut SOT {
|
||||||
|
&mut self.shadow_observers
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shadow_hooks(&self) -> &bool {
|
||||||
|
&self.shadow_hooks
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shadow_hooks_mut(&mut self) -> &mut bool {
|
||||||
|
&mut self.shadow_hooks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, EM, I, S, SOT, Z> HasShadowObserverHooks<EM, I, S, SOT, Z> for ShadowExecutor<E, SOT>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
SOT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec_shadow_observers(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.shadow_observers
|
||||||
|
.pre_exec_all(fuzzer, state, mgr, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn post_exec_shadow_observers(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.shadow_observers
|
||||||
|
.post_exec_all(fuzzer, state, mgr, input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, EM, I, S, SOT, Z> Executor<EM, I, S, Z> for ShadowExecutor<E, SOT>
|
||||||
|
where
|
||||||
|
E: Executor<EM, I, S, Z>,
|
||||||
|
I: Input,
|
||||||
|
SOT: ObserversTuple,
|
||||||
|
{
|
||||||
|
fn run_target(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
) -> Result<ExitKind, Error> {
|
||||||
|
self.executor.run_target(fuzzer, state, mgr, input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, OT, SOT> HasObservers<OT> for ShadowExecutor<E, SOT>
|
||||||
|
where
|
||||||
|
E: HasObservers<OT>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
SOT: ObserversTuple,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn observers(&self) -> &OT {
|
||||||
|
self.executor.observers()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn observers_mut(&mut self) -> &mut OT {
|
||||||
|
self.executor.observers_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, EM, I, OT, S, SOT, Z> HasObserversHooks<EM, I, OT, S, Z> for ShadowExecutor<E, SOT>
|
||||||
|
where
|
||||||
|
E: HasObservers<OT>,
|
||||||
|
I: Input,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
|
SOT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
|
{
|
||||||
|
/// Run the pre exec hook for all [`crate::observers::Observer`]`s` linked to this [`Executor`].
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec_observers(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
if self.shadow_hooks {
|
||||||
|
self.shadow_observers
|
||||||
|
.pre_exec_all(fuzzer, state, mgr, input)?;
|
||||||
|
}
|
||||||
|
self.observers_mut().pre_exec_all(fuzzer, state, mgr, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the post exec hook for all the [`crate::observers::Observer`]`s` linked to this [`Executor`].
|
||||||
|
#[inline]
|
||||||
|
fn post_exec_observers(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
if self.shadow_hooks {
|
||||||
|
self.shadow_observers
|
||||||
|
.post_exec_all(fuzzer, state, mgr, input)?;
|
||||||
|
}
|
||||||
|
self.observers_mut()
|
||||||
|
.post_exec_all(fuzzer, state, mgr, input)
|
||||||
|
}
|
||||||
|
}
|
@ -106,6 +106,18 @@ pub trait Evaluator<E, EM, I, S> {
|
|||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: I,
|
input: I,
|
||||||
) -> Result<(bool, Option<usize>), Error>;
|
) -> Result<(bool, Option<usize>), Error>;
|
||||||
|
|
||||||
|
/// Runs the input and triggers observers and feedback.
|
||||||
|
/// Adds an input, to the corpus even if it's not considered `interesting` by the `feedback`.
|
||||||
|
/// Returns the `index` of the new testcase in the corpus.
|
||||||
|
/// Usually, you want to use [`Evaluator::evaluate_input`], unless you know what you are doing.
|
||||||
|
fn add_input(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: I,
|
||||||
|
) -> Result<usize, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The main fuzzer trait.
|
/// The main fuzzer trait.
|
||||||
@ -391,6 +403,42 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds an input, even if it's not conisered `interesting` by any of the executors
|
||||||
|
fn add_input(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: I,
|
||||||
|
) -> Result<usize, Error> {
|
||||||
|
let _ = self.execute_input(state, executor, manager, &input)?;
|
||||||
|
let observers = executor.observers();
|
||||||
|
// Always consider this to be "interesting"
|
||||||
|
|
||||||
|
// Not a solution
|
||||||
|
self.objective_mut().discard_metadata(state, &input)?;
|
||||||
|
|
||||||
|
// Add the input to the main corpus
|
||||||
|
let mut testcase = Testcase::new(input.clone());
|
||||||
|
self.feedback_mut().append_metadata(state, &mut testcase)?;
|
||||||
|
let idx = state.corpus_mut().add(testcase)?;
|
||||||
|
self.scheduler_mut().on_add(state, idx)?;
|
||||||
|
|
||||||
|
let observers_buf = manager.serialize_observers(observers)?;
|
||||||
|
manager.fire(
|
||||||
|
state,
|
||||||
|
Event::NewTestcase {
|
||||||
|
input,
|
||||||
|
observers_buf,
|
||||||
|
corpus_size: state.corpus().count(),
|
||||||
|
client_config: "TODO".into(),
|
||||||
|
time: current_time(),
|
||||||
|
executions: *state.executions(),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
Ok(idx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, CS, E, EM, F, I, OF, OT, S, ST, SC> Fuzzer<E, EM, I, S, ST>
|
impl<C, CS, E, EM, F, I, OF, OT, S, ST, SC> Fuzzer<E, EM, I, S, ST>
|
||||||
|
@ -9,7 +9,7 @@ pub mod mutational;
|
|||||||
pub use mutational::{MutationalStage, StdMutationalStage};
|
pub use mutational::{MutationalStage, StdMutationalStage};
|
||||||
|
|
||||||
pub mod tracing;
|
pub mod tracing;
|
||||||
pub use tracing::TracingStage;
|
pub use tracing::{ShadowTracingStage, TracingStage};
|
||||||
|
|
||||||
//pub mod power;
|
//pub mod power;
|
||||||
//pub use power::PowerMutationalStage;
|
//pub use power::PowerMutationalStage;
|
||||||
|
@ -2,7 +2,7 @@ use core::{marker::PhantomData, mem::drop};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::Corpus,
|
corpus::Corpus,
|
||||||
executors::{Executor, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
executors::{Executor, HasExecHooksTuple, HasObservers, HasObserversHooks, ShadowExecutor},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
mark_feature_time,
|
mark_feature_time,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
@ -15,7 +15,7 @@ use crate::{
|
|||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
use crate::stats::PerfFeature;
|
use crate::stats::PerfFeature;
|
||||||
|
|
||||||
/// The default mutational stage
|
/// A stage that runs a tracer executor
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct TracingStage<C, EM, I, OT, S, TE, Z>
|
pub struct TracingStage<C, EM, I, OT, S, TE, Z>
|
||||||
where
|
where
|
||||||
@ -87,7 +87,7 @@ where
|
|||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
/// Creates a new default mutational stage
|
/// Creates a new default stage
|
||||||
pub fn new(tracer_executor: TE) -> Self {
|
pub fn new(tracer_executor: TE) -> Self {
|
||||||
Self {
|
Self {
|
||||||
tracer_executor,
|
tracer_executor,
|
||||||
@ -95,3 +95,78 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A stage that runs the shadow executor using also the shadow observers
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ShadowTracingStage<C, E, EM, I, OT, S, SOT, Z> {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
phantom: PhantomData<(C, E, EM, I, OT, S, SOT, Z)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, E, EM, I, OT, S, SOT, Z> Stage<ShadowExecutor<E, SOT>, EM, S, Z>
|
||||||
|
for ShadowTracingStage<C, E, EM, I, OT, S, SOT, Z>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
C: Corpus<I>,
|
||||||
|
E: Executor<EM, I, S, Z> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Z>,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
|
SOT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
|
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn perform(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
executor: &mut ShadowExecutor<E, SOT>,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
corpus_idx: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
start_timer!(state);
|
||||||
|
let input = state
|
||||||
|
.corpus()
|
||||||
|
.get(corpus_idx)?
|
||||||
|
.borrow_mut()
|
||||||
|
.load_input()?
|
||||||
|
.clone();
|
||||||
|
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
|
||||||
|
|
||||||
|
let prev_shadow_hooks = *executor.shadow_hooks();
|
||||||
|
*executor.shadow_hooks_mut() = true;
|
||||||
|
|
||||||
|
start_timer!(state);
|
||||||
|
executor.pre_exec_observers(fuzzer, state, manager, &input)?;
|
||||||
|
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
||||||
|
|
||||||
|
start_timer!(state);
|
||||||
|
drop(executor.run_target(fuzzer, state, manager, &input)?);
|
||||||
|
mark_feature_time!(state, PerfFeature::TargetExecution);
|
||||||
|
|
||||||
|
*state.executions_mut() += 1;
|
||||||
|
|
||||||
|
start_timer!(state);
|
||||||
|
executor.post_exec_observers(fuzzer, state, manager, &input)?;
|
||||||
|
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
||||||
|
|
||||||
|
*executor.shadow_hooks_mut() = prev_shadow_hooks;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, E, EM, I, OT, S, SOT, Z> ShadowTracingStage<C, E, EM, I, OT, S, SOT, Z>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
C: Corpus<I>,
|
||||||
|
E: Executor<EM, I, S, Z> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Z>,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
|
SOT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
|
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
||||||
|
{
|
||||||
|
/// Creates a new default stage
|
||||||
|
pub fn new(_executor: &mut ShadowExecutor<E, SOT>) -> Self {
|
||||||
|
Self {
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -355,12 +355,15 @@ where
|
|||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
/// loads inputs from a directory
|
/// loads inputs from a directory
|
||||||
|
/// If `forced` is `true`, the value will be loaded,
|
||||||
|
/// even if it's not considered to be `interesting`.
|
||||||
fn load_from_directory<E, EM, Z>(
|
fn load_from_directory<E, EM, Z>(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
in_dir: &Path,
|
in_dir: &Path,
|
||||||
|
forced: bool,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Z: Evaluator<E, EM, I, Self>,
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
@ -379,18 +382,69 @@ where
|
|||||||
if attr.is_file() && attr.len() > 0 {
|
if attr.is_file() && attr.len() > 0 {
|
||||||
println!("Loading file {:?} ...", &path);
|
println!("Loading file {:?} ...", &path);
|
||||||
let input = I::from_file(&path)?;
|
let input = I::from_file(&path)?;
|
||||||
let (is_interesting, _) = fuzzer.evaluate_input(self, executor, manager, input)?;
|
if forced {
|
||||||
|
let _ = fuzzer.add_input(self, executor, manager, input)?;
|
||||||
|
} else {
|
||||||
|
let (is_interesting, _) =
|
||||||
|
fuzzer.evaluate_input(self, executor, manager, input)?;
|
||||||
if !is_interesting {
|
if !is_interesting {
|
||||||
println!("File {:?} was not interesting, skipped.", &path);
|
println!("File {:?} was not interesting, skipped.", &path);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if attr.is_dir() {
|
} else if attr.is_dir() {
|
||||||
self.load_from_directory(fuzzer, executor, manager, &path)?;
|
self.load_from_directory(fuzzer, executor, manager, &path, forced)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loads initial inputs from the passed-in `in_dirs`.
|
||||||
|
/// If `forced` is true, will add all testcases, no matter what.
|
||||||
|
fn load_initial_inputs_internal<E, EM, Z>(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
in_dirs: &[PathBuf],
|
||||||
|
forced: bool,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
|
EM: EventManager<E, I, Self, Z>,
|
||||||
|
{
|
||||||
|
for in_dir in in_dirs {
|
||||||
|
self.load_from_directory(fuzzer, executor, manager, in_dir, forced)?;
|
||||||
|
}
|
||||||
|
manager.fire(
|
||||||
|
self,
|
||||||
|
Event::Log {
|
||||||
|
severity_level: LogSeverity::Debug,
|
||||||
|
message: format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
|
||||||
|
phantom: PhantomData,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
manager.process(fuzzer, self, executor)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads all intial inputs, even if they are not consiered `intesting`.
|
||||||
|
/// This is rarely the right method, use `load_initial_inputs`,
|
||||||
|
/// and potentially fix your `Feedback`, instead.
|
||||||
|
pub fn load_initial_inputs_forced<E, EM, Z>(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
in_dirs: &[PathBuf],
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
|
EM: EventManager<E, I, Self, Z>,
|
||||||
|
{
|
||||||
|
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, true)
|
||||||
|
}
|
||||||
|
|
||||||
/// Loads initial inputs from the passed-in `in_dirs`.
|
/// Loads initial inputs from the passed-in `in_dirs`.
|
||||||
pub fn load_initial_inputs<E, EM, Z>(
|
pub fn load_initial_inputs<E, EM, Z>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -403,19 +457,7 @@ where
|
|||||||
Z: Evaluator<E, EM, I, Self>,
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
EM: EventManager<E, I, Self, Z>,
|
EM: EventManager<E, I, Self, Z>,
|
||||||
{
|
{
|
||||||
for in_dir in in_dirs {
|
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, false)
|
||||||
self.load_from_directory(fuzzer, executor, manager, in_dir)?;
|
|
||||||
}
|
|
||||||
manager.fire(
|
|
||||||
self,
|
|
||||||
Event::Log {
|
|
||||||
severity_level: LogSeverity::Debug,
|
|
||||||
message: format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
|
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
manager.process(fuzzer, self, executor)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +109,6 @@ impl FridaOptions {
|
|||||||
}
|
}
|
||||||
"cmplog" => {
|
"cmplog" => {
|
||||||
options.enable_cmplog = value.parse().unwrap();
|
options.enable_cmplog = value.parse().unwrap();
|
||||||
|
|
||||||
#[cfg(not(target_arch = "aarch64"))]
|
#[cfg(not(target_arch = "aarch64"))]
|
||||||
if options.enable_cmplog {
|
if options.enable_cmplog {
|
||||||
panic!(
|
panic!(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user