No Uses* from executor (#2766)
* first step * wip * lol * making progress, slowly * add * a bit more * progress * 80%done * 90% done * done from linux * Hello from windows * 1 * 2 * 3 * 4 * 5 * 6 * 7 * Hello from windows * 9 * 10 * 11 * 11 * 12 * 13 * aa * fixer * a * oops --------- Co-authored-by: Your Name <you@example.com>
This commit is contained in:
parent
ca647f0c30
commit
aa0391ef8d
@ -7,19 +7,19 @@ use libafl::monitors::tui::TuiMonitor;
|
||||
#[cfg(not(feature = "tui"))]
|
||||
use libafl::monitors::SimpleMonitor;
|
||||
use libafl::{
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
executors::{Executor, ExitKind, WithObservers},
|
||||
feedback_and_fast,
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::HasTargetBytes,
|
||||
inputs::{HasTargetBytes, UsesInput},
|
||||
mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator},
|
||||
observers::StdMapObserver,
|
||||
schedulers::QueueScheduler,
|
||||
stages::mutational::StdMutationalStage,
|
||||
state::{HasExecutions, State, StdState, UsesState},
|
||||
state::{HasCorpus, HasExecutions, StdState, UsesState},
|
||||
};
|
||||
use libafl_bolts::{current_nanos, nonzero, rands::StdRand, tuples::tuple_list, AsSlice};
|
||||
|
||||
@ -35,11 +35,11 @@ fn signals_set(idx: usize) {
|
||||
unsafe { write(SIGNALS_PTR.add(idx), 1) };
|
||||
}
|
||||
|
||||
struct CustomExecutor<S: State> {
|
||||
struct CustomExecutor<S> {
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S: State> CustomExecutor<S> {
|
||||
impl<S> CustomExecutor<S> {
|
||||
pub fn new(_state: &S) -> Self {
|
||||
Self {
|
||||
phantom: PhantomData,
|
||||
@ -47,22 +47,18 @@ impl<S: State> CustomExecutor<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State> UsesState for CustomExecutor<S> {
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<EM, S, Z> Executor<EM, Z> for CustomExecutor<S>
|
||||
impl<EM, S, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z> for CustomExecutor<S>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
S: State + HasExecutions,
|
||||
Self::Input: HasTargetBytes,
|
||||
S: HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: HasTargetBytes,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, libafl::Error> {
|
||||
// We need to keep track of the exec count.
|
||||
*state.executions_mut() += 1;
|
||||
|
@ -22,7 +22,7 @@ debug = true
|
||||
[build-dependencies]
|
||||
anyhow = "1.0.89"
|
||||
bindgen = "0.70.1"
|
||||
cc = "1.1.21"
|
||||
cc = "=1.2.7" # fix me later
|
||||
|
||||
[dependencies]
|
||||
libafl = { path = "../../../libafl", features = ["tui_monitor"] }
|
||||
|
@ -12,6 +12,7 @@ use libafl::{
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::BytesInput,
|
||||
monitors::SimpleMonitor,
|
||||
mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator},
|
||||
observers::StdMapObserver,
|
||||
@ -131,7 +132,11 @@ pub fn main() {
|
||||
.timeout(Duration::from_secs(2))
|
||||
.build();
|
||||
let mut executor =
|
||||
command_configurator.into_executor_with_hooks(tuple_list!(observer), tuple_list!(hook));
|
||||
<PTraceCommandConfigurator as CommandConfigurator<BytesInput, _>>::into_executor_with_hooks(
|
||||
command_configurator,
|
||||
tuple_list!(observer),
|
||||
tuple_list!(hook),
|
||||
);
|
||||
|
||||
// Generator of printable bytearrays of max size 32
|
||||
let mut generator = RandPrintablesGenerator::new(NonZero::new(32).unwrap());
|
||||
|
@ -323,7 +323,6 @@ impl<M: Monitor> Instance<'_, M> {
|
||||
where
|
||||
Z: Fuzzer<E, ClientMgr<M>, ClientState, ST>
|
||||
+ Evaluator<E, ClientMgr<M>, BytesInput, ClientState>,
|
||||
E: UsesState<State = ClientState>,
|
||||
ST: StagesTuple<E, ClientMgr<M>, ClientState, Z>,
|
||||
{
|
||||
let corpus_dirs = [self.options.input_dir()];
|
||||
|
@ -6,9 +6,10 @@ use std::{
|
||||
};
|
||||
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, ExitKind, HasObservers, HasTimeout},
|
||||
observers::ObserversTuple,
|
||||
state::{State, UsesState},
|
||||
inputs::UsesInput,
|
||||
state::{HasCorpus, UsesState},
|
||||
Error,
|
||||
};
|
||||
use libafl_bolts::tuples::RefIndexable;
|
||||
@ -259,28 +260,20 @@ pub enum SupportedExecutors<S, OT, FSV, NYX> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "nyx")]
|
||||
impl<S, OT, FSV, NYX> UsesState for SupportedExecutors<S, OT, FSV, NYX>
|
||||
impl<S, OT, FSV, NYX, EM, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for SupportedExecutors<S, OT, FSV, NYX>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
#[cfg(feature = "nyx")]
|
||||
impl<S, OT, FSV, NYX, EM, Z> Executor<EM, Z> for SupportedExecutors<S, OT, FSV, NYX>
|
||||
where
|
||||
S: State,
|
||||
Z: UsesState<State = S>,
|
||||
S: HasCorpus + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
EM: UsesState<State = S>,
|
||||
FSV: Executor<EM, Z, State = S>,
|
||||
NYX: Executor<EM, Z, State = S>,
|
||||
NYX: Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
FSV: Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &S::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
match self {
|
||||
Self::Forkserver(fsrv, _) => fsrv.run_target(fuzzer, state, mgr, input),
|
||||
@ -293,10 +286,8 @@ where
|
||||
#[cfg(feature = "nyx")]
|
||||
impl<S, OT, FSV, NYX> HasObservers for SupportedExecutors<S, OT, FSV, NYX>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
FSV: HasObservers<Observers = OT>,
|
||||
NYX: HasObservers<Observers = OT>,
|
||||
FSV: HasObservers<Observers = OT>,
|
||||
{
|
||||
type Observers = OT;
|
||||
#[inline]
|
||||
@ -340,25 +331,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nyx"))]
|
||||
impl<S, OT, FSV> UsesState for SupportedExecutors<S, OT, FSV>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nyx"))]
|
||||
pub enum SupportedExecutors<S, OT, FSV> {
|
||||
Forkserver(FSV, PhantomData<(S, OT)>),
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nyx"))]
|
||||
impl<S, OT, FSV, EM, Z> Executor<EM, Z> for SupportedExecutors<S, OT, FSV>
|
||||
impl<S, OT, FSV, EM, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for SupportedExecutors<S, OT, FSV>
|
||||
where
|
||||
S: State,
|
||||
S: HasCorpus + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
EM: UsesState<State = S>,
|
||||
FSV: Executor<EM, Z, State = S>,
|
||||
FSV: Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
@ -376,8 +360,6 @@ where
|
||||
#[cfg(not(feature = "nyx"))]
|
||||
impl<S, OT, FSV> HasObservers for SupportedExecutors<S, OT, FSV>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
FSV: HasObservers<Observers = OT>,
|
||||
{
|
||||
type Observers = OT;
|
||||
|
@ -17,10 +17,11 @@ use crate::{
|
||||
corpus::Corpus,
|
||||
events::{Event, EventFirer, LogSeverity},
|
||||
executors::{Executor, HasObservers},
|
||||
inputs::{Input, UsesInput},
|
||||
monitors::{AggregatorOps, UserStats, UserStatsValue},
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
|
||||
state::{HasCorpus, HasExecutions, UsesState},
|
||||
state::{HasCorpus, HasExecutions},
|
||||
Error, HasMetadata, HasScheduler,
|
||||
};
|
||||
|
||||
@ -28,19 +29,17 @@ use crate::{
|
||||
///
|
||||
/// Algorithm based on WMOPT: <https://hexhive.epfl.ch/publications/files/21ISSTA2.pdf>
|
||||
#[derive(Debug)]
|
||||
pub struct MapCorpusMinimizer<C, E, O, T, TS> {
|
||||
pub struct MapCorpusMinimizer<C, E, O, S, T, TS> {
|
||||
observer_handle: Handle<C>,
|
||||
phantom: PhantomData<(E, O, T, TS)>,
|
||||
phantom: PhantomData<(E, O, S, T, TS)>,
|
||||
}
|
||||
|
||||
/// Standard corpus minimizer, which weights inputs by length and time.
|
||||
pub type StdCorpusMinimizer<C, E, O, T> = MapCorpusMinimizer<C, E, O, T, LenTimeMulTestcaseScore>;
|
||||
pub type StdCorpusMinimizer<C, E, O, S, T> =
|
||||
MapCorpusMinimizer<C, E, O, S, T, LenTimeMulTestcaseScore>;
|
||||
|
||||
impl<C, E, O, T, TS> MapCorpusMinimizer<C, E, O, T, TS>
|
||||
impl<C, E, O, S, T, TS> MapCorpusMinimizer<C, E, O, S, T, TS>
|
||||
where
|
||||
E: UsesState,
|
||||
E::State: HasCorpus + HasMetadata,
|
||||
TS: TestcaseScore<E::State>,
|
||||
C: Named,
|
||||
{
|
||||
/// Constructs a new `MapCorpusMinimizer` from a provided observer. This observer will be used
|
||||
@ -53,15 +52,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, E, O, T, TS> MapCorpusMinimizer<C, E, O, T, TS>
|
||||
impl<C, E, O, S, T, TS> MapCorpusMinimizer<C, E, O, S, T, TS>
|
||||
where
|
||||
E: UsesState,
|
||||
for<'a> O: MapObserver<Entry = T> + AsIter<'a, Item = T>,
|
||||
C: AsRef<O>,
|
||||
E::State: HasMetadata + HasCorpus + HasExecutions,
|
||||
<<E as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>,
|
||||
S: HasMetadata + HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input,
|
||||
T: Copy + Hash + Eq,
|
||||
TS: TestcaseScore<E::State>,
|
||||
TS: TestcaseScore<S>,
|
||||
{
|
||||
/// Do the minimization
|
||||
#[expect(clippy::too_many_lines)]
|
||||
@ -70,14 +68,15 @@ where
|
||||
fuzzer: &mut Z,
|
||||
executor: &mut E,
|
||||
manager: &mut EM,
|
||||
state: &mut E::State,
|
||||
state: &mut S,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<E::Input, E::State>,
|
||||
CS: Scheduler<E::Input, E::State> + RemovableScheduler<E::Input, E::State>,
|
||||
EM: EventFirer<State = E::State>,
|
||||
Z: HasScheduler<E::Input, E::State, Scheduler = CS>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
CS: Scheduler<<S::Corpus as Corpus>::Input, S>
|
||||
+ RemovableScheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S>,
|
||||
Z: HasScheduler<<S::Corpus as Corpus>::Input, S, Scheduler = CS>,
|
||||
{
|
||||
// don't delete this else it won't work after restart
|
||||
let current = *state.corpus().current();
|
||||
|
@ -367,7 +367,7 @@ impl<E, EM, EMH, S, SP, Z> EventProcessor<E, Z> for CentralizedEventManager<EM,
|
||||
where
|
||||
EM: AdaptiveSerializer + EventProcessor<E, Z> + EventFirer<State = S> + HasEventManagerId,
|
||||
EMH: EventManagerHooksTuple<S>,
|
||||
E: HasObservers + Executor<Self, Z, State = Self::State>,
|
||||
E: HasObservers + Executor<Self, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers:
|
||||
ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State> + Serialize,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
@ -402,7 +402,7 @@ where
|
||||
|
||||
impl<E, EM, EMH, S, SP, Z> EventManager<E, Z> for CentralizedEventManager<EM, EMH, S, SP>
|
||||
where
|
||||
E: HasObservers + Executor<Self, Z, State = Self::State>,
|
||||
E: HasObservers + Executor<Self, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers:
|
||||
ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State> + Serialize,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
@ -532,7 +532,7 @@ where
|
||||
executor: &mut E,
|
||||
) -> Result<usize, Error>
|
||||
where
|
||||
E: Executor<Self, Z, State = <Self as UsesState>::State> + HasObservers,
|
||||
E: Executor<Self, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers:
|
||||
ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State> + Serialize,
|
||||
<Self as UsesState>::State: UsesInput + HasExecutions + HasMetadata,
|
||||
@ -582,7 +582,7 @@ where
|
||||
event: Event<<<Self as UsesState>::State as UsesInput>::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<Self, Z, State = <Self as UsesState>::State> + HasObservers,
|
||||
E: Executor<Self, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers:
|
||||
ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State> + Serialize,
|
||||
<Self as UsesState>::State: UsesInput + HasExecutions + HasMetadata,
|
||||
|
@ -410,7 +410,7 @@ where
|
||||
event: Event<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<Self, Z, State = S> + HasObservers,
|
||||
E: Executor<Self, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<S::Input, S> + Serialize,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
|
||||
@ -608,7 +608,7 @@ where
|
||||
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
|
||||
S::Corpus: Corpus<Input = S::Input>,
|
||||
SP: ShMemProvider,
|
||||
E: HasObservers + Executor<Self, Z, State = S>,
|
||||
E: HasObservers + Executor<Self, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: ObserversTuple<S::Input, S> + Serialize,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
|
||||
@ -666,7 +666,7 @@ where
|
||||
|
||||
impl<E, EMH, S, SP, Z> EventManager<E, Z> for LlmpEventManager<EMH, S, SP>
|
||||
where
|
||||
E: HasObservers + Executor<Self, Z, State = S>,
|
||||
E: HasObservers + Executor<Self, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: ObserversTuple<S::Input, S> + Serialize,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
EMH: EventManagerHooksTuple<S>,
|
||||
|
@ -294,7 +294,7 @@ where
|
||||
event: Event<DI>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
EM: UsesState<State = S> + EventFirer,
|
||||
S::Corpus: Corpus<Input = S::Input>,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
@ -349,7 +349,7 @@ where
|
||||
manager: &mut EM,
|
||||
) -> Result<usize, Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
EM: UsesState<State = S> + EventFirer,
|
||||
S::Corpus: Corpus<Input = S::Input>,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
|
@ -191,7 +191,7 @@ where
|
||||
|
||||
impl<E, EMH, S, SP, Z> EventProcessor<E, Z> for LlmpRestartingEventManager<EMH, S, SP>
|
||||
where
|
||||
E: HasObservers + Executor<LlmpEventManager<EMH, S, SP>, Z, State = S>,
|
||||
E: HasObservers + Executor<LlmpEventManager<EMH, S, SP>, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: ObserversTuple<S::Input, S> + Serialize,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
EMH: EventManagerHooksTuple<S>,
|
||||
@ -219,7 +219,7 @@ where
|
||||
|
||||
impl<E, EMH, S, SP, Z> EventManager<E, Z> for LlmpRestartingEventManager<EMH, S, SP>
|
||||
where
|
||||
E: HasObservers + Executor<LlmpEventManager<EMH, S, SP>, Z, State = S>,
|
||||
E: HasObservers + Executor<LlmpEventManager<EMH, S, SP>, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: ObserversTuple<S::Input, S> + Serialize,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
EMH: EventManagerHooksTuple<S>,
|
||||
|
@ -601,7 +601,7 @@ where
|
||||
event: Event<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<Self, Z, State = S> + HasObservers,
|
||||
E: Executor<Self, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: Serialize + ObserversTuple<S::Input, S>,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
|
||||
@ -740,7 +740,7 @@ where
|
||||
|
||||
impl<E, EMH, S, Z> EventProcessor<E, Z> for TcpEventManager<EMH, S>
|
||||
where
|
||||
E: HasObservers + Executor<Self, Z, State = S>,
|
||||
E: HasObservers + Executor<Self, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: Serialize + ObserversTuple<S::Input, S>,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
EMH: EventManagerHooksTuple<S>,
|
||||
@ -815,7 +815,7 @@ where
|
||||
|
||||
impl<E, EMH, S, Z> EventManager<E, Z> for TcpEventManager<EMH, S>
|
||||
where
|
||||
E: HasObservers + Executor<Self, Z, State = S>,
|
||||
E: HasObservers + Executor<Self, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: Serialize + ObserversTuple<S::Input, S>,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
EMH: EventManagerHooksTuple<S>,
|
||||
@ -956,7 +956,7 @@ where
|
||||
|
||||
impl<E, EMH, S, SP, Z> EventProcessor<E, Z> for TcpRestartingEventManager<EMH, S, SP>
|
||||
where
|
||||
E: HasObservers + Executor<TcpEventManager<EMH, S>, Z, State = S>,
|
||||
E: HasObservers + Executor<TcpEventManager<EMH, S>, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
E::Observers: ObserversTuple<S::Input, S> + Serialize,
|
||||
EMH: EventManagerHooksTuple<S>,
|
||||
@ -977,7 +977,7 @@ where
|
||||
|
||||
impl<E, EMH, S, SP, Z> EventManager<E, Z> for TcpRestartingEventManager<EMH, S, SP>
|
||||
where
|
||||
E: HasObservers + Executor<TcpEventManager<EMH, S>, Z, State = S>,
|
||||
E: HasObservers + Executor<TcpEventManager<EMH, S>, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: ObserversTuple<S::Input, S> + Serialize,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
EMH: EventManagerHooksTuple<S>,
|
||||
|
@ -8,7 +8,6 @@ use libafl_bolts::tuples::RefIndexable;
|
||||
use super::HasTimeout;
|
||||
use crate::{
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
state::{HasExecutions, UsesState},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -21,12 +20,7 @@ pub struct CombinedExecutor<A, B> {
|
||||
|
||||
impl<A, B> CombinedExecutor<A, B> {
|
||||
/// Create a new `CombinedExecutor`, wrapping the given `executor`s.
|
||||
pub fn new<EM, Z>(primary: A, secondary: B) -> Self
|
||||
where
|
||||
A: Executor<EM, Z>,
|
||||
B: Executor<EM, Z, State = <Self as UsesState>::State>,
|
||||
EM: UsesState<State = <Self as UsesState>::State>,
|
||||
{
|
||||
pub fn new(primary: A, secondary: B) -> Self {
|
||||
Self { primary, secondary }
|
||||
}
|
||||
|
||||
@ -41,19 +35,17 @@ impl<A, B> CombinedExecutor<A, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, EM, Z> Executor<EM, Z> for CombinedExecutor<A, B>
|
||||
impl<A, B, EM, I, S, Z> Executor<EM, I, S, Z> for CombinedExecutor<A, B>
|
||||
where
|
||||
A: Executor<EM, Z>,
|
||||
B: Executor<EM, Z, State = <Self as UsesState>::State>,
|
||||
Self::State: HasExecutions,
|
||||
EM: UsesState<State = <Self as UsesState>::State>,
|
||||
A: Executor<EM, I, S, Z>,
|
||||
B: Executor<EM, I, S, Z>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &I,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.primary.run_target(fuzzer, state, mgr, input)
|
||||
}
|
||||
@ -80,13 +72,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> UsesState for CombinedExecutor<A, B>
|
||||
where
|
||||
A: UsesState,
|
||||
{
|
||||
type State = A::State;
|
||||
}
|
||||
|
||||
impl<A, B> HasObservers for CombinedExecutor<A, B>
|
||||
where
|
||||
A: HasObservers,
|
||||
|
@ -46,12 +46,14 @@ use nix::{
|
||||
use typed_builder::TypedBuilder;
|
||||
|
||||
use super::HasTimeout;
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::executors::hooks::ExecutorHooksTuple;
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{hooks::ExecutorHooksTuple, Executor, ExitKind, HasObservers},
|
||||
inputs::{HasTargetBytes, Input, UsesInput},
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
inputs::HasTargetBytes,
|
||||
observers::{ObserversTuple, StdErrObserver, StdOutObserver},
|
||||
state::{HasCorpus, HasExecutions, State, UsesState},
|
||||
state::{HasCorpus, HasExecutions},
|
||||
std::borrow::ToOwned,
|
||||
Error,
|
||||
};
|
||||
@ -321,11 +323,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<OT, S, T, HT, C> CommandExecutor<OT, S, T, HT, C>
|
||||
where
|
||||
T: Debug,
|
||||
OT: Debug,
|
||||
{
|
||||
impl<OT, S, T, HT, C> CommandExecutor<OT, S, T, HT, C> {
|
||||
/// Accesses the inner value
|
||||
pub fn inner(&mut self) -> &mut T {
|
||||
&mut self.configurer
|
||||
@ -333,13 +331,17 @@ where
|
||||
}
|
||||
|
||||
// this only works on unix because of the reliance on checking the process signal for detecting OOM
|
||||
impl<I, OT, S, T> CommandExecutor<OT, S, T>
|
||||
impl<OT, S, T> CommandExecutor<OT, S, T>
|
||||
where
|
||||
S: State + HasExecutions + UsesInput<Input = I>,
|
||||
T: CommandConfigurator<I> + Debug,
|
||||
OT: Debug + ObserversTuple<I, S>,
|
||||
S: HasExecutions + HasCorpus,
|
||||
T: CommandConfigurator<<S::Corpus as Corpus>::Input> + Debug,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
fn execute_input_with_command(&mut self, state: &mut S, input: &I) -> Result<ExitKind, Error> {
|
||||
fn execute_input_with_command(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
use wait_timeout::ChildExt;
|
||||
|
||||
*state.executions_mut() += 1;
|
||||
@ -389,19 +391,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<EM, OT, S, T, Z> Executor<EM, Z> for CommandExecutor<OT, S, T>
|
||||
impl<EM, OT, S, T, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z> for CommandExecutor<OT, S, T>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
S: State + HasExecutions + UsesInput,
|
||||
T: CommandConfigurator<S::Input> + Debug,
|
||||
OT: Debug + MatchName + ObserversTuple<S::Input, S>,
|
||||
S: HasExecutions + HasCorpus,
|
||||
T: CommandConfigurator<<S::Corpus as Corpus>::Input> + Debug,
|
||||
OT: MatchName + ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.execute_input_with_command(state, input)
|
||||
}
|
||||
@ -425,13 +426,13 @@ where
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
impl<EM, OT, S, T, Z, HT> Executor<EM, Z> for CommandExecutor<OT, S, T, HT, Pid>
|
||||
impl<EM, OT, S, T, Z, HT> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for CommandExecutor<OT, S, T, HT, Pid>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
S: State + HasExecutions + UsesInput,
|
||||
T: CommandConfigurator<S::Input, Pid> + Debug,
|
||||
OT: Debug + MatchName + ObserversTuple<S::Input, S>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
S: HasCorpus + HasExecutions,
|
||||
T: CommandConfigurator<<S::Corpus as Corpus>::Input, Pid> + Debug,
|
||||
OT: MatchName + ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
/// Linux specific low level implementation, to directly handle `fork`, `exec` and use linux
|
||||
/// `ptrace`
|
||||
@ -441,9 +442,9 @@ where
|
||||
fn run_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
@ -471,7 +472,7 @@ where
|
||||
|
||||
self.observers.pre_exec_child_all(state, input)?;
|
||||
if *state.executions() == 1 {
|
||||
self.hooks.init_all::<Self>(state);
|
||||
self.hooks.init_all(state);
|
||||
}
|
||||
self.hooks.pre_exec_all(state, input);
|
||||
|
||||
@ -501,18 +502,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<OT, S, T, HT, C> UsesState for CommandExecutor<OT, S, T, HT, C>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<OT, S, T, HT, C> HasObservers for CommandExecutor<OT, S, T, HT, C>
|
||||
where
|
||||
S: State,
|
||||
T: Debug,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: HasCorpus,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
type Observers = OT;
|
||||
|
||||
@ -695,9 +688,9 @@ impl CommandExecutorBuilder {
|
||||
observers: OT,
|
||||
) -> Result<CommandExecutor<OT, S, StdCommandConfigurator>, Error>
|
||||
where
|
||||
OT: MatchName + ObserversTuple<S::Input, S>,
|
||||
S: UsesInput,
|
||||
S::Input: Input + HasTargetBytes,
|
||||
S: HasCorpus,
|
||||
<S::Corpus as Corpus>::Input: HasTargetBytes,
|
||||
OT: MatchName + ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
let Some(program) = &self.program else {
|
||||
return Err(Error::illegal_argument(
|
||||
@ -744,12 +737,9 @@ impl CommandExecutorBuilder {
|
||||
timeout: self.timeout,
|
||||
command,
|
||||
};
|
||||
Ok(
|
||||
<StdCommandConfigurator as CommandConfigurator<S::Input>>::into_executor::<OT, S>(
|
||||
configurator,
|
||||
observers,
|
||||
),
|
||||
)
|
||||
Ok(<StdCommandConfigurator as CommandConfigurator<
|
||||
<S::Corpus as Corpus>::Input,
|
||||
>>::into_executor::<OT, S>(configurator, observers))
|
||||
}
|
||||
}
|
||||
|
||||
@ -757,7 +747,7 @@ impl CommandExecutorBuilder {
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use std::{io::Write, process::{Stdio, Command, Child}, time::Duration};
|
||||
/// use libafl::{Error, inputs::{BytesInput, HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::{UsesState, HasExecutions}};
|
||||
/// use libafl::{Error, corpus::Corpus, inputs::{BytesInput, HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::{HasCorpus, UsesState, HasExecutions}};
|
||||
/// use libafl_bolts::AsSlice;
|
||||
/// #[derive(Debug)]
|
||||
/// struct MyExecutor;
|
||||
@ -787,10 +777,12 @@ impl CommandExecutorBuilder {
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn make_executor<EM, Z>() -> impl Executor<EM, Z>
|
||||
/// fn make_executor<EM, S, Z>() -> impl Executor<EM, BytesInput, S, Z>
|
||||
/// where
|
||||
/// EM: UsesState,
|
||||
/// EM::State: UsesInput<Input = BytesInput> + HasExecutions,
|
||||
/// S: HasCorpus + HasExecutions,
|
||||
/// S::Corpus: Corpus<Input = BytesInput>,
|
||||
/// {
|
||||
/// MyExecutor.into_executor(())
|
||||
/// }
|
||||
@ -826,10 +818,7 @@ pub trait CommandConfigurator<I, C = Child>: Sized {
|
||||
}
|
||||
|
||||
/// Create an `Executor` from this `CommandConfigurator`.
|
||||
fn into_executor<OT, S>(self, observers: OT) -> CommandExecutor<OT, S, Self, (), C>
|
||||
where
|
||||
OT: MatchName,
|
||||
{
|
||||
fn into_executor<OT, S>(self, observers: OT) -> CommandExecutor<OT, S, Self, (), C> {
|
||||
CommandExecutor {
|
||||
configurer: self,
|
||||
observers,
|
||||
@ -844,12 +833,7 @@ pub trait CommandConfigurator<I, C = Child>: Sized {
|
||||
self,
|
||||
observers: OT,
|
||||
hooks: HT,
|
||||
) -> CommandExecutor<OT, S, Self, HT, C>
|
||||
where
|
||||
OT: MatchName,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
S: UsesInput<Input = I>,
|
||||
{
|
||||
) -> CommandExecutor<OT, S, Self, HT, C> {
|
||||
CommandExecutor {
|
||||
configurer: self,
|
||||
observers,
|
||||
@ -885,7 +869,7 @@ mod tests {
|
||||
Executor,
|
||||
},
|
||||
fuzzer::NopFuzzer,
|
||||
inputs::BytesInput,
|
||||
inputs::{BytesInput, NopInput},
|
||||
monitors::SimpleMonitor,
|
||||
state::NopState,
|
||||
};
|
||||
@ -893,7 +877,8 @@ mod tests {
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)]
|
||||
fn test_builder() {
|
||||
let mut mgr = SimpleEventManager::new(SimpleMonitor::new(|status| {
|
||||
let mut mgr: SimpleEventManager<_, NopState<NopInput>> =
|
||||
SimpleEventManager::new(SimpleMonitor::new(|status| {
|
||||
log::info!("{status}");
|
||||
}));
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
use core::{
|
||||
cell::UnsafeCell,
|
||||
fmt::Debug,
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
ptr,
|
||||
};
|
||||
@ -20,28 +21,23 @@ use super::HasTimeout;
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
inputs::UsesInput,
|
||||
observers::{DifferentialObserversTuple, ObserversTuple},
|
||||
state::{HasCorpus, UsesState},
|
||||
state::HasCorpus,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A [`DiffExecutor`] wraps a primary executor, forwarding its methods, and a secondary one
|
||||
#[derive(Debug)]
|
||||
pub struct DiffExecutor<A, B, DOT, OTA, OTB> {
|
||||
pub struct DiffExecutor<A, B, DOT, OTA, OTB, S> {
|
||||
primary: A,
|
||||
secondary: B,
|
||||
observers: UnsafeCell<ProxyObserversTuple<OTA, OTB, DOT>>,
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<A, B, DOT, OTA, OTB> DiffExecutor<A, B, DOT, OTA, OTB> {
|
||||
impl<A, B, DOT, OTA, OTB, S> DiffExecutor<A, B, DOT, OTA, OTB, S> {
|
||||
/// Create a new `DiffExecutor`, wrapping the given `executor`s.
|
||||
pub fn new(primary: A, secondary: B, observers: DOT) -> Self
|
||||
where
|
||||
A: UsesState + HasObservers<Observers = OTA>,
|
||||
B: UsesState<State = <Self as UsesState>::State> + HasObservers<Observers = OTB>,
|
||||
DOT: DifferentialObserversTuple<OTA, OTB, A::Input, A::State>,
|
||||
{
|
||||
pub fn new(primary: A, secondary: B, observers: DOT) -> Self {
|
||||
Self {
|
||||
primary,
|
||||
secondary,
|
||||
@ -50,6 +46,7 @@ impl<A, B, DOT, OTA, OTB> DiffExecutor<A, B, DOT, OTA, OTB> {
|
||||
secondary: OwnedMutPtr::Ptr(ptr::null_mut()),
|
||||
differential: observers,
|
||||
}),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,23 +61,23 @@ impl<A, B, DOT, OTA, OTB> DiffExecutor<A, B, DOT, OTA, OTB> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, DOT, EM, Z> Executor<EM, Z> for DiffExecutor<A, B, DOT, A::Observers, B::Observers>
|
||||
impl<A, B, DOT, EM, S, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for DiffExecutor<A, B, DOT, A::Observers, B::Observers, S>
|
||||
where
|
||||
A: Executor<EM, Z> + HasObservers,
|
||||
B: Executor<EM, Z, State = <Self as UsesState>::State> + HasObservers,
|
||||
EM: UsesState<State = <Self as UsesState>::State>,
|
||||
<A as HasObservers>::Observers:
|
||||
ObserversTuple<<<A as UsesState>::State as UsesInput>::Input, <A as UsesState>::State>,
|
||||
<B as HasObservers>::Observers:
|
||||
ObserversTuple<<<A as UsesState>::State as UsesInput>::Input, <A as UsesState>::State>,
|
||||
DOT: DifferentialObserversTuple<A::Observers, B::Observers, A::Input, A::State> + MatchName,
|
||||
A: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
B: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
<A as HasObservers>::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
<B as HasObservers>::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
DOT: DifferentialObserversTuple<A::Observers, B::Observers, <S::Corpus as Corpus>::Input, S>
|
||||
+ MatchName,
|
||||
S: HasCorpus,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.observers(); // update in advance
|
||||
let observers = self.observers.get_mut();
|
||||
@ -120,7 +117,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, DOT, OTA, OTB> HasTimeout for DiffExecutor<A, B, DOT, OTA, OTB>
|
||||
impl<A, B, DOT, OTA, OTB, S> HasTimeout for DiffExecutor<A, B, DOT, OTA, OTB, S>
|
||||
where
|
||||
A: HasTimeout,
|
||||
B: HasTimeout,
|
||||
@ -154,11 +151,9 @@ pub struct ProxyObserversTuple<A, B, DOT> {
|
||||
|
||||
impl<A, B, DOT, I, S> ObserversTuple<I, S> for ProxyObserversTuple<A, B, DOT>
|
||||
where
|
||||
A: ObserversTuple<I, S>,
|
||||
B: ObserversTuple<I, S>,
|
||||
A: MatchName,
|
||||
B: MatchName,
|
||||
DOT: DifferentialObserversTuple<A, B, I, S> + MatchName,
|
||||
S: HasCorpus,
|
||||
S::Corpus: Corpus<Input = I>,
|
||||
{
|
||||
fn pre_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
||||
self.differential.pre_exec_all(state, input)
|
||||
@ -238,20 +233,14 @@ impl<A, B, DOT> ProxyObserversTuple<A, B, DOT> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, DOT, OTA, OTB> UsesState for DiffExecutor<A, B, DOT, OTA, OTB>
|
||||
impl<A, B, DOT, OTA, OTB, S> HasObservers for DiffExecutor<A, B, DOT, OTA, OTB, S>
|
||||
where
|
||||
A: UsesState,
|
||||
{
|
||||
type State = A::State;
|
||||
}
|
||||
|
||||
impl<A, B, DOT, OTA, OTB> HasObservers for DiffExecutor<A, B, DOT, OTA, OTB>
|
||||
where
|
||||
A: UsesState + HasObservers<Observers = OTA>,
|
||||
B: UsesState<State = <Self as UsesState>::State> + HasObservers<Observers = OTB>,
|
||||
DOT: DifferentialObserversTuple<OTA, OTB, A::Input, A::State> + MatchName,
|
||||
OTA: ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State>,
|
||||
OTB: ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State>,
|
||||
A: HasObservers<Observers = OTA>,
|
||||
B: HasObservers<Observers = OTB>,
|
||||
DOT: DifferentialObserversTuple<OTA, OTB, <S::Corpus as Corpus>::Input, S> + MatchName,
|
||||
OTA: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OTB: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
type Observers = ProxyObserversTuple<OTA, OTB, DOT>;
|
||||
|
||||
|
@ -43,13 +43,12 @@ use crate::observers::{
|
||||
get_asan_runtime_flags, get_asan_runtime_flags_with_log_path, AsanBacktraceObserver,
|
||||
};
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
inputs::{
|
||||
BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter, UsesInput,
|
||||
},
|
||||
inputs::{BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter},
|
||||
mutators::Tokens,
|
||||
observers::{MapObserver, Observer, ObserversTuple},
|
||||
state::{HasExecutions, State, UsesState},
|
||||
state::{HasCorpus, HasExecutions},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -662,8 +661,8 @@ impl ForkserverExecutor<(), (), (), UnixShMemProvider> {
|
||||
|
||||
impl<TC, OT, S, SP> ForkserverExecutor<TC, OT, S, SP>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: UsesInput,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
SP: ShMemProvider,
|
||||
TC: TargetBytesConverter,
|
||||
{
|
||||
@ -842,9 +841,9 @@ where
|
||||
#[expect(clippy::pedantic)]
|
||||
pub fn build<OT, S>(mut self, observers: OT) -> Result<ForkserverExecutor<TC, OT, S, SP>, Error>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: UsesInput,
|
||||
S::Input: Input,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
<S::Corpus as Corpus>::Input: Input,
|
||||
TC: TargetBytesConverter,
|
||||
SP: ShMemProvider,
|
||||
{
|
||||
@ -910,10 +909,10 @@ where
|
||||
) -> Result<ForkserverExecutor<TC, (A, OT), S, SP>, Error>
|
||||
where
|
||||
MO: MapObserver + Truncate, // TODO maybe enforce Entry = u8 for the cov map
|
||||
A: Observer<S::Input, S> + AsMut<MO>,
|
||||
OT: ObserversTuple<S::Input, S> + Prepend<MO>,
|
||||
S: UsesInput,
|
||||
S::Input: Input + HasTargetBytes,
|
||||
A: Observer<<S::Corpus as Corpus>::Input, S> + AsMut<MO>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Prepend<MO>,
|
||||
<S::Corpus as Corpus>::Input: Input + HasTargetBytes,
|
||||
S: HasCorpus,
|
||||
SP: ShMemProvider,
|
||||
{
|
||||
let (forkserver, input_file, map) = self.build_helper()?;
|
||||
@ -1580,21 +1579,21 @@ impl Default
|
||||
}
|
||||
}
|
||||
|
||||
impl<EM, TC, OT, S, SP, Z> Executor<EM, Z> for ForkserverExecutor<TC, OT, S, SP>
|
||||
impl<EM, TC, OT, S, SP, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for ForkserverExecutor<TC, OT, S, SP>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
SP: ShMemProvider,
|
||||
S: State + HasExecutions,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
EM: UsesState<State = S>,
|
||||
S: HasCorpus + HasExecutions,
|
||||
TC: TargetBytesConverter<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
#[inline]
|
||||
fn run_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.execute_input(state, input)
|
||||
}
|
||||
@ -1615,18 +1614,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<TC, OT, S, SP> UsesState for ForkserverExecutor<TC, OT, S, SP>
|
||||
where
|
||||
S: State,
|
||||
SP: ShMemProvider,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<TC, OT, S, SP> HasObservers for ForkserverExecutor<TC, OT, S, SP>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
SP: ShMemProvider,
|
||||
{
|
||||
type Observers = OT;
|
||||
@ -1654,7 +1645,9 @@ mod tests {
|
||||
use serial_test::serial;
|
||||
|
||||
use crate::{
|
||||
corpus::NopCorpus,
|
||||
executors::forkserver::{ForkserverExecutor, FAILED_TO_START_FORKSERVER_MSG},
|
||||
inputs::BytesInput,
|
||||
observers::{ConstMapObserver, HitcountsMapObserver},
|
||||
Error,
|
||||
};
|
||||
@ -1684,7 +1677,7 @@ mod tests {
|
||||
.coverage_map_size(MAP_SIZE)
|
||||
.debug_child(false)
|
||||
.shmem_provider(&mut shmem_provider)
|
||||
.build::<_, ()>(tuple_list!(edges_observer));
|
||||
.build::<_, NopCorpus<BytesInput>>(tuple_list!(edges_observer));
|
||||
|
||||
// Since /usr/bin/echo is not a instrumented binary file, the test will just check if the forkserver has failed at the initial handshake
|
||||
let result = match executor {
|
||||
|
@ -23,16 +23,15 @@ use windows::Win32::System::Threading::{CRITICAL_SECTION, PTP_TIMER};
|
||||
use crate::executors::hooks::timer::TimerStruct;
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use crate::executors::hooks::unix::unix_signal_handler;
|
||||
#[cfg(windows)]
|
||||
use crate::state::State;
|
||||
#[cfg(any(unix, windows))]
|
||||
use crate::{corpus::Corpus, observers::ObserversTuple, state::UsesState};
|
||||
use crate::observers::ObserversTuple;
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers},
|
||||
feedbacks::Feedback,
|
||||
inputs::UsesInput,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions},
|
||||
inputs::{Input, UsesInput},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
Error, HasObjective,
|
||||
};
|
||||
|
||||
@ -84,10 +83,7 @@ pub trait HasTimeout {
|
||||
fn handle_timeout(&mut self, data: &mut InProcessExecutorHandlerData) -> bool;
|
||||
}
|
||||
|
||||
impl<S> HasTimeout for InProcessHooks<S>
|
||||
where
|
||||
S: UsesInput,
|
||||
{
|
||||
impl<S> HasTimeout for InProcessHooks<S> {
|
||||
#[cfg(feature = "std")]
|
||||
fn timer(&self) -> &TimerStruct {
|
||||
&self.timer
|
||||
@ -191,14 +187,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> ExecutorHook<S> for InProcessHooks<S>
|
||||
impl<S> ExecutorHook<<S::Corpus as Corpus>::Input, S> for InProcessHooks<S>
|
||||
where
|
||||
S: UsesInput,
|
||||
S: HasCorpus,
|
||||
{
|
||||
fn init<E: HasObservers>(&mut self, _state: &mut S) {}
|
||||
fn init(&mut self, _state: &mut S) {}
|
||||
/// Call before running a target.
|
||||
#[expect(unused_variables)]
|
||||
fn pre_exec(&mut self, state: &mut S, input: &S::Input) {
|
||||
fn pre_exec(&mut self, state: &mut S, input: &<S::Corpus as Corpus>::Input) {
|
||||
#[cfg(feature = "std")]
|
||||
unsafe {
|
||||
let data = &raw mut GLOBAL_STATE;
|
||||
@ -211,7 +207,7 @@ where
|
||||
}
|
||||
|
||||
/// Call after running a target.
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &<S::Corpus as Corpus>::Input) {
|
||||
// timeout stuff
|
||||
// # Safety
|
||||
// We're calling this only once per execution, in a single thread.
|
||||
@ -220,23 +216,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> InProcessHooks<S>
|
||||
where
|
||||
S: UsesInput,
|
||||
{
|
||||
impl<S> InProcessHooks<S> {
|
||||
/// Create new [`InProcessHooks`].
|
||||
#[cfg(unix)]
|
||||
#[allow(unused_variables)] // for `exec_tmout` without `std`
|
||||
pub fn new<E, EM, OF, Z>(exec_tmout: Duration) -> Result<Self, Error>
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers + HasInProcessHooks<E::State>,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers + HasInProcessHooks<S>,
|
||||
E::Observers: ObserversTuple<<S as UsesInput>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
// # Safety
|
||||
// We get a pointer to `GLOBAL_STATE` that will be initialized at this point in time.
|
||||
@ -245,7 +242,7 @@ where
|
||||
#[cfg(all(not(miri), unix, feature = "std"))]
|
||||
let data = unsafe { &raw mut GLOBAL_STATE };
|
||||
#[cfg(feature = "std")]
|
||||
unix_signal_handler::setup_panic_hook::<E, EM, OF, Z>();
|
||||
unix_signal_handler::setup_panic_hook::<E, EM, OF, S, Z>();
|
||||
// # Safety
|
||||
// Setting up the signal handlers with a pointer to the `GLOBAL_STATE` which should not be NULL at this point.
|
||||
// We are the sole users of `GLOBAL_STATE` right now, and only dereference it in case of Segfault/Panic.
|
||||
@ -257,10 +254,10 @@ where
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
Ok(Self {
|
||||
#[cfg(feature = "std")]
|
||||
crash_handler: unix_signal_handler::inproc_crash_handler::<E, EM, OF, Z>
|
||||
crash_handler: unix_signal_handler::inproc_crash_handler::<E, EM, OF, S, Z>
|
||||
as *const c_void,
|
||||
#[cfg(feature = "std")]
|
||||
timeout_handler: unix_signal_handler::inproc_timeout_handler::<E, EM, OF, Z>
|
||||
timeout_handler: unix_signal_handler::inproc_timeout_handler::<E, EM, OF, S, Z>
|
||||
as *const _,
|
||||
#[cfg(feature = "std")]
|
||||
timer: TimerStruct::new(exec_tmout),
|
||||
@ -273,14 +270,18 @@ where
|
||||
#[allow(unused_variables)] // for `exec_tmout` without `std`
|
||||
pub fn new<E, EM, OF, Z>(exec_tmout: Duration) -> Result<Self, Error>
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers + HasInProcessHooks<E::State>,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: State + HasExecutions + HasSolutions + HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers + HasInProcessHooks<S>,
|
||||
E::Observers: ObserversTuple<<S as UsesInput>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
let ret;
|
||||
#[cfg(feature = "std")]
|
||||
@ -290,6 +291,7 @@ where
|
||||
E,
|
||||
EM,
|
||||
OF,
|
||||
S,
|
||||
Z,
|
||||
>();
|
||||
setup_exception_handler(data)?;
|
||||
@ -299,6 +301,7 @@ where
|
||||
E,
|
||||
EM,
|
||||
OF,
|
||||
S,
|
||||
Z,
|
||||
> as *const _;
|
||||
let timeout_handler =
|
||||
@ -306,6 +309,7 @@ where
|
||||
E,
|
||||
EM,
|
||||
OF,
|
||||
S,
|
||||
Z,
|
||||
> as *const c_void;
|
||||
let timer = TimerStruct::new(exec_tmout, timeout_handler);
|
||||
@ -331,10 +335,13 @@ where
|
||||
#[expect(unused_variables)]
|
||||
pub fn new<E, EM, OF, Z>(exec_tmout: Duration) -> Result<Self, Error>
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers + HasInProcessHooks<E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers + HasInProcessHooks<S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
#[cfg_attr(miri, allow(unused_variables))]
|
||||
|
@ -14,15 +14,15 @@ use libafl_bolts::os::unix_signals::{ucontext_t, Signal, SignalHandler};
|
||||
use libc::siginfo_t;
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{
|
||||
common_signals,
|
||||
hooks::ExecutorHook,
|
||||
inprocess_fork::{child_signal_handlers, ForkHandlerFuncPtr},
|
||||
HasObservers,
|
||||
},
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
state::UsesState,
|
||||
state::HasCorpus,
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -36,15 +36,15 @@ pub struct InChildProcessHooks<S> {
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S> ExecutorHook<S> for InChildProcessHooks<S>
|
||||
impl<S> ExecutorHook<<S::Corpus as Corpus>::Input, S> for InChildProcessHooks<S>
|
||||
where
|
||||
S: UsesInput,
|
||||
S: HasCorpus,
|
||||
{
|
||||
/// Init this hook
|
||||
fn init<E: HasObservers>(&mut self, _state: &mut S) {}
|
||||
fn init(&mut self, _state: &mut S) {}
|
||||
|
||||
/// Call before running a target.
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) {
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &<S::Corpus as Corpus>::Input) {
|
||||
unsafe {
|
||||
let data = &raw mut FORK_EXECUTOR_GLOBAL_DATA;
|
||||
(*data).crash_handler = self.crash_handler;
|
||||
@ -53,15 +53,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {}
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &<S::Corpus as Corpus>::Input) {}
|
||||
}
|
||||
|
||||
impl<S> InChildProcessHooks<S> {
|
||||
/// Create new [`InChildProcessHooks`].
|
||||
pub fn new<E>() -> Result<Self, Error>
|
||||
where
|
||||
E: HasObservers + UsesState,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
#[cfg_attr(miri, allow(unused_variables, unused_unsafe))]
|
||||
unsafe {
|
||||
@ -71,8 +72,16 @@ impl<S> InChildProcessHooks<S> {
|
||||
setup_signal_handler(data)?;
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
Ok(Self {
|
||||
crash_handler: child_signal_handlers::child_crash_handler::<E> as *const c_void,
|
||||
timeout_handler: child_signal_handlers::child_timeout_handler::<E> as *const c_void,
|
||||
crash_handler: child_signal_handlers::child_crash_handler::<
|
||||
E,
|
||||
<S::Corpus as Corpus>::Input,
|
||||
S,
|
||||
> as *const c_void,
|
||||
timeout_handler: child_signal_handlers::child_timeout_handler::<
|
||||
E,
|
||||
<S::Corpus as Corpus>::Input,
|
||||
S,
|
||||
> as *const c_void,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
@ -10,11 +10,7 @@ use num_traits::SaturatingAdd;
|
||||
use serde::Serialize;
|
||||
use typed_builder::TypedBuilder;
|
||||
|
||||
use crate::{
|
||||
executors::{hooks::ExecutorHook, HasObservers},
|
||||
inputs::UsesInput,
|
||||
Error,
|
||||
};
|
||||
use crate::{corpus::Corpus, executors::hooks::ExecutorHook, state::HasCorpus, Error};
|
||||
|
||||
/// Info of a binary's section that can be used during `Intel PT` traces decoding
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -40,18 +36,18 @@ pub struct IntelPTHook<T> {
|
||||
map_len: usize,
|
||||
}
|
||||
|
||||
impl<S, T> ExecutorHook<S> for IntelPTHook<T>
|
||||
impl<S, T> ExecutorHook<<S::Corpus as Corpus>::Input, S> for IntelPTHook<T>
|
||||
where
|
||||
S: UsesInput + Serialize,
|
||||
S: Serialize + HasCorpus,
|
||||
T: SaturatingAdd + From<u8> + Debug,
|
||||
{
|
||||
fn init<E: HasObservers>(&mut self, _state: &mut S) {}
|
||||
fn init(&mut self, _state: &mut S) {}
|
||||
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) {
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &<S::Corpus as Corpus>::Input) {
|
||||
self.intel_pt.enable_tracing().unwrap();
|
||||
}
|
||||
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &<S::Corpus as Corpus>::Input) {
|
||||
let pt = &mut self.intel_pt;
|
||||
pt.disable_tracing().unwrap();
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
//! Hooks for the executors.
|
||||
//! These will be executed right before and after the executor's harness run.
|
||||
|
||||
use crate::{executors::HasObservers, inputs::UsesInput};
|
||||
|
||||
/// windows crash/timeout handler and asan death callback
|
||||
#[cfg(windows)]
|
||||
pub mod windows;
|
||||
@ -27,57 +25,47 @@ pub mod timer;
|
||||
pub mod intel_pt;
|
||||
|
||||
/// The hook that runs before and after the executor runs the target
|
||||
pub trait ExecutorHook<S>
|
||||
where
|
||||
S: UsesInput,
|
||||
{
|
||||
pub trait ExecutorHook<I, S> {
|
||||
/// Init this hook
|
||||
fn init<E: HasObservers>(&mut self, state: &mut S);
|
||||
fn init(&mut self, state: &mut S);
|
||||
/// The hook that runs before runs the target
|
||||
fn pre_exec(&mut self, state: &mut S, input: &S::Input);
|
||||
fn pre_exec(&mut self, state: &mut S, input: &I);
|
||||
/// The hook that runs before runs the target
|
||||
fn post_exec(&mut self, state: &mut S, input: &S::Input);
|
||||
fn post_exec(&mut self, state: &mut S, input: &I);
|
||||
}
|
||||
|
||||
/// The hook that runs before and after the executor runs the target
|
||||
pub trait ExecutorHooksTuple<S>
|
||||
where
|
||||
S: UsesInput,
|
||||
{
|
||||
pub trait ExecutorHooksTuple<I, S> {
|
||||
/// Init these hooks
|
||||
fn init_all<E: HasObservers>(&mut self, state: &mut S);
|
||||
fn init_all(&mut self, state: &mut S);
|
||||
/// The hooks that runs before runs the target
|
||||
fn pre_exec_all(&mut self, state: &mut S, input: &S::Input);
|
||||
fn pre_exec_all(&mut self, state: &mut S, input: &I);
|
||||
/// The hooks that runs after runs the target
|
||||
fn post_exec_all(&mut self, state: &mut S, input: &S::Input);
|
||||
fn post_exec_all(&mut self, state: &mut S, input: &I);
|
||||
}
|
||||
|
||||
impl<S> ExecutorHooksTuple<S> for ()
|
||||
impl<I, S> ExecutorHooksTuple<I, S> for () {
|
||||
fn init_all(&mut self, _state: &mut S) {}
|
||||
fn pre_exec_all(&mut self, _state: &mut S, _input: &I) {}
|
||||
fn post_exec_all(&mut self, _state: &mut S, _input: &I) {}
|
||||
}
|
||||
|
||||
impl<Head, Tail, I, S> ExecutorHooksTuple<I, S> for (Head, Tail)
|
||||
where
|
||||
S: UsesInput,
|
||||
Head: ExecutorHook<I, S>,
|
||||
Tail: ExecutorHooksTuple<I, S>,
|
||||
{
|
||||
fn init_all<E: HasObservers>(&mut self, _state: &mut S) {}
|
||||
fn pre_exec_all(&mut self, _state: &mut S, _input: &S::Input) {}
|
||||
fn post_exec_all(&mut self, _state: &mut S, _input: &S::Input) {}
|
||||
fn init_all(&mut self, state: &mut S) {
|
||||
self.0.init(state);
|
||||
self.1.init_all(state);
|
||||
}
|
||||
|
||||
impl<Head, Tail, S> ExecutorHooksTuple<S> for (Head, Tail)
|
||||
where
|
||||
S: UsesInput,
|
||||
Head: ExecutorHook<S>,
|
||||
Tail: ExecutorHooksTuple<S>,
|
||||
{
|
||||
fn init_all<E: HasObservers>(&mut self, state: &mut S) {
|
||||
self.0.init::<E>(state);
|
||||
self.1.init_all::<E>(state);
|
||||
}
|
||||
|
||||
fn pre_exec_all(&mut self, state: &mut S, input: &S::Input) {
|
||||
fn pre_exec_all(&mut self, state: &mut S, input: &I) {
|
||||
self.0.pre_exec(state, input);
|
||||
self.1.pre_exec_all(state, input);
|
||||
}
|
||||
|
||||
fn post_exec_all(&mut self, state: &mut S, input: &S::Input) {
|
||||
fn post_exec_all(&mut self, state: &mut S, input: &I) {
|
||||
self.0.post_exec(state, input);
|
||||
self.1.post_exec_all(state, input);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ pub mod unix_signal_handler {
|
||||
fuzzer::HasObjective,
|
||||
inputs::{Input, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
};
|
||||
|
||||
pub(crate) type HandlerFuncPtr = unsafe fn(
|
||||
@ -77,16 +77,20 @@ pub mod unix_signal_handler {
|
||||
}
|
||||
|
||||
/// invokes the `post_exec` hook on all observer in case of panic
|
||||
pub fn setup_panic_hook<E, EM, OF, Z>()
|
||||
pub fn setup_panic_hook<E, EM, OF, S, Z>()
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
{
|
||||
let old_hook = panic::take_hook();
|
||||
panic::set_hook(Box::new(move |panic_info| unsafe {
|
||||
@ -96,12 +100,12 @@ pub mod unix_signal_handler {
|
||||
if (*data).is_valid() {
|
||||
// We are fuzzing!
|
||||
let executor = (*data).executor_mut::<E>();
|
||||
let state = (*data).state_mut::<E::State>();
|
||||
let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let state = (*data).state_mut::<S>();
|
||||
let input = (*data).take_current_input::<<S::Corpus as Corpus>::Input>();
|
||||
let fuzzer = (*data).fuzzer_mut::<Z>();
|
||||
let event_mgr = (*data).event_mgr_mut::<EM>();
|
||||
|
||||
run_observers_and_save_state::<E, EM, OF, Z>(
|
||||
run_observers_and_save_state::<E, EM, OF, S, Z>(
|
||||
executor,
|
||||
state,
|
||||
input,
|
||||
@ -123,20 +127,24 @@ pub mod unix_signal_handler {
|
||||
/// Well, signal handling is not safe
|
||||
#[cfg(unix)]
|
||||
#[allow(clippy::needless_pass_by_value)] // nightly no longer requires this
|
||||
pub unsafe fn inproc_timeout_handler<E, EM, OF, Z>(
|
||||
pub unsafe fn inproc_timeout_handler<E, EM, OF, S, Z>(
|
||||
_signal: Signal,
|
||||
_info: &mut siginfo_t,
|
||||
_context: Option<&mut ucontext_t>,
|
||||
data: &mut InProcessExecutorHandlerData,
|
||||
) where
|
||||
E: Executor<EM, Z> + HasInProcessHooks<E::State> + HasObservers,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasInProcessHooks<S> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
// this stuff is for batch timeout
|
||||
if !data.executor_ptr.is_null()
|
||||
@ -154,14 +162,14 @@ pub mod unix_signal_handler {
|
||||
}
|
||||
|
||||
let executor = data.executor_mut::<E>();
|
||||
let state = data.state_mut::<E::State>();
|
||||
let state = data.state_mut::<S>();
|
||||
let event_mgr = data.event_mgr_mut::<EM>();
|
||||
let fuzzer = data.fuzzer_mut::<Z>();
|
||||
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let input = data.take_current_input::<<S::Corpus as Corpus>::Input>();
|
||||
|
||||
log::error!("Timeout in fuzz run.");
|
||||
|
||||
run_observers_and_save_state::<E, EM, OF, Z>(
|
||||
run_observers_and_save_state::<E, EM, OF, S, Z>(
|
||||
executor,
|
||||
state,
|
||||
input,
|
||||
@ -180,20 +188,24 @@ pub mod unix_signal_handler {
|
||||
/// # Safety
|
||||
/// Well, signal handling is not safe
|
||||
#[allow(clippy::needless_pass_by_value)] // nightly no longer requires this
|
||||
pub unsafe fn inproc_crash_handler<E, EM, OF, Z>(
|
||||
pub unsafe fn inproc_crash_handler<E, EM, OF, S, Z>(
|
||||
signal: Signal,
|
||||
_info: &mut siginfo_t,
|
||||
_context: Option<&mut ucontext_t>,
|
||||
data: &mut InProcessExecutorHandlerData,
|
||||
) where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
|
||||
let _context = _context.map(|p| {
|
||||
@ -205,10 +217,10 @@ pub mod unix_signal_handler {
|
||||
if data.is_valid() {
|
||||
let executor = data.executor_mut::<E>();
|
||||
// disarms timeout in case of timeout
|
||||
let state = data.state_mut::<E::State>();
|
||||
let state = data.state_mut::<S>();
|
||||
let event_mgr = data.event_mgr_mut::<EM>();
|
||||
let fuzzer = data.fuzzer_mut::<Z>();
|
||||
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let input = data.take_current_input::<<S::Corpus as Corpus>::Input>();
|
||||
|
||||
log::error!("Child crashed!");
|
||||
|
||||
@ -233,7 +245,7 @@ pub mod unix_signal_handler {
|
||||
}
|
||||
}
|
||||
|
||||
run_observers_and_save_state::<E, EM, OF, Z>(
|
||||
run_observers_and_save_state::<E, EM, OF, S, Z>(
|
||||
executor,
|
||||
state,
|
||||
input,
|
||||
|
@ -17,23 +17,27 @@ pub mod windows_asan_handler {
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
inputs::{Input, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
};
|
||||
|
||||
/// # Safety
|
||||
/// ASAN deatch handler
|
||||
pub unsafe extern "C" fn asan_death_handler<E, EM, OF, Z>()
|
||||
pub unsafe extern "C" fn asan_death_handler<E, EM, OF, S, Z>()
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
{
|
||||
let data = &raw mut GLOBAL_STATE;
|
||||
(*data).set_in_handler(true);
|
||||
@ -78,16 +82,16 @@ pub mod windows_asan_handler {
|
||||
(*data).ptp_timer = None;
|
||||
}
|
||||
|
||||
let state = (*data).state_mut::<E::State>();
|
||||
let state = (*data).state_mut::<S>();
|
||||
let fuzzer = (*data).fuzzer_mut::<Z>();
|
||||
let event_mgr = (*data).event_mgr_mut::<EM>();
|
||||
|
||||
log::error!("Child crashed!");
|
||||
|
||||
// Make sure we don't crash in the crash handler forever.
|
||||
let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let input = (*data).take_current_input::<<S::Corpus as Corpus>::Input>();
|
||||
|
||||
run_observers_and_save_state::<E, EM, OF, Z>(
|
||||
run_observers_and_save_state::<E, EM, OF, S, Z>(
|
||||
executor,
|
||||
state,
|
||||
input,
|
||||
@ -138,7 +142,7 @@ pub mod windows_exception_handler {
|
||||
fuzzer::HasObjective,
|
||||
inputs::{Input, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
};
|
||||
|
||||
pub(crate) type HandlerFuncPtr =
|
||||
@ -182,16 +186,20 @@ pub mod windows_exception_handler {
|
||||
/// # Safety
|
||||
/// Well, exception handling is not safe
|
||||
#[cfg(feature = "std")]
|
||||
pub fn setup_panic_hook<E, EM, OF, Z>()
|
||||
pub fn setup_panic_hook<E, EM, OF, S, Z>()
|
||||
where
|
||||
E: HasObservers + Executor<EM, Z>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
{
|
||||
let old_hook = panic::take_hook();
|
||||
panic::set_hook(Box::new(move |panic_info| unsafe {
|
||||
@ -216,13 +224,13 @@ pub mod windows_exception_handler {
|
||||
if (*data).is_valid() {
|
||||
// We are fuzzing!
|
||||
let executor = (*data).executor_mut::<E>();
|
||||
let state = (*data).state_mut::<E::State>();
|
||||
let state = (*data).state_mut::<S>();
|
||||
let fuzzer = (*data).fuzzer_mut::<Z>();
|
||||
let event_mgr = (*data).event_mgr_mut::<EM>();
|
||||
|
||||
let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let input = (*data).take_current_input::<<S::Corpus as Corpus>::Input>();
|
||||
|
||||
run_observers_and_save_state::<E, EM, OF, Z>(
|
||||
run_observers_and_save_state::<E, EM, OF, S, Z>(
|
||||
executor,
|
||||
state,
|
||||
input,
|
||||
@ -242,19 +250,23 @@ pub mod windows_exception_handler {
|
||||
///
|
||||
/// # Safety
|
||||
/// Well, exception handling is not safe
|
||||
pub unsafe extern "system" fn inproc_timeout_handler<E, EM, OF, Z>(
|
||||
pub unsafe extern "system" fn inproc_timeout_handler<E, EM, OF, S, Z>(
|
||||
_p0: *mut u8,
|
||||
global_state: *mut c_void,
|
||||
_p1: *mut u8,
|
||||
) where
|
||||
E: HasObservers + HasInProcessHooks<E::State> + Executor<EM, Z>,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: State + HasExecutions + HasSolutions + HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasInProcessHooks<S> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
let data: &mut InProcessExecutorHandlerData =
|
||||
&mut *(global_state as *mut InProcessExecutorHandlerData);
|
||||
@ -277,7 +289,7 @@ pub mod windows_exception_handler {
|
||||
|
||||
if data.in_target == 1 {
|
||||
let executor = data.executor_mut::<E>();
|
||||
let state = data.state_mut::<E::State>();
|
||||
let state = data.state_mut::<S>();
|
||||
let fuzzer = data.fuzzer_mut::<Z>();
|
||||
let event_mgr = data.event_mgr_mut::<EM>();
|
||||
|
||||
@ -286,12 +298,12 @@ pub mod windows_exception_handler {
|
||||
} else {
|
||||
log::error!("Timeout in fuzz run.");
|
||||
|
||||
let input = (data.current_input_ptr as *const <E::State as UsesInput>::Input)
|
||||
let input = (data.current_input_ptr as *const <S::Corpus as Corpus>::Input)
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
data.current_input_ptr = ptr::null_mut();
|
||||
|
||||
run_observers_and_save_state::<E, EM, OF, Z>(
|
||||
run_observers_and_save_state::<E, EM, OF, S, Z>(
|
||||
executor,
|
||||
state,
|
||||
input,
|
||||
@ -315,18 +327,22 @@ pub mod windows_exception_handler {
|
||||
///
|
||||
/// # Safety
|
||||
/// Well, exception handling is not safe
|
||||
pub unsafe fn inproc_crash_handler<E, EM, OF, Z>(
|
||||
pub unsafe fn inproc_crash_handler<E, EM, OF, S, Z>(
|
||||
exception_pointers: *mut EXCEPTION_POINTERS,
|
||||
data: &mut InProcessExecutorHandlerData,
|
||||
) where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
// Have we set a timer_before?
|
||||
if data.ptp_timer.is_some() {
|
||||
@ -400,7 +416,7 @@ pub mod windows_exception_handler {
|
||||
data.ptp_timer = None;
|
||||
}
|
||||
|
||||
let state = data.state_mut::<E::State>();
|
||||
let state = data.state_mut::<S>();
|
||||
let fuzzer = data.fuzzer_mut::<Z>();
|
||||
let event_mgr = data.event_mgr_mut::<EM>();
|
||||
|
||||
@ -412,7 +428,7 @@ pub mod windows_exception_handler {
|
||||
|
||||
// Make sure we don't crash in the crash handler forever.
|
||||
if is_crash {
|
||||
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let input = data.take_current_input::<<S::Corpus as Corpus>::Input>();
|
||||
{
|
||||
let mut bsod = Vec::new();
|
||||
{
|
||||
@ -424,7 +440,7 @@ pub mod windows_exception_handler {
|
||||
}
|
||||
log::error!("{}", std::str::from_utf8(&bsod).unwrap());
|
||||
}
|
||||
run_observers_and_save_state::<E, EM, OF, Z>(
|
||||
run_observers_and_save_state::<E, EM, OF, S, Z>(
|
||||
executor,
|
||||
state,
|
||||
input,
|
||||
|
@ -28,9 +28,9 @@ use crate::{
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
inputs::{Input, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -54,18 +54,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<HT, OT, S> UsesState for GenericInProcessExecutorInner<HT, OT, S>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<HT, OT, S> HasObservers for GenericInProcessExecutorInner<HT, OT, S>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
impl<HT, OT, S> HasObservers for GenericInProcessExecutorInner<HT, OT, S> {
|
||||
type Observers = OT;
|
||||
|
||||
#[inline]
|
||||
@ -81,8 +70,8 @@ where
|
||||
|
||||
impl<HT, OT, S> GenericInProcessExecutorInner<HT, OT, S>
|
||||
where
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
S: State,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
/// This function marks the boundary between the fuzzer and the target
|
||||
///
|
||||
@ -93,9 +82,9 @@ where
|
||||
pub unsafe fn enter_target<EM, Z>(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut <Self as UsesState>::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &<Self as UsesInput>::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
executor_ptr: *const c_void,
|
||||
) {
|
||||
unsafe {
|
||||
@ -128,9 +117,9 @@ where
|
||||
pub fn leave_target<EM, Z>(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
_state: &mut <Self as UsesState>::State,
|
||||
_state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
_input: &<Self as UsesInput>::Input,
|
||||
_input: &<S::Corpus as Corpus>::Input,
|
||||
) {
|
||||
unsafe {
|
||||
let data = &raw mut GLOBAL_STATE;
|
||||
@ -143,9 +132,9 @@ where
|
||||
|
||||
impl<HT, OT, S> GenericInProcessExecutorInner<HT, OT, S>
|
||||
where
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: HasCorpus + HasExecutions + HasSolutions + UsesInput,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus + HasExecutions + HasSolutions,
|
||||
{
|
||||
/// Create a new in mem executor with the default timeout (5 sec)
|
||||
pub fn generic<E, EM, OF, Z>(
|
||||
@ -156,14 +145,17 @@ where
|
||||
event_mgr: &mut EM,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers + HasInProcessHooks<S>,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers + HasInProcessHooks<S>,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, E::Input, E::Observers, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ HasSolutions
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
{
|
||||
Self::with_timeout_generic::<E, EM, OF, Z>(
|
||||
user_hooks,
|
||||
@ -186,14 +178,17 @@ where
|
||||
exec_tmout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers + HasInProcessHooks<S>,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers + HasInProcessHooks<S>,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, E::Input, E::Observers, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ HasSolutions
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
{
|
||||
let mut me = Self::with_timeout_generic::<E, EM, OF, Z>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
|
||||
@ -219,18 +214,21 @@ where
|
||||
timeout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers + HasInProcessHooks<S>,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers + HasInProcessHooks<S>,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, E::Input, E::Observers, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ HasSolutions
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
{
|
||||
let default = InProcessHooks::new::<E, EM, OF, Z>(timeout)?;
|
||||
let mut hooks = tuple_list!(default).merge(user_hooks);
|
||||
hooks.init_all::<Self>(state);
|
||||
hooks.init_all(state);
|
||||
|
||||
#[cfg(windows)]
|
||||
// Some initialization necessary for windows.
|
||||
@ -275,10 +273,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<HT, OT, S> HasInProcessHooks<S> for GenericInProcessExecutorInner<HT, OT, S>
|
||||
where
|
||||
S: UsesInput,
|
||||
{
|
||||
impl<HT, OT, S> HasInProcessHooks<S> for GenericInProcessExecutorInner<HT, OT, S> {
|
||||
/// the timeout handler
|
||||
#[inline]
|
||||
fn inprocess_hooks(&self) -> &InProcessHooks<S> {
|
||||
|
@ -16,6 +16,8 @@ use libafl_bolts::tuples::{tuple_list, RefIndexable};
|
||||
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
use crate::executors::hooks::inprocess::GLOBAL_STATE;
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
use crate::ExecutionProcessor;
|
||||
use crate::{
|
||||
corpus::{Corpus, Testcase},
|
||||
events::{Event, EventFirer, EventRestarter},
|
||||
@ -26,13 +28,11 @@ use crate::{
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
inputs::{Input, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions, State, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
use crate::{ExecutionProcessor, HasScheduler};
|
||||
|
||||
/// The inner structure of `InProcessExecutor`.
|
||||
pub mod inner;
|
||||
@ -55,14 +55,7 @@ pub type OwnedInProcessExecutor<OT, S> = GenericInProcessExecutor<
|
||||
>;
|
||||
|
||||
/// The inmem executor simply calls a target function, then returns afterwards.
|
||||
pub struct GenericInProcessExecutor<H, HB, HT, OT, S>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
pub struct GenericInProcessExecutor<H, HB, HT, OT, S> {
|
||||
harness_fn: HB,
|
||||
inner: GenericInProcessExecutorInner<HT, OT, S>,
|
||||
phantom: PhantomData<(*const H, HB)>,
|
||||
@ -70,11 +63,7 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S> Debug for GenericInProcessExecutor<H, HB, HT, OT, S>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
S: State,
|
||||
OT: Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("GenericInProcessExecutor")
|
||||
@ -84,32 +73,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, HB, HT, OT, S> UsesState for GenericInProcessExecutor<H, HB, HT, OT, S>
|
||||
impl<EM, H, HB, HT, OT, S, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for GenericInProcessExecutor<H, HB, HT, OT, S>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
S: HasCorpus + HasExecutions,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<EM, H, HB, HT, OT, S, Z> Executor<EM, Z> for GenericInProcessExecutor<H, HB, HT, OT, S>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State + HasExecutions,
|
||||
H: FnMut(&<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
*state.executions_mut() += 1;
|
||||
unsafe {
|
||||
@ -127,14 +105,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, HB, HT, OT, S> HasObservers for GenericInProcessExecutor<H, HB, HT, OT, S>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
impl<H, HB, HT, OT, S> HasObservers for GenericInProcessExecutor<H, HB, HT, OT, S> {
|
||||
type Observers = OT;
|
||||
|
||||
#[inline]
|
||||
@ -150,11 +121,15 @@ where
|
||||
|
||||
impl<'a, H, OT, S> InProcessExecutor<'a, H, OT, S>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: HasExecutions + HasSolutions + HasCorpus + State,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
H: FnMut(&<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
|
||||
+ HasExecutions
|
||||
+ HasSolutions,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input,
|
||||
{
|
||||
/// Create a new in mem executor with the default timeout (5 sec)
|
||||
pub fn new<EM, OF, Z>(
|
||||
@ -165,13 +140,11 @@ where
|
||||
event_mgr: &mut EM,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S> + HasObservers,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
Self::with_timeout_generic(
|
||||
Self::with_timeout_generic::<EM, OF, Z>(
|
||||
tuple_list!(),
|
||||
harness_fn,
|
||||
observers,
|
||||
@ -193,13 +166,9 @@ where
|
||||
exec_tmout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>(
|
||||
tuple_list!(),
|
||||
@ -234,13 +203,9 @@ where
|
||||
timeout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>(
|
||||
tuple_list!(),
|
||||
@ -261,13 +226,17 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S> GenericInProcessExecutor<H, HB, HT, OT, S>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
H: FnMut(&<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State + HasExecutions + HasSolutions + HasCorpus,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
|
||||
+ HasExecutions
|
||||
+ HasSolutions,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input,
|
||||
{
|
||||
/// Create a new in mem executor with the default timeout (5 sec)
|
||||
pub fn generic<EM, OF, Z>(
|
||||
@ -279,13 +248,11 @@ where
|
||||
event_mgr: &mut EM,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
Self::with_timeout_generic(
|
||||
Self::with_timeout_generic::<EM, OF, Z>(
|
||||
user_hooks,
|
||||
harness_fn,
|
||||
observers,
|
||||
@ -308,13 +275,9 @@ where
|
||||
exec_tmout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
|
||||
@ -345,13 +308,9 @@ where
|
||||
timeout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, timeout,
|
||||
@ -390,10 +349,7 @@ where
|
||||
}
|
||||
|
||||
/// The struct has [`InProcessHooks`].
|
||||
pub trait HasInProcessHooks<S>
|
||||
where
|
||||
S: UsesInput,
|
||||
{
|
||||
pub trait HasInProcessHooks<S> {
|
||||
/// Get the in-process handlers.
|
||||
fn inprocess_hooks(&self) -> &InProcessHooks<S>;
|
||||
|
||||
@ -401,14 +357,7 @@ where
|
||||
fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks<S>;
|
||||
}
|
||||
|
||||
impl<H, HB, HT, OT, S> HasInProcessHooks<S> for GenericInProcessExecutor<H, HB, HT, OT, S>
|
||||
where
|
||||
H: FnMut(&<S as UsesInput>::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State + HasExecutions + HasSolutions + HasCorpus,
|
||||
{
|
||||
impl<H, HB, HT, OT, S> HasInProcessHooks<S> for GenericInProcessExecutor<H, HB, HT, OT, S> {
|
||||
/// the timeout handler
|
||||
#[inline]
|
||||
fn inprocess_hooks(&self) -> &InProcessHooks<S> {
|
||||
@ -424,21 +373,26 @@ where
|
||||
|
||||
#[inline]
|
||||
/// Save state if it is an objective
|
||||
pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
||||
pub fn run_observers_and_save_state<E, EM, OF, S, Z>(
|
||||
executor: &mut E,
|
||||
state: &mut E::State,
|
||||
input: &E::Input,
|
||||
state: &mut S,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
fuzzer: &mut Z,
|
||||
event_mgr: &mut EM,
|
||||
exitkind: ExitKind,
|
||||
) where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
let mut observers = executor.observers_mut();
|
||||
|
||||
@ -491,29 +445,33 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
||||
/// # Safety
|
||||
/// This will directly access `GLOBAL_STATE` and related data pointers
|
||||
#[cfg(any(unix, feature = "std"))]
|
||||
pub unsafe fn generic_inproc_crash_handler<E, EM, OF, Z>()
|
||||
pub unsafe fn generic_inproc_crash_handler<E, EM, OF, S, Z>()
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>
|
||||
+ HasScheduler<E::Input, E::State>
|
||||
+ ExecutionProcessor<EM, E::Input, E::Observers, E::State>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
+ ExecutionProcessor<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
{
|
||||
let data = &raw mut GLOBAL_STATE;
|
||||
let in_handler = (*data).set_in_handler(true);
|
||||
|
||||
if (*data).is_valid() {
|
||||
let executor = (*data).executor_mut::<E>();
|
||||
let state = (*data).state_mut::<E::State>();
|
||||
let state = (*data).state_mut::<S>();
|
||||
let event_mgr = (*data).event_mgr_mut::<EM>();
|
||||
let fuzzer = (*data).fuzzer_mut::<Z>();
|
||||
let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let input = (*data).take_current_input::<<S::Corpus as Corpus>::Input>();
|
||||
|
||||
run_observers_and_save_state::<E, EM, OF, Z>(
|
||||
run_observers_and_save_state::<E, EM, OF, S, Z>(
|
||||
executor,
|
||||
state,
|
||||
input,
|
||||
|
@ -20,9 +20,9 @@ use crate::{
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
inputs::{Input, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -44,14 +44,7 @@ pub type OwnedInProcessExecutor<OT, S, ES> = StatefulGenericInProcessExecutor<
|
||||
|
||||
/// The inmem executor simply calls a target function, then returns afterwards.
|
||||
/// The harness can access the internal state of the executor.
|
||||
pub struct StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
pub struct StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES> {
|
||||
/// The harness function, being executed for each fuzzing loop execution
|
||||
harness_fn: HB,
|
||||
/// The state used as argument of the harness
|
||||
@ -63,11 +56,7 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> Debug for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
S: State,
|
||||
OT: Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("StatefulGenericInProcessExecutor")
|
||||
@ -77,33 +66,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> UsesState for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<EM, H, HB, HT, OT, S, Z, ES> Executor<EM, Z>
|
||||
impl<EM, H, HB, HT, OT, S, Z, ES> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &mut S, &<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State + HasExecutions,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus + HasExecutions,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
*state.executions_mut() += 1;
|
||||
unsafe {
|
||||
@ -123,11 +100,11 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> HasObservers for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &mut S, &<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
type Observers = OT;
|
||||
#[inline]
|
||||
@ -143,11 +120,15 @@ where
|
||||
|
||||
impl<'a, H, OT, S, ES> StatefulInProcessExecutor<'a, H, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&mut ES, &mut S, &<S as UsesInput>::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: HasExecutions + HasSolutions + HasCorpus + State,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
H: FnMut(&mut ES, &mut S, &<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Clone + Input,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
/// Create a new in mem executor with the default timeout (5 sec)
|
||||
pub fn new<EM, OF, Z>(
|
||||
@ -159,10 +140,8 @@ where
|
||||
event_mgr: &mut EM,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
Self::with_timeout_generic(
|
||||
@ -189,13 +168,9 @@ where
|
||||
exec_tmout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>(
|
||||
tuple_list!(),
|
||||
@ -232,13 +207,9 @@ where
|
||||
timeout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>(
|
||||
tuple_list!(),
|
||||
@ -258,14 +229,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
impl<H, HB, HT, OT, S, ES> StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES> {
|
||||
/// The executor state given to the harness
|
||||
pub fn exposed_executor_state(&self) -> &ES {
|
||||
&self.exposed_executor_state
|
||||
@ -279,13 +243,18 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &mut S, &<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State + HasExecutions + HasSolutions + HasCorpus,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus
|
||||
+ HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
{
|
||||
/// Create a new in mem executor with the default timeout (5 sec)
|
||||
pub fn generic<EM, OF, Z>(
|
||||
@ -299,8 +268,7 @@ where
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
Self::with_timeout_generic(
|
||||
@ -330,11 +298,8 @@ where
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
|
||||
@ -369,11 +334,8 @@ where
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
EM: EventFirer<State = S> + EventRestarter,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, timeout,
|
||||
@ -414,12 +376,6 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> HasInProcessHooks<S>
|
||||
for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&mut ES, &mut S, &<S as UsesInput>::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State + HasExecutions + HasSolutions + HasCorpus,
|
||||
{
|
||||
/// the timeout handler
|
||||
#[inline]
|
||||
|
@ -20,7 +20,7 @@ use nix::{
|
||||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
use crate::executors::hooks::timer::{setitimer, Itimerval, Timeval, ITIMER_REAL};
|
||||
use crate::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
corpus::Corpus,
|
||||
executors::{
|
||||
hooks::{
|
||||
inprocess_fork::{InChildProcessHooks, FORK_EXECUTOR_GLOBAL_DATA},
|
||||
@ -28,9 +28,8 @@ use crate::{
|
||||
},
|
||||
ExitKind, HasObservers,
|
||||
},
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
state::{State, UsesState},
|
||||
state::HasCorpus,
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -73,13 +72,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<HT, OT, S, SP, EM, Z> UsesState for GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn parse_itimerspec(timeout: Duration) -> libc::itimerspec {
|
||||
let milli_sec = timeout.as_millis();
|
||||
@ -116,18 +108,17 @@ fn parse_itimerval(timeout: Duration) -> Itimerval {
|
||||
|
||||
impl<EM, HT, OT, S, SP, Z> GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
S: State + UsesInput,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
SP: ShMemProvider,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
pub(super) unsafe fn pre_run_target_child(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut <GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z> as UsesState>::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &<GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z> as UsesInput>::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<(), Error> {
|
||||
self.shmem_provider.post_fork(true)?;
|
||||
|
||||
@ -160,9 +151,9 @@ where
|
||||
pub(super) unsafe fn post_run_target_child(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut <GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z> as UsesState>::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &<GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z> as UsesInput>::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) {
|
||||
self.observers
|
||||
.post_exec_child_all(state, input, &ExitKind::Ok)
|
||||
@ -209,18 +200,18 @@ where
|
||||
|
||||
impl<HT, OT, S, SP, EM, Z> GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
S: State,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
#[inline]
|
||||
/// This function marks the boundary between the fuzzer and the target.
|
||||
pub fn enter_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
state: &mut <Self as UsesState>::State,
|
||||
state: &mut S,
|
||||
_event_mgr: &mut EM,
|
||||
input: &<Self as UsesInput>::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) {
|
||||
unsafe {
|
||||
let data = &raw mut FORK_EXECUTOR_GLOBAL_DATA;
|
||||
@ -245,9 +236,9 @@ where
|
||||
pub fn leave_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
_state: &mut <Self as UsesState>::State,
|
||||
_state: &mut S,
|
||||
_event_mgr: &mut EM,
|
||||
_input: &<Self as UsesInput>::Input,
|
||||
_input: &<S::Corpus as Corpus>::Input,
|
||||
) {
|
||||
// do nothing
|
||||
}
|
||||
@ -265,7 +256,7 @@ where
|
||||
) -> Result<Self, Error> {
|
||||
let default_hooks = InChildProcessHooks::new::<Self>()?;
|
||||
let mut hooks = tuple_list!(default_hooks).merge(userhooks);
|
||||
hooks.init_all::<Self>(state);
|
||||
hooks.init_all(state);
|
||||
let itimerspec = parse_itimerspec(timeout);
|
||||
Ok(Self {
|
||||
shmem_provider,
|
||||
@ -289,7 +280,7 @@ where
|
||||
) -> Result<Self, Error> {
|
||||
let default_hooks = InChildProcessHooks::new::<Self>()?;
|
||||
let mut hooks = tuple_list!(default_hooks).merge(userhooks);
|
||||
hooks.init_all::<Self>(state);
|
||||
hooks.init_all(state);
|
||||
|
||||
let itimerval = parse_itimerval(timeout);
|
||||
|
||||
@ -303,10 +294,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<HT, OT, S, SP, EM, Z> HasObservers for GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
impl<HT, OT, S, SP, EM, Z> HasObservers
|
||||
for GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z>
|
||||
{
|
||||
type Observers = OT;
|
||||
|
||||
|
@ -14,16 +14,13 @@ use nix::unistd::{fork, ForkResult};
|
||||
|
||||
use super::hooks::ExecutorHooksTuple;
|
||||
use crate::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
corpus::Corpus,
|
||||
executors::{
|
||||
hooks::inprocess_fork::InProcessForkExecutorGlobalData,
|
||||
inprocess_fork::inner::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers,
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
state::{HasExecutions, HasSolutions, State, UsesState},
|
||||
state::{HasCorpus, HasExecutions},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -46,16 +43,10 @@ pub mod stateful;
|
||||
pub type InProcessForkExecutor<'a, H, OT, S, SP, EM, Z> =
|
||||
GenericInProcessForkExecutor<'a, H, (), OT, S, SP, EM, Z>;
|
||||
|
||||
impl<'a, H, OT, S, SP, EM, Z, OF> InProcessForkExecutor<'a, H, OT, S, SP, EM, Z>
|
||||
impl<'a, H, OT, S, SP, EM, Z> InProcessForkExecutor<'a, H, OT, S, SP, EM, Z>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
S: State,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
SP: ShMemProvider,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: HasSolutions,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
/// The constructor for `InProcessForkExecutor`
|
||||
pub fn new(
|
||||
@ -84,27 +75,16 @@ where
|
||||
///
|
||||
/// On Linux, when fuzzing a Rust target, set `panic = "abort"` in your `Cargo.toml` (see [Cargo documentation](https://doc.rust-lang.org/cargo/reference/profiles.html#panic)).
|
||||
/// Else panics can not be caught by `LibAFL`.
|
||||
pub struct GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: UsesInput,
|
||||
SP: ShMemProvider,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
EM: UsesState<State = S>,
|
||||
{
|
||||
pub struct GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z> {
|
||||
harness_fn: &'a mut H,
|
||||
inner: GenericInProcessForkExecutorInner<HT, OT, S, SP, EM, Z>,
|
||||
}
|
||||
|
||||
impl<H, HT, OT, S, SP, EM, Z> Debug for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
S: UsesInput,
|
||||
SP: ShMemProvider,
|
||||
HT: ExecutorHooksTuple<S> + Debug,
|
||||
EM: UsesState<State = S>,
|
||||
HT: Debug,
|
||||
OT: Debug,
|
||||
SP: Debug,
|
||||
{
|
||||
#[cfg(target_os = "linux")]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
@ -123,36 +103,22 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, HT, OT, S, SP, EM, Z> UsesState
|
||||
impl<EM, H, HT, OT, S, SP, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
H: FnMut(&<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
S: HasCorpus + HasExecutions,
|
||||
SP: ShMemProvider,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
EM: UsesState<State = S>,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<EM, H, HT, OT, S, SP, Z> Executor<EM, Z>
|
||||
for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
S: State + HasExecutions,
|
||||
SP: ShMemProvider,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
#[inline]
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
@ -176,16 +142,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, H, HT, OT, S, SP, EM, Z, OF> GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z>
|
||||
impl<'a, H, HT, OT, S, SP, EM, Z> GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
SP: ShMemProvider,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: State + HasSolutions,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
/// Creates a new [`GenericInProcessForkExecutor`] with custom hooks
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
@ -229,13 +190,6 @@ where {
|
||||
|
||||
impl<H, HT, OT, S, SP, EM, Z> HasObservers
|
||||
for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
S: State,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
SP: ShMemProvider,
|
||||
EM: UsesState<State = S>,
|
||||
{
|
||||
type Observers = OT;
|
||||
#[inline]
|
||||
@ -262,16 +216,14 @@ pub mod child_signal_handlers {
|
||||
hooks::inprocess_fork::{InProcessForkExecutorGlobalData, FORK_EXECUTOR_GLOBAL_DATA},
|
||||
ExitKind, HasObservers,
|
||||
},
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
state::UsesState,
|
||||
};
|
||||
|
||||
/// invokes the `post_exec_child` hook on all observer in case the child process panics
|
||||
pub fn setup_child_panic_hook<E>()
|
||||
pub fn setup_child_panic_hook<E, I, S>()
|
||||
where
|
||||
E: HasObservers + UsesState,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: HasObservers,
|
||||
E::Observers: ObserversTuple<I, S>,
|
||||
{
|
||||
let old_hook = panic::take_hook();
|
||||
panic::set_hook(Box::new(move |panic_info| unsafe {
|
||||
@ -280,9 +232,9 @@ pub mod child_signal_handlers {
|
||||
if !data.is_null() && (*data).is_valid() {
|
||||
let executor = (*data).executor_mut::<E>();
|
||||
let mut observers = executor.observers_mut();
|
||||
let state = (*data).state_mut::<E::State>();
|
||||
let state = (*data).state_mut::<S>();
|
||||
// Invalidate data to not execute again the observer hooks in the crash handler
|
||||
let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let input = (*data).take_current_input::<I>();
|
||||
observers
|
||||
.post_exec_child_all(state, input, &ExitKind::Crash)
|
||||
.expect("Failed to run post_exec on observers");
|
||||
@ -300,20 +252,20 @@ pub mod child_signal_handlers {
|
||||
/// It will dereference the `data` pointer and assume it's valid.
|
||||
#[cfg(unix)]
|
||||
#[allow(clippy::needless_pass_by_value)] // nightly no longer requires this
|
||||
pub(crate) unsafe fn child_crash_handler<E>(
|
||||
pub(crate) unsafe fn child_crash_handler<E, I, S>(
|
||||
_signal: Signal,
|
||||
_info: &mut siginfo_t,
|
||||
_context: Option<&mut ucontext_t>,
|
||||
data: &mut InProcessForkExecutorGlobalData,
|
||||
) where
|
||||
E: HasObservers + UsesState,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: HasObservers,
|
||||
E::Observers: ObserversTuple<I, S>,
|
||||
{
|
||||
if data.is_valid() {
|
||||
let executor = data.executor_mut::<E>();
|
||||
let mut observers = executor.observers_mut();
|
||||
let state = data.state_mut::<E::State>();
|
||||
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let state = data.state_mut::<S>();
|
||||
let input = data.take_current_input::<I>();
|
||||
observers
|
||||
.post_exec_child_all(state, input, &ExitKind::Crash)
|
||||
.expect("Failed to run post_exec on observers");
|
||||
@ -324,20 +276,20 @@ pub mod child_signal_handlers {
|
||||
|
||||
#[cfg(unix)]
|
||||
#[allow(clippy::needless_pass_by_value)] // nightly no longer requires this
|
||||
pub(crate) unsafe fn child_timeout_handler<E>(
|
||||
pub(crate) unsafe fn child_timeout_handler<E, I, S>(
|
||||
#[cfg(unix)] _signal: Signal,
|
||||
_info: &mut siginfo_t,
|
||||
_context: Option<&mut ucontext_t>,
|
||||
data: &mut InProcessForkExecutorGlobalData,
|
||||
) where
|
||||
E: HasObservers + UsesState,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: HasObservers,
|
||||
E::Observers: ObserversTuple<I, S>,
|
||||
{
|
||||
if data.is_valid() {
|
||||
let executor = data.executor_mut::<E>();
|
||||
let mut observers = executor.observers_mut();
|
||||
let state = data.state_mut::<E::State>();
|
||||
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
||||
let state = data.state_mut::<S>();
|
||||
let input = data.take_current_input::<I>();
|
||||
observers
|
||||
.post_exec_child_all(state, input, &ExitKind::Timeout)
|
||||
.expect("Failed to run post_exec on observers");
|
||||
@ -430,7 +382,7 @@ mod tests {
|
||||
let input = NopInput {};
|
||||
let mut fuzzer = NopFuzzer::new();
|
||||
let mut state = NopState::new();
|
||||
let mut mgr = SimpleEventManager::printing();
|
||||
let mut mgr: SimpleEventManager<_, NopState<NopInput>> = SimpleEventManager::printing();
|
||||
in_process_fork_executor
|
||||
.run_target(&mut fuzzer, &mut state, &mut mgr, &input)
|
||||
.unwrap();
|
||||
|
@ -15,16 +15,13 @@ use libafl_bolts::{
|
||||
use nix::unistd::{fork, ForkResult};
|
||||
|
||||
use crate::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
corpus::Corpus,
|
||||
executors::{
|
||||
hooks::ExecutorHooksTuple, inprocess_fork::GenericInProcessForkExecutorInner, Executor,
|
||||
ExitKind, HasObservers,
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
state::{HasExecutions, State, UsesState},
|
||||
state::{HasCorpus, HasExecutions},
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -34,9 +31,8 @@ pub type StatefulInProcessForkExecutor<'a, H, OT, S, SP, ES, EM, Z> =
|
||||
|
||||
impl<'a, H, OT, S, SP, ES, EM, Z> StatefulInProcessForkExecutor<'a, H, OT, S, SP, ES, EM, Z>
|
||||
where
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
/// The constructor for `InProcessForkExecutor`
|
||||
@ -65,11 +61,7 @@ where
|
||||
}
|
||||
|
||||
/// [`StatefulGenericInProcessForkExecutor`] is an executor that forks the current process before each execution. Harness can access some internal state.
|
||||
pub struct StatefulGenericInProcessForkExecutor<'a, H, HT, OT, S, SP, ES, EM, Z>
|
||||
where
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
S: UsesInput,
|
||||
{
|
||||
pub struct StatefulGenericInProcessForkExecutor<'a, H, HT, OT, S, SP, ES, EM, Z> {
|
||||
/// The harness function, being executed for each fuzzing loop execution
|
||||
harness_fn: &'a mut H,
|
||||
/// The state used as argument of the harness
|
||||
@ -82,10 +74,8 @@ where
|
||||
impl<H, HT, OT, S, SP, ES, EM, Z> Debug
|
||||
for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z>
|
||||
where
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HT: Debug,
|
||||
OT: Debug,
|
||||
S: UsesInput,
|
||||
SP: Debug,
|
||||
{
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -105,34 +95,22 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, HT, OT, S, SP, ES, EM, Z> UsesState
|
||||
impl<EM, H, HT, OT, S, SP, Z, ES> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z>
|
||||
where
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<EM, H, HT, OT, S, SP, Z, ES, OF> Executor<EM, Z>
|
||||
for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z>
|
||||
where
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
S: State + HasExecutions,
|
||||
H: FnMut(&mut ES, &<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
HT: ExecutorHooksTuple<<<S as HasCorpus>::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus + HasExecutions,
|
||||
SP: ShMemProvider,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
OT: ObserversTuple<<<S as HasCorpus>::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
#[inline]
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
@ -159,10 +137,9 @@ where
|
||||
impl<'a, H, HT, OT, S, SP, ES, EM, Z>
|
||||
StatefulGenericInProcessForkExecutor<'a, H, HT, OT, S, SP, ES, EM, Z>
|
||||
where
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
HT: ExecutorHooksTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus,
|
||||
{
|
||||
/// Creates a new [`StatefulGenericInProcessForkExecutor`] with custom hooks
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
@ -208,10 +185,6 @@ where
|
||||
|
||||
impl<H, HT, OT, S, SP, ES, EM, Z> HasObservers
|
||||
for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z>
|
||||
where
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
type Observers = OT;
|
||||
|
||||
|
@ -20,7 +20,7 @@ use serde::{Deserialize, Serialize};
|
||||
pub use shadow::ShadowExecutor;
|
||||
pub use with_observers::WithObservers;
|
||||
|
||||
use crate::{state::UsesState, Error};
|
||||
use crate::Error;
|
||||
|
||||
pub mod combined;
|
||||
#[cfg(all(feature = "std", unix))]
|
||||
@ -117,17 +117,14 @@ pub trait HasObservers {
|
||||
}
|
||||
|
||||
/// An executor takes the given inputs, and runs the harness/target.
|
||||
pub trait Executor<EM, Z>: UsesState
|
||||
where
|
||||
EM: UsesState<State = Self::State>,
|
||||
{
|
||||
pub trait Executor<EM, I, S, Z> {
|
||||
/// Instruct the target about the input and run
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &I,
|
||||
) -> Result<ExitKind, Error>;
|
||||
}
|
||||
|
||||
@ -170,7 +167,7 @@ mod test {
|
||||
executors::{Executor, ExitKind},
|
||||
fuzzer::NopFuzzer,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
state::{HasExecutions, NopState, State, UsesState},
|
||||
state::{HasExecutions, NopState},
|
||||
};
|
||||
|
||||
/// A simple executor that does nothing.
|
||||
@ -196,25 +193,17 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> UsesState for NopExecutor<S>
|
||||
impl<EM, I, S, Z> Executor<EM, I, S, Z> for NopExecutor<S>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<EM, S, Z> Executor<EM, Z> for NopExecutor<S>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
S: State + HasExecutions,
|
||||
S::Input: HasTargetBytes,
|
||||
S: HasExecutions,
|
||||
I: HasTargetBytes,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &I,
|
||||
) -> Result<ExitKind, Error> {
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
@ -232,24 +221,14 @@ mod test {
|
||||
let nonempty_input = BytesInput::new(vec![1u8]);
|
||||
let mut executor = NopExecutor::new();
|
||||
let mut fuzzer = NopFuzzer::new();
|
||||
|
||||
let mut state = NopState::new();
|
||||
let mut mgr: NopEventManager<NopState<BytesInput>> = NopEventManager::new();
|
||||
let mut state: NopState<BytesInput> = NopState::new();
|
||||
|
||||
executor
|
||||
.run_target(
|
||||
&mut fuzzer,
|
||||
&mut state,
|
||||
&mut NopEventManager::new(),
|
||||
&empty_input,
|
||||
)
|
||||
.run_target(&mut fuzzer, &mut state, &mut mgr, &empty_input)
|
||||
.unwrap_err();
|
||||
executor
|
||||
.run_target(
|
||||
&mut fuzzer,
|
||||
&mut state,
|
||||
&mut NopEventManager::new(),
|
||||
&nonempty_input,
|
||||
)
|
||||
.run_target(&mut fuzzer, &mut state, &mut mgr, &nonempty_input)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use core::{
|
||||
fmt::{self, Debug, Formatter},
|
||||
marker::PhantomData,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
@ -9,22 +10,23 @@ use libafl_bolts::tuples::RefIndexable;
|
||||
|
||||
use super::HasTimeout;
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
state::UsesState,
|
||||
state::HasCorpus,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A [`ShadowExecutor`] wraps an executor and a set of shadow observers
|
||||
pub struct ShadowExecutor<E, SOT> {
|
||||
pub struct ShadowExecutor<E, S, SOT> {
|
||||
/// The wrapped executor
|
||||
executor: E,
|
||||
/// The shadow observers
|
||||
shadow_observers: SOT,
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<E, SOT> Debug for ShadowExecutor<E, SOT>
|
||||
impl<E, S, SOT> Debug for ShadowExecutor<E, S, SOT>
|
||||
where
|
||||
E: Debug,
|
||||
SOT: Debug,
|
||||
@ -37,16 +39,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, SOT> ShadowExecutor<E, SOT>
|
||||
impl<E, S, SOT> ShadowExecutor<E, S, SOT>
|
||||
where
|
||||
E: HasObservers + UsesState,
|
||||
SOT: ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State>,
|
||||
E: HasObservers,
|
||||
S: HasCorpus,
|
||||
SOT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
/// Create a new `ShadowExecutor`, wrapping the given `executor`.
|
||||
pub fn new(executor: E, shadow_observers: SOT) -> Self {
|
||||
Self {
|
||||
executor,
|
||||
shadow_observers,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,24 +67,25 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, EM, SOT, Z> Executor<EM, Z> for ShadowExecutor<E, SOT>
|
||||
impl<E, EM, S, SOT, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for ShadowExecutor<E, S, SOT>
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
SOT: ObserversTuple<Self::Input, Self::State>,
|
||||
EM: UsesState<State = Self::State>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
S: HasCorpus,
|
||||
SOT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.executor.run_target(fuzzer, state, mgr, input)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, SOT> HasTimeout for ShadowExecutor<E, SOT>
|
||||
impl<E, S, SOT> HasTimeout for ShadowExecutor<E, S, SOT>
|
||||
where
|
||||
E: HasTimeout,
|
||||
{
|
||||
@ -94,17 +99,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, SOT> UsesState for ShadowExecutor<E, SOT>
|
||||
impl<E, S, SOT> HasObservers for ShadowExecutor<E, S, SOT>
|
||||
where
|
||||
E: UsesState,
|
||||
{
|
||||
type State = E::State;
|
||||
}
|
||||
|
||||
impl<E, SOT> HasObservers for ShadowExecutor<E, SOT>
|
||||
where
|
||||
E: HasObservers + UsesState,
|
||||
SOT: ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State>,
|
||||
E: HasObservers,
|
||||
S: HasCorpus,
|
||||
SOT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
type Observers = E::Observers;
|
||||
#[inline]
|
||||
|
@ -1,51 +1,45 @@
|
||||
//! A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`].
|
||||
|
||||
use core::fmt::Debug;
|
||||
use core::{fmt::Debug, marker::PhantomData};
|
||||
|
||||
use libafl_bolts::tuples::RefIndexable;
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
inputs::UsesInput,
|
||||
observers::ObserversTuple,
|
||||
state::UsesState,
|
||||
state::HasCorpus,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`].
|
||||
#[derive(Debug)]
|
||||
pub struct WithObservers<E, OT> {
|
||||
pub struct WithObservers<E, OT, S> {
|
||||
executor: E,
|
||||
observers: OT,
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<E, EM, OT, Z> Executor<EM, Z> for WithObservers<E, OT>
|
||||
impl<E, EM, OT, S, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z> for WithObservers<E, OT, S>
|
||||
where
|
||||
E: Executor<EM, Z>,
|
||||
EM: UsesState<State = Self::State>,
|
||||
S: HasCorpus,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.executor.run_target(fuzzer, state, mgr, input)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, OT> UsesState for WithObservers<E, OT>
|
||||
impl<E, OT, S> HasObservers for WithObservers<E, OT, S>
|
||||
where
|
||||
E: UsesState,
|
||||
{
|
||||
type State = E::State;
|
||||
}
|
||||
|
||||
impl<E, OT> HasObservers for WithObservers<E, OT>
|
||||
where
|
||||
E: UsesState,
|
||||
OT: ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State>,
|
||||
S: HasCorpus,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
type Observers = OT;
|
||||
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||
@ -57,7 +51,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, OT> WithObservers<E, OT> {
|
||||
impl<E, OT, S> WithObservers<E, OT, S> {
|
||||
/// Wraps the given [`Executor`] with the given [`ObserversTuple`] to implement [`HasObservers`].
|
||||
///
|
||||
/// If the executor already implements [`HasObservers`], then the original implementation will be overshadowed by
|
||||
@ -66,6 +60,7 @@ impl<E, OT> WithObservers<E, OT> {
|
||||
Self {
|
||||
executor,
|
||||
observers,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -513,7 +513,7 @@ impl<CS, E, EM, F, IF, OF, S> EvaluatorObservers<E, EM, <S::Corpus as Corpus>::I
|
||||
for StdFuzzer<CS, F, IF, OF>
|
||||
where
|
||||
CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
E: HasObservers + Executor<EM, Self, State = S>,
|
||||
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Self>,
|
||||
E::Observers: MatchName + ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
|
||||
EM: EventFirer<State = S>,
|
||||
F: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
@ -591,7 +591,7 @@ impl<CS, E, EM, F, IF, OF, S> Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>
|
||||
for StdFuzzer<CS, F, IF, OF>
|
||||
where
|
||||
CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
E: HasObservers + Executor<EM, Self, State = S>,
|
||||
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Self>,
|
||||
E::Observers: MatchName + ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
|
||||
EM: EventFirer<State = S>,
|
||||
F: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
@ -748,7 +748,6 @@ where
|
||||
impl<CS, E, EM, F, IF, OF, S, ST> Fuzzer<E, EM, S, ST> for StdFuzzer<CS, F, IF, OF>
|
||||
where
|
||||
CS: Scheduler<S::Input, S>,
|
||||
E: UsesState<State = S>,
|
||||
EM: ProgressReporter + EventProcessor<E, Self, State = S>,
|
||||
S: HasExecutions
|
||||
+ HasMetadata
|
||||
@ -923,7 +922,7 @@ impl<CS, E, EM, F, IF, OF, S> ExecutesInput<E, EM, <S::Corpus as Corpus>::Input,
|
||||
for StdFuzzer<CS, F, IF, OF>
|
||||
where
|
||||
CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
E: Executor<EM, Self, State = S> + HasObservers,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Self> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: UsesState<State = S>,
|
||||
S: UsesInput<Input = <S::Corpus as Corpus>::Input>
|
||||
@ -977,7 +976,6 @@ impl Default for NopFuzzer {
|
||||
|
||||
impl<E, EM, S, ST> Fuzzer<E, EM, S, ST> for NopFuzzer
|
||||
where
|
||||
E: UsesState,
|
||||
EM: ProgressReporter<State = S> + EventProcessor<E, Self>,
|
||||
ST: StagesTuple<E, EM, S, Self>,
|
||||
S: HasMetadata + HasExecutions + HasLastReportTime + HasCurrentStageId + UsesInput,
|
||||
|
@ -88,7 +88,7 @@ const CAL_STAGE_MAX: usize = 8; // AFL++'s CAL_CYCLES + 1
|
||||
|
||||
impl<C, E, EM, O, OT, S, Z> Stage<E, EM, S, Z> for CalibrationStage<C, E, O, OT, S>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers<Observers = OT>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers<Observers = OT>,
|
||||
EM: EventFirer<State = S>,
|
||||
O: MapObserver,
|
||||
C: AsRef<O>,
|
||||
|
@ -22,7 +22,7 @@ use crate::{
|
||||
nonzero,
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
stages::{RetryCountRestartHelper, Stage},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasRand, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasRand},
|
||||
Error, HasMetadata, HasNamedMetadata,
|
||||
};
|
||||
|
||||
@ -68,10 +68,7 @@ pub struct ColorizationStage<C, E, EM, O, S, Z> {
|
||||
phantom: PhantomData<(E, EM, O, E, S, Z)>,
|
||||
}
|
||||
|
||||
impl<C, E, EM, O, S, Z> Named for ColorizationStage<C, E, EM, O, S, Z>
|
||||
where
|
||||
E: UsesState,
|
||||
{
|
||||
impl<C, E, EM, O, S, Z> Named for ColorizationStage<C, E, EM, O, S, Z> {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
@ -80,7 +77,7 @@ where
|
||||
impl<C, E, EM, O, S, Z> Stage<E, EM, S, Z> for ColorizationStage<C, E, EM, O, S, Z>
|
||||
where
|
||||
EM: EventFirer<State = S>,
|
||||
E: HasObservers + Executor<EM, Z, State = S>,
|
||||
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
S: HasCorpus
|
||||
+ HasMetadata
|
||||
+ HasRand
|
||||
@ -162,7 +159,7 @@ where
|
||||
EM: EventFirer<State = S>,
|
||||
O: MapObserver,
|
||||
C: AsRef<O> + Named,
|
||||
E: HasObservers + Executor<EM, Z, State = S>,
|
||||
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus
|
||||
+ HasMetadata
|
||||
|
@ -50,7 +50,7 @@ impl<EM, TE, S, Z> Named for ConcolicTracingStage<'_, EM, TE, S, Z> {
|
||||
|
||||
impl<E, EM, TE, S, Z> Stage<E, EM, S, Z> for ConcolicTracingStage<'_, EM, TE, S, Z>
|
||||
where
|
||||
TE: Executor<EM, Z, State = S> + HasObservers,
|
||||
TE: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
TE::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasExecutions
|
||||
+ HasCorpus
|
||||
|
@ -64,7 +64,7 @@ impl<C, E, EM, O, S, Z> Stage<E, EM, S, Z> for GeneralizationStage<C, EM, O, E::
|
||||
where
|
||||
O: MapObserver,
|
||||
C: CanTrack + AsRef<O> + Named,
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
E: Executor<EM, BytesInput, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<BytesInput, S>,
|
||||
S: HasExecutions
|
||||
+ HasMetadata
|
||||
@ -348,6 +348,7 @@ where
|
||||
+ HasCorpus
|
||||
+ MaybeHasClientPerfMonitor
|
||||
+ UsesInput<Input = BytesInput>,
|
||||
S::Corpus: Corpus<Input = BytesInput>,
|
||||
OT: ObserversTuple<BytesInput, S>,
|
||||
EM: UsesState<State = S>,
|
||||
{
|
||||
@ -375,7 +376,7 @@ where
|
||||
input: &BytesInput,
|
||||
) -> Result<bool, Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<BytesInput, S>,
|
||||
{
|
||||
start_timer!(state);
|
||||
@ -417,7 +418,7 @@ where
|
||||
split_char: u8,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers<Observers = OT>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers<Observers = OT>,
|
||||
{
|
||||
let mut start = 0;
|
||||
while start < payload.len() {
|
||||
@ -455,7 +456,7 @@ where
|
||||
closing_char: u8,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers<Observers = OT>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers<Observers = OT>,
|
||||
{
|
||||
let mut index = 0;
|
||||
while index < payload.len() {
|
||||
|
@ -79,7 +79,7 @@ where
|
||||
|
||||
impl<E, F, EM, I, M, S, Z> Stage<E, EM, S, Z> for PowerMutationalStage<E, F, EM, I, M, S, Z>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
EM: UsesState<State = S>,
|
||||
F: TestcaseScore<S>,
|
||||
M: Mutator<I, S>,
|
||||
@ -121,7 +121,7 @@ where
|
||||
|
||||
impl<E, F, EM, I, M, S, Z> PowerMutationalStage<E, F, EM, I, M, S, Z>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
EM: UsesState<State = S>,
|
||||
F: TestcaseScore<S>,
|
||||
I: Input,
|
||||
|
@ -256,7 +256,7 @@ where
|
||||
+ HasNamedMetadata
|
||||
+ HasMetadata
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
E: Executor<EM, Z, State = S> + HasObservers<Observers = OT>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers<Observers = OT>,
|
||||
EM: EventFirer<State = S> + EventRestarter + HasEventManagerId + ProgressReporter<State = S>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
PS: PushStage<EM, <S::Corpus as Corpus>::Input, OT, S, Z>,
|
||||
|
@ -243,7 +243,7 @@ where
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
|
||||
+ State,
|
||||
SP: ShMemProvider,
|
||||
E: HasObservers + Executor<EM, Z, State = S>,
|
||||
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
Z: EvaluatorObservers<E, EM, <S::Corpus as Corpus>::Input, S>
|
||||
+ ExecutionProcessor<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
|
@ -34,7 +34,7 @@ use crate::{
|
||||
start_timer,
|
||||
state::{
|
||||
HasCorpus, HasCurrentTestcase, HasExecutions, HasMaxSize, HasSolutions,
|
||||
MaybeHasClientPerfMonitor, State, UsesState,
|
||||
MaybeHasClientPerfMonitor, State,
|
||||
},
|
||||
Error, ExecutesInput, ExecutionProcessor, HasFeedback, HasMetadata, HasNamedMetadata,
|
||||
HasScheduler,
|
||||
@ -63,7 +63,7 @@ where
|
||||
+ ExecutesInput<E, EM, <S::Corpus as Corpus>::Input, S>
|
||||
+ HasFeedback,
|
||||
Z::Scheduler: RemovableScheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
E: HasObservers + UsesState<State = S>,
|
||||
E: HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
|
||||
EM: EventFirer<State = S>,
|
||||
FF: FeedbackFactory<F, E::Observers>,
|
||||
@ -134,7 +134,7 @@ where
|
||||
+ ExecutesInput<E, EM, <S::Corpus as Corpus>::Input, S>
|
||||
+ HasFeedback,
|
||||
Z::Scheduler: RemovableScheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
E: HasObservers + UsesState<State = S>,
|
||||
E: HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
|
||||
EM: EventFirer<State = S>,
|
||||
FF: FeedbackFactory<F, E::Observers>,
|
||||
|
@ -32,7 +32,7 @@ pub struct TracingStage<EM, TE, S, Z> {
|
||||
|
||||
impl<EM, TE, S, Z> TracingStage<EM, TE, S, Z>
|
||||
where
|
||||
TE: Executor<EM, Z, State = S> + HasObservers,
|
||||
TE: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
TE::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasExecutions
|
||||
+ HasCorpus
|
||||
@ -76,7 +76,7 @@ where
|
||||
|
||||
impl<E, EM, TE, S, Z> Stage<E, EM, S, Z> for TracingStage<EM, TE, S, Z>
|
||||
where
|
||||
TE: Executor<EM, Z, State = S> + HasObservers,
|
||||
TE: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
TE::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasExecutions
|
||||
+ HasCorpus
|
||||
@ -164,10 +164,10 @@ impl<E, EM, SOT, S, Z> Named for ShadowTracingStage<E, EM, SOT, S, Z> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, EM, SOT, S, Z> Stage<ShadowExecutor<E, SOT>, EM, S, Z>
|
||||
impl<E, EM, SOT, S, Z> Stage<ShadowExecutor<E, S, SOT>, EM, S, Z>
|
||||
for ShadowTracingStage<E, EM, SOT, S, Z>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
SOT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasExecutions
|
||||
@ -184,7 +184,7 @@ where
|
||||
fn perform(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
executor: &mut ShadowExecutor<E, SOT>,
|
||||
executor: &mut ShadowExecutor<E, S, SOT>,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
) -> Result<(), Error> {
|
||||
@ -227,13 +227,13 @@ where
|
||||
|
||||
impl<E, EM, SOT, S, Z> ShadowTracingStage<E, EM, SOT, S, Z>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
S: HasExecutions + HasCorpus + UsesInput,
|
||||
SOT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: UsesState<State = S>,
|
||||
{
|
||||
/// Creates a new default stage
|
||||
pub fn new(_executor: &mut ShadowExecutor<E, SOT>) -> Self {
|
||||
pub fn new(_executor: &mut ShadowExecutor<E, 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;
|
||||
|
@ -84,7 +84,7 @@ impl<I> TimeoutsToVerify<I> {
|
||||
impl<E, EM, S, Z> Stage<E, EM, S, Z> for VerifyTimeoutsStage<E, S>
|
||||
where
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
E: Executor<EM, Z, State = S> + HasObservers + HasTimeout,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers + HasTimeout,
|
||||
EM: UsesState<State = S>,
|
||||
Z: Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus + HasMetadata + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
|
@ -723,7 +723,6 @@ where
|
||||
load_config: LoadConfig<I, Self, Z>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -748,7 +747,6 @@ where
|
||||
config: &mut LoadConfig<I, Self, Z>,
|
||||
) -> Result<ExecuteInputResult, Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -783,7 +781,6 @@ where
|
||||
mut config: LoadConfig<I, Self, Z>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -848,7 +845,6 @@ where
|
||||
file_list: &[PathBuf],
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -876,7 +872,6 @@ where
|
||||
in_dirs: &[PathBuf],
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -903,7 +898,6 @@ where
|
||||
file_list: &[PathBuf],
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -929,7 +923,6 @@ where
|
||||
in_dirs: &[PathBuf],
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -956,7 +949,6 @@ where
|
||||
in_dirs: &[PathBuf],
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -998,7 +990,6 @@ where
|
||||
cores: &Cores,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
{
|
||||
@ -1093,7 +1084,6 @@ where
|
||||
forced: bool,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
G: Generator<<Self as UsesInput>::Input, Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
@ -1132,7 +1122,6 @@ where
|
||||
num: usize,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
G: Generator<<Self as UsesInput>::Input, Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
@ -1150,7 +1139,6 @@ where
|
||||
num: usize,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
E: UsesState<State = Self>,
|
||||
EM: EventFirer<State = Self>,
|
||||
G: Generator<<Self as UsesInput>::Input, Self>,
|
||||
Z: Evaluator<E, EM, I, Self>,
|
||||
@ -1280,6 +1268,18 @@ impl<I> HasMaxSize for NopState<I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> HasCorpus for NopState<I> {
|
||||
type Corpus = InMemoryCorpus<I>;
|
||||
|
||||
fn corpus(&self) -> &Self::Corpus {
|
||||
unimplemented!("Unimplemented for NopState!");
|
||||
}
|
||||
|
||||
fn corpus_mut(&mut self) -> &mut Self::Corpus {
|
||||
unimplemented!("Unimplemented for No[State!");
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> UsesInput for NopState<I>
|
||||
where
|
||||
I: Input,
|
||||
|
@ -3429,9 +3429,7 @@ where
|
||||
&broker_shmem_description,
|
||||
);
|
||||
}
|
||||
ListenerStream::Empty() => {
|
||||
continue;
|
||||
}
|
||||
ListenerStream::Empty() => {}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -702,7 +702,6 @@ where
|
||||
Ok(()) => (),
|
||||
Err(e) => {
|
||||
log::info!("Ignoring failed read from client {e:?} {poll_fd:?}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
@ -7,19 +7,20 @@ use frida_gum::{
|
||||
stalker::{NoneEventSink, Stalker},
|
||||
Gum, MemoryRange, NativePointer,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks},
|
||||
state::{HasCorpus, HasSolutions},
|
||||
};
|
||||
use libafl::{
|
||||
executors::{Executor, ExitKind, HasObservers, InProcessExecutor},
|
||||
inputs::{HasTargetBytes, NopTargetBytesConverter, TargetBytesConverter},
|
||||
inputs::{NopTargetBytesConverter, TargetBytesConverter, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasExecutions, State, UsesState},
|
||||
state::{HasCorpus, HasExecutions, UsesState},
|
||||
Error,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use libafl::{
|
||||
executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks},
|
||||
inputs::Input,
|
||||
state::{HasCurrentTestcase, HasSolutions},
|
||||
};
|
||||
use libafl_bolts::{tuples::RefIndexable, AsSlice};
|
||||
|
||||
#[cfg(not(test))]
|
||||
@ -29,14 +30,7 @@ use crate::helper::{FridaInstrumentationHelper, FridaRuntimeTuple};
|
||||
use crate::windows_hooks::initialize;
|
||||
|
||||
/// The [`FridaInProcessExecutor`] is an [`Executor`] that executes the target in the same process, usinig [`frida`](https://frida.re/) for binary-only instrumentation.
|
||||
pub struct FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
S: State,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
'b: 'a,
|
||||
{
|
||||
pub struct FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> {
|
||||
base: InProcessExecutor<'a, H, OT, S>,
|
||||
/// `thread_id` for the Stalker
|
||||
thread_id: Option<u32>,
|
||||
@ -51,10 +45,7 @@ where
|
||||
|
||||
impl<H, OT, RT, S, TC> Debug for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
OT: Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("FridaInProcessExecutor")
|
||||
@ -65,14 +56,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<EM, H, OT, RT, S, TC, Z> Executor<EM, Z>
|
||||
impl<EM, H, OT, RT, S, TC, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State + HasExecutions,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
H: FnMut(&<S::Corpus as Corpus>::Input) -> ExitKind,
|
||||
S: HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
TC: TargetBytesConverter<Input = <S::Corpus as Corpus>::Input>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
RT: FridaRuntimeTuple,
|
||||
{
|
||||
/// Instruct the target about the input and run
|
||||
@ -80,9 +71,9 @@ where
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
let target_bytes = self.target_bytes_converter.to_target_bytes(input);
|
||||
self.helper.pre_exec(target_bytes.as_slice())?;
|
||||
@ -122,23 +113,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, OT, RT, S, TC> UsesState for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<H, OT, RT, S, TC> HasObservers for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
S: State,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
{
|
||||
impl<H, OT, RT, S, TC> HasObservers for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> {
|
||||
type Observers = OT;
|
||||
#[inline]
|
||||
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||
@ -152,12 +127,18 @@ where
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c, H, OT, RT, S>
|
||||
FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, NopTargetBytesConverter<S::Input>>
|
||||
FridaInProcessExecutor<
|
||||
'a,
|
||||
'b,
|
||||
'c,
|
||||
H,
|
||||
OT,
|
||||
RT,
|
||||
S,
|
||||
NopTargetBytesConverter<<S::Corpus as Corpus>::Input>,
|
||||
>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State,
|
||||
S::Input: HasTargetBytes,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: HasCorpus,
|
||||
RT: FridaRuntimeTuple,
|
||||
{
|
||||
/// Creates a new [`FridaInProcessExecutor`].
|
||||
@ -194,10 +175,6 @@ where
|
||||
|
||||
impl<'a, 'b, 'c, H, OT, RT, S, TC> FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
RT: FridaRuntimeTuple,
|
||||
{
|
||||
/// Creates a new [`FridaInProcessExecutor`].
|
||||
@ -257,13 +234,17 @@ where
|
||||
impl<'a, 'b, 'c, H, OT, RT, S, TC> HasInProcessHooks<S>
|
||||
for FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State + HasSolutions + HasCorpus + HasExecutions,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
H: FnMut(&<S::Corpus as Corpus>::Input) -> ExitKind,
|
||||
S: HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
+ HasExecutions
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input,
|
||||
TC: TargetBytesConverter<Input = <S::Corpus as Corpus>::Input>,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
RT: FridaRuntimeTuple,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
/// the timeout handler
|
||||
#[inline]
|
||||
|
@ -70,7 +70,6 @@ where
|
||||
+ HasLastReportTime
|
||||
+ HasCurrentStageId
|
||||
+ Stoppable,
|
||||
E: UsesState<State = S>,
|
||||
EM: ProgressReporter<State = S> + EventProcessor<E, F>,
|
||||
ST: StagesTuple<E, EM, S, F>,
|
||||
{
|
||||
|
@ -158,13 +158,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, O> UsesState for MappedEdgeMapObserver<M, O>
|
||||
where
|
||||
M: UsesState,
|
||||
{
|
||||
type State = M::State;
|
||||
}
|
||||
|
||||
impl<M, O, S> Observer<S::Input, S> for MappedEdgeMapObserver<M, O>
|
||||
where
|
||||
M: Observer<S::Input, S> + Debug,
|
||||
|
@ -31,7 +31,7 @@ where
|
||||
+ HasLastReportTime
|
||||
+ HasCurrentStageId
|
||||
+ Stoppable,
|
||||
E: HasObservers + UsesState<State = S>,
|
||||
E: HasObservers,
|
||||
EM: ProgressReporter<State = S> + EventProcessor<E, F>,
|
||||
ST: StagesTuple<E, EM, S, F>,
|
||||
{
|
||||
|
@ -5,10 +5,11 @@ use std::{
|
||||
};
|
||||
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, ExitKind, HasObservers, HasTimeout},
|
||||
inputs::HasTargetBytes,
|
||||
inputs::{HasTargetBytes, UsesInput},
|
||||
observers::{ObserversTuple, StdOutObserver},
|
||||
state::{HasExecutions, State, UsesState},
|
||||
state::{HasCorpus, HasExecutions, UsesState},
|
||||
Error,
|
||||
};
|
||||
use libafl_bolts::{tuples::RefIndexable, AsSlice};
|
||||
@ -38,26 +39,19 @@ impl NyxExecutor<(), ()> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, OT> UsesState for NyxExecutor<S, OT>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<EM, S, Z, OT> Executor<EM, Z> for NyxExecutor<S, OT>
|
||||
impl<EM, S, Z, OT> Executor<EM, <S::Corpus as Corpus>::Input, S, Z> for NyxExecutor<S, OT>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
S: State + HasExecutions,
|
||||
S::Input: HasTargetBytes,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: HasTargetBytes,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
@ -205,11 +199,7 @@ impl NyxExecutorBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, OT> HasObservers for NyxExecutor<S, OT>
|
||||
where
|
||||
S: State,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
{
|
||||
impl<S, OT> HasObservers for NyxExecutor<S, OT> {
|
||||
type Observers = OT;
|
||||
|
||||
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||
|
@ -144,7 +144,7 @@ fn exec_rustc(args: &[&str]) -> String {
|
||||
|
||||
fn find_rustc_llvm_version() -> Option<i32> {
|
||||
let output = exec_rustc(&["--verbose", "--version"]);
|
||||
let ver = output.split(':').last().unwrap().trim();
|
||||
let ver = output.split(':').next_back().unwrap().trim();
|
||||
if let Some(major) = ver.split('.').collect::<Vec<&str>>().first() {
|
||||
if let Ok(res) = major.parse::<i32>() {
|
||||
return Some(res);
|
||||
|
@ -9,8 +9,6 @@ use std::ptr;
|
||||
#[cfg(feature = "systemmode")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[cfg(any(feature = "usermode", feature = "fork"))]
|
||||
use libafl::inputs::UsesInput;
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
@ -22,8 +20,9 @@ use libafl::{
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::{Input, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions, State, UsesState},
|
||||
Error, ExecutionProcessor, HasScheduler,
|
||||
};
|
||||
#[cfg(feature = "fork")]
|
||||
@ -94,16 +93,20 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, OF, S, Z>(
|
||||
context: Option<&mut ucontext_t>,
|
||||
data: &mut InProcessExecutorHandlerData,
|
||||
) where
|
||||
E: HasObservers + HasInProcessHooks<E::State> + Executor<EM, Z>,
|
||||
E::Observers: ObserversTuple<E::Input, E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
E: HasObservers + HasInProcessHooks<S> + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ Unpin
|
||||
+ HasCurrentTestcase
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
S: State + Unpin,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
#[cfg(feature = "systemmode")]
|
||||
{
|
||||
@ -114,6 +117,7 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, OF, S, Z>(
|
||||
E,
|
||||
EM,
|
||||
OF,
|
||||
S,
|
||||
Z,
|
||||
>(signal, info, context, data);
|
||||
}
|
||||
@ -126,9 +130,13 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, OF, S, Z>(
|
||||
emulator_modules.modules_mut().on_timeout_all();
|
||||
}
|
||||
|
||||
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<E, EM, OF, Z>(
|
||||
signal, info, context, data,
|
||||
);
|
||||
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<
|
||||
E,
|
||||
EM,
|
||||
OF,
|
||||
S,
|
||||
Z,
|
||||
>(signal, info, context, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,9 +159,16 @@ impl<'a, CM, ED, ET, H, OT, S, SM> QemuExecutor<'a, CM, ED, ET, H, OT, S, SM>
|
||||
where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &mut S, &S::Input) -> ExitKind,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &mut S, &<S::Corpus as Corpus>::Input) -> ExitKind,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus
|
||||
+ Unpin
|
||||
+ HasExecutions
|
||||
+ HasSolutions
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
|
||||
+ State,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: Input,
|
||||
{
|
||||
pub fn new<EM, OF, Z>(
|
||||
emulator: Emulator<CM, ED, ET, S, SM>,
|
||||
@ -168,13 +183,9 @@ where
|
||||
ED: EmulatorDriver<CM, ET, S, SM>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
|
||||
S::Corpus: Corpus<Input = S::Input>,
|
||||
Z: HasObjective<Objective = OF>
|
||||
+ HasScheduler<<S::Corpus as Corpus>::Input, S>
|
||||
+ ExecutionProcessor<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
S::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
<S::Corpus as Corpus>::Input: Clone, //delete me
|
||||
{
|
||||
let mut inner = StatefulInProcessExecutor::with_timeout(
|
||||
harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout,
|
||||
@ -188,7 +199,8 @@ where
|
||||
let handler = |qemu: Qemu, _emulator_modules: &mut EmulatorModules<ET, S>, host_sig| {
|
||||
eprintln!("Crashed with signal {host_sig}");
|
||||
unsafe {
|
||||
libafl::executors::inprocess::generic_inproc_crash_handler::<Self, EM, OF, Z>();
|
||||
libafl::executors::inprocess::generic_inproc_crash_handler::<Self, EM, OF, S, Z>(
|
||||
);
|
||||
}
|
||||
if let Some(cpu) = qemu.current_cpu() {
|
||||
eprint!("Context:\n{}", cpu.display_context());
|
||||
@ -236,22 +248,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<CM, ED, EM, ET, H, OT, S, SM, Z> Executor<EM, Z> for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM>
|
||||
impl<CM, ED, EM, ET, H, OT, S, SM, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM>
|
||||
where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
ED: EmulatorDriver<CM, ET, S, SM>,
|
||||
EM: UsesState<State = S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &mut S, &S::Input) -> ExitKind,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State + HasExecutions + Unpin,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &mut S, &<S::Corpus as Corpus>::Input) -> ExitKind,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: State + HasExecutions + Unpin + HasCorpus + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
if self.first_exec {
|
||||
self.inner.exposed_executor_state_mut().first_exec(state);
|
||||
@ -275,24 +288,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<CM, ED, ET, H, OT, S, SM> UsesState for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM>
|
||||
where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &mut S, &S::Input) -> ExitKind,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<CM, ED, ET, H, OT, S, SM> HasObservers for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM>
|
||||
where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &mut S, &S::Input) -> ExitKind,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &mut S, &<S::Corpus as Corpus>::Input) -> ExitKind,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: State + HasCorpus + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
{
|
||||
type Observers = OT;
|
||||
#[inline]
|
||||
@ -314,7 +316,7 @@ pub struct QemuForkExecutor<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z>
|
||||
where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: UsesInput,
|
||||
SP: ShMemProvider,
|
||||
@ -330,7 +332,7 @@ where
|
||||
EM: UsesState<State = S>,
|
||||
ED: Debug,
|
||||
ET: EmulatorModuleTuple<S> + Debug,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + Sized,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
S: UsesInput + Debug,
|
||||
SM: Debug,
|
||||
@ -351,12 +353,12 @@ where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State + HasSolutions,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &<S::Corpus as Corpus>::Input) -> ExitKind + Sized,
|
||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: State + HasSolutions + HasCorpus + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
SP: ShMemProvider,
|
||||
Z: HasObjective,
|
||||
Z::Objective: Feedback<EM, S::Input, OT, S>,
|
||||
Z::Objective: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
|
||||
{
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
@ -405,7 +407,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "fork")]
|
||||
impl<CM, ED, EM, ET, H, OF, OT, S, SM, SP, Z> Executor<EM, Z>
|
||||
impl<CM, ED, EM, ET, H, OF, OT, S, SM, SP, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for QemuForkExecutor<'_, CM, ED, EM, ET, H, OT, S, SM, SP, Z>
|
||||
where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
@ -415,16 +417,16 @@ where
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind,
|
||||
OF: Feedback<EM, S::Input, OT, S>,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
S: State + HasExecutions + Unpin,
|
||||
S: State + HasExecutions + Unpin + HasCorpus + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
SP: ShMemProvider,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.inner.exposed_executor_state.first_exec(state);
|
||||
|
||||
@ -449,7 +451,7 @@ impl<CM, ED, EM, ET, H, OT, S, SM, SP, Z> UsesState
|
||||
where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
SP: ShMemProvider,
|
||||
@ -464,7 +466,7 @@ where
|
||||
CM: CommandManager<ED, ET, S, SM>,
|
||||
EM: UsesState<State = S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut Emulator<CM, ED, ET, S, SM>, &S::Input) -> ExitKind + Sized,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
SP: ShMemProvider,
|
||||
|
@ -1,10 +1,7 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use libafl::{
|
||||
executors::{hooks::ExecutorHook, HasObservers},
|
||||
inputs::UsesInput,
|
||||
};
|
||||
use libafl::executors::hooks::ExecutorHook;
|
||||
use once_cell::sync::Lazy;
|
||||
/// The list of functions that this execution has observed
|
||||
pub static mut FUNCTION_LIST: Lazy<HashMap<usize, usize>> = Lazy::new(HashMap::new);
|
||||
@ -22,11 +19,11 @@ pub unsafe extern "C" fn __libafl_target_call_hook(id: usize) {
|
||||
|
||||
/// The empty struct to clear the `FUNCTION_LIST` before the execution
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct CallHook<S> {
|
||||
phantom: PhantomData<S>,
|
||||
pub struct CallHook<I, S> {
|
||||
phantom: PhantomData<(I, S)>,
|
||||
}
|
||||
|
||||
impl<S> CallHook<S> {
|
||||
impl<I, S> CallHook<I, S> {
|
||||
/// The constructor
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
@ -36,13 +33,10 @@ impl<S> CallHook<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> ExecutorHook<S> for CallHook<S>
|
||||
where
|
||||
S: UsesInput,
|
||||
{
|
||||
fn init<E: HasObservers>(&mut self, _state: &mut S) {}
|
||||
impl<I, S> ExecutorHook<I, S> for CallHook<I, S> {
|
||||
fn init(&mut self, _state: &mut S) {}
|
||||
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) {
|
||||
// clear it before the execution
|
||||
// # Safety
|
||||
// This typically happens while no other execution happens.
|
||||
@ -54,5 +48,5 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {}
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &I) {}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ impl<EM, TE, S, Z> Named for AFLppCmplogTracingStage<'_, EM, TE, S, Z> {
|
||||
impl<E, EM, TE, S, Z> Stage<E, EM, S, Z> for AFLppCmplogTracingStage<'_, EM, TE, S, Z>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
TE: HasObservers + Executor<EM, Z, State = S>,
|
||||
TE: HasObservers + Executor<EM, BytesInput, S, Z>,
|
||||
TE::Observers: MatchNameRef + ObserversTuple<BytesInput, S>,
|
||||
S: HasCorpus
|
||||
+ HasCurrentTestcase
|
||||
|
@ -10,7 +10,7 @@ use core::{mem::align_of, slice};
|
||||
feature = "sancov_ctx",
|
||||
feature = "sancov_ngram8"
|
||||
))]
|
||||
use libafl::executors::{hooks::ExecutorHook, HasObservers};
|
||||
use libafl::executors::hooks::ExecutorHook;
|
||||
|
||||
#[cfg(any(
|
||||
feature = "pointer_maps",
|
||||
@ -80,25 +80,19 @@ use core::marker::PhantomData;
|
||||
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))]
|
||||
#[rustversion::nightly]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct NgramHook<S>
|
||||
where
|
||||
S: libafl::inputs::UsesInput,
|
||||
{
|
||||
phantom: PhantomData<S>,
|
||||
pub struct NgramHook<I, S> {
|
||||
phantom: PhantomData<(I, S)>,
|
||||
}
|
||||
|
||||
/// The hook to initialize ctx everytime we run the harness
|
||||
#[cfg(feature = "sancov_ctx")]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CtxHook<S> {
|
||||
phantom: PhantomData<S>,
|
||||
pub struct CtxHook<I, S> {
|
||||
phantom: PhantomData<(I, S)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "sancov_ctx")]
|
||||
impl<S> CtxHook<S>
|
||||
where
|
||||
S: libafl::inputs::UsesInput,
|
||||
{
|
||||
impl<I, S> CtxHook<I, S> {
|
||||
/// The constructor for this struct
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
@ -109,10 +103,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "sancov_ctx")]
|
||||
impl<S> Default for CtxHook<S>
|
||||
where
|
||||
S: libafl::inputs::UsesInput,
|
||||
{
|
||||
impl<I, S> Default for CtxHook<I, S> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
@ -120,12 +111,9 @@ where
|
||||
|
||||
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))]
|
||||
#[rustversion::nightly]
|
||||
impl<S> ExecutorHook<S> for NgramHook<S>
|
||||
where
|
||||
S: libafl::inputs::UsesInput,
|
||||
{
|
||||
fn init<E: HasObservers>(&mut self, _state: &mut S) {}
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) {
|
||||
impl<I, S> ExecutorHook<I, S> for NgramHook<I, S> {
|
||||
fn init(&mut self, _state: &mut S) {}
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) {
|
||||
#[cfg(feature = "sancov_ngram4")]
|
||||
unsafe {
|
||||
PREV_ARRAY_4 = Ngram4::from_array([0, 0, 0, 0]);
|
||||
@ -136,15 +124,12 @@ where
|
||||
PREV_ARRAY_8 = Ngram8::from_array([0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
}
|
||||
}
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {}
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &I) {}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))]
|
||||
#[rustversion::nightly]
|
||||
impl<S> NgramHook<S>
|
||||
where
|
||||
S: libafl::inputs::UsesInput,
|
||||
{
|
||||
impl<I, S> NgramHook<I, S> {
|
||||
/// The constructor for this struct
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
@ -156,27 +141,21 @@ where
|
||||
|
||||
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))]
|
||||
#[rustversion::nightly]
|
||||
impl<S> Default for NgramHook<S>
|
||||
where
|
||||
S: libafl::inputs::UsesInput,
|
||||
{
|
||||
impl<I, S> Default for NgramHook<I, S> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sancov_ctx")]
|
||||
impl<S> ExecutorHook<S> for CtxHook<S>
|
||||
where
|
||||
S: libafl::inputs::UsesInput,
|
||||
{
|
||||
fn init<E: HasObservers>(&mut self, _state: &mut S) {}
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) {
|
||||
impl<I, S> ExecutorHook<I, S> for CtxHook<I, S> {
|
||||
fn init(&mut self, _state: &mut S) {}
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) {
|
||||
unsafe {
|
||||
__afl_prev_ctx = 0;
|
||||
}
|
||||
}
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {}
|
||||
fn post_exec(&mut self, _state: &mut S, _input: &I) {}
|
||||
}
|
||||
|
||||
#[rustversion::nightly]
|
||||
|
@ -5,9 +5,9 @@ use libafl::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{hooks::windows::windows_asan_handler::asan_death_handler, Executor, HasObservers},
|
||||
feedbacks::Feedback,
|
||||
inputs::UsesInput,
|
||||
inputs::{Input, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
HasObjective,
|
||||
};
|
||||
|
||||
@ -30,16 +30,20 @@ extern "C" {
|
||||
///
|
||||
/// # Safety
|
||||
/// Calls the unsafe `__sanitizer_set_death_callback` symbol, but should be safe to call otherwise.
|
||||
pub unsafe fn setup_asan_callback<E, EM, OF, Z>(_executor: &E, _event_mgr: &EM, _fuzzer: &Z)
|
||||
pub unsafe fn setup_asan_callback<E, EM, OF, S, Z>(_executor: &E, _event_mgr: &EM, _fuzzer: &Z)
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||
E::State: HasSolutions + HasCorpus + HasExecutions,
|
||||
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
|
||||
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
|
||||
S: HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCurrentTestcase
|
||||
+ HasCorpus
|
||||
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||
<S::Corpus as Corpus>::Input: Input + Clone,
|
||||
{
|
||||
__sanitizer_set_death_callback(Some(asan_death_handler::<E, EM, OF, Z>));
|
||||
__sanitizer_set_death_callback(Some(asan_death_handler::<E, EM, OF, S, Z>));
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
use core::{marker::PhantomData, ptr, time::Duration};
|
||||
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
inputs::HasTargetBytes,
|
||||
observers::ObserversTuple,
|
||||
state::{HasExecutions, State, UsesState},
|
||||
inputs::{HasTargetBytes, UsesInput},
|
||||
state::{HasCorpus, HasExecutions, UsesState},
|
||||
Error,
|
||||
};
|
||||
use libafl_bolts::{
|
||||
@ -48,20 +48,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<EM, S, SP, OT, Z> Executor<EM, Z> for TinyInstExecutor<S, SP, OT>
|
||||
impl<EM, S, SP, OT, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z>
|
||||
for TinyInstExecutor<S, SP, OT>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
S: State + HasExecutions,
|
||||
S::Input: HasTargetBytes,
|
||||
S: HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
|
||||
<S::Corpus as Corpus>::Input: HasTargetBytes,
|
||||
SP: ShMemProvider,
|
||||
{
|
||||
#[inline]
|
||||
fn run_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
input: &<S::Corpus as Corpus>::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
*state.executions_mut() += 1;
|
||||
match &self.map {
|
||||
@ -317,9 +318,7 @@ where
|
||||
|
||||
impl<S, SP, OT> HasObservers for TinyInstExecutor<S, SP, OT>
|
||||
where
|
||||
S: State,
|
||||
SP: ShMemProvider,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
{
|
||||
type Observers = OT;
|
||||
|
||||
@ -331,10 +330,3 @@ where
|
||||
RefIndexable::from(&mut self.observers)
|
||||
}
|
||||
}
|
||||
impl<S, SP, OT> UsesState for TinyInstExecutor<S, SP, OT>
|
||||
where
|
||||
S: State,
|
||||
SP: ShMemProvider,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user