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:
Dongjia "toka" Zhang 2025-01-11 15:25:15 +01:00 committed by GitHub
parent ca647f0c30
commit aa0391ef8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
56 changed files with 851 additions and 1167 deletions

View File

@ -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;

View File

@ -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"] }

View File

@ -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());

View File

@ -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()];

View File

@ -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;

View File

@ -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();

View File

@ -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,

View File

@ -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>,

View File

@ -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>,

View File

@ -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>,

View File

@ -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>,

View File

@ -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,

View File

@ -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}");
}));

View File

@ -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>;

View File

@ -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 {

View File

@ -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))]

View File

@ -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,
})
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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,

View File

@ -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,

View File

@ -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> {

View File

@ -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,

View File

@ -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]

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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]

View File

@ -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,
}
}
}

View File

@ -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,

View File

@ -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>,

View File

@ -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

View File

@ -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

View File

@ -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() {

View File

@ -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,

View File

@ -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>,

View File

@ -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>,

View File

@ -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>,

View File

@ -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;

View File

@ -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>,

View File

@ -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,

View File

@ -3429,9 +3429,7 @@ where
&broker_shmem_description,
);
}
ListenerStream::Empty() => {
continue;
}
ListenerStream::Empty() => {}
};
}
});

View File

@ -702,7 +702,6 @@ where
Ok(()) => (),
Err(e) => {
log::info!("Ignoring failed read from client {e:?} {poll_fd:?}");
continue;
}
};
} else {

View File

@ -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]

View File

@ -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>,
{

View File

@ -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,

View File

@ -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>,
{

View File

@ -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> {

View File

@ -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);

View File

@ -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,

View File

@ -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) {}
}

View File

@ -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

View File

@ -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]

View File

@ -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>));
}

View File

@ -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;
}