No uses for EventManager (#2831)

* the first step of the last step

* wip

* 99% done

* 99.9% done

* 99.99

* Hello from windows

* aaa

* 99.999

* aa

* 1

* 2

* 3

* 4

* 5

* plz

* plzplzplz

---------

Co-authored-by: Your Name <you@example.com>
This commit is contained in:
Dongjia "toka" Zhang 2025-01-15 16:56:40 +01:00 committed by GitHub
parent ba09cb0706
commit 435ca021cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
77 changed files with 1310 additions and 1824 deletions

View File

@ -11,6 +11,10 @@
- Related: `EmulatorBuilder` uses a single function to provide a `Qemu` initializer: `EmulatorBuilder::qemu_parameters`. For now, it can be either a `Vec<String>` or a `QemuConfig` instance.
- Related: Qemu's `AsanModule` does not need any special call to `Qemu` init methods anymore. It is now possible to simply initialize `AsanModule` (or `AsanGuestModule`) with a reference to the environment as parameter.
- `CustomBufHandlers` has been deleted. Please use `EventManagerHooksTuple` from now on.
- The `UsesState` and `UsesInput` traits have been removed in favor of regular Generics.
- For the structs/traits that used to use `UsesState`, we bring back the generic for the state.
- For `UsesState`, you can access to the input type through `HasCorpus` and `Corpus` traits
# 0.14.0 -> 0.14.1
- Removed `with_observers` from `Executor` trait.
- `MmapShMemProvider::new_shmem_persistent` has been removed in favour of `MmapShMem::persist`. You probably want to do something like this: `let shmem = MmapShMemProvider::new()?.new_shmem(size)?.persist()?;`

View File

@ -14,12 +14,12 @@ use libafl::{
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{HasTargetBytes, UsesInput},
inputs::HasTargetBytes,
mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator},
observers::StdMapObserver,
schedulers::QueueScheduler,
stages::{mutational::StdMutationalStage, AflStatsStage, CalibrationStage},
state::{HasCorpus, HasExecutions, StdState, UsesState},
state::{HasCorpus, HasExecutions, StdState},
};
use libafl_bolts::{current_nanos, nonzero, rands::StdRand, tuples::tuple_list, AsSlice};
@ -49,8 +49,7 @@ impl<S> CustomExecutor<S> {
impl<EM, S, Z> Executor<EM, <S::Corpus as Corpus>::Input, S, Z> for CustomExecutor<S>
where
EM: UsesState<State = S>,
S: HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasCorpus + HasExecutions,
<S::Corpus as Corpus>::Input: HasTargetBytes,
{
fn run_target(

View File

@ -7,7 +7,7 @@ use std::{env, fmt::Write, io, path::PathBuf, process, ptr::NonNull};
use clap::{builder::Str, Parser};
use libafl::{
corpus::{Corpus, InMemoryOnDiskCorpus, NopCorpus},
events::{EventRestarter, SimpleRestartingEventManager},
events::{EventRestarter, ManagerExit, SimpleRestartingEventManager},
executors::ExitKind,
feedbacks::MaxMapFeedback,
fuzzer::StdFuzzer,

View File

@ -10,7 +10,7 @@ use libafl::{
corpus::{Corpus, InMemoryCorpus},
events::{
launcher::Launcher, ClientDescription, EventConfig, EventRestarter,
LlmpRestartingEventManager,
LlmpRestartingEventManager, ManagerExit,
},
executors::ExitKind,
fuzzer::StdFuzzer,

View File

@ -8,8 +8,7 @@ use std::{
use libafl::{
corpus::Corpus,
executors::{Executor, ExitKind, HasObservers, HasTimeout},
inputs::UsesInput,
state::{HasCorpus, UsesState},
state::HasCorpus,
Error,
};
use libafl_bolts::tuples::RefIndexable;
@ -263,7 +262,7 @@ pub enum 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: HasCorpus + UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasCorpus,
EM: UsesState<State = S>,
NYX: Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
FSV: Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
@ -340,8 +339,7 @@ pub enum 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: HasCorpus + UsesInput<Input = <S::Corpus as Corpus>::Input>,
EM: UsesState<State = S>,
S: HasCorpus,
FSV: Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
{
fn run_target(
@ -349,7 +347,7 @@ where
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),

View File

@ -22,7 +22,7 @@ use libafl::{
CaptureTimeoutFeedback, ConstFeedback, CrashFeedback, MaxMapFeedback, TimeFeedback,
},
fuzzer::StdFuzzer,
inputs::{BytesInput, NopTargetBytesConverter, UsesInput},
inputs::{BytesInput, NopTargetBytesConverter},
mutators::{havoc_mutations, tokens_mutations, AFLppRedQueen, StdScheduledMutator, Tokens},
observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{
@ -83,7 +83,7 @@ type LibaflFuzzManager = CentralizedEventManager<
StdShMemProvider,
>;
#[cfg(feature = "fuzzbench")]
type LibaflFuzzManager<F> = SimpleEventManager<SimpleMonitor<F>, LibaflFuzzState>;
type LibaflFuzzManager<F> = SimpleEventManager<BytesInput, SimpleMonitor<F>, LibaflFuzzState>;
macro_rules! define_run_client {
($state: ident, $mgr: ident, $fuzzer_dir: ident, $core_id: ident, $opt:ident, $is_main_node: ident, $body:block) => {
@ -658,9 +658,9 @@ pub fn run_fuzzer_with_stages<E, EM, S, ST, Z>(
) -> Result<(), Error>
where
Z: Fuzzer<E, EM, S, ST>,
EM: ProgressReporter<State = S>,
EM: ProgressReporter<S>,
ST: StagesTuple<E, EM, S, Z>,
S: HasLastReportTime + HasExecutions + HasMetadata + UsesInput,
S: HasLastReportTime + HasExecutions + HasMetadata,
{
if opt.bench_just_one {
fuzzer.fuzz_loop_for(stages, executor, state, mgr, 1)?;

View File

@ -1,6 +1,7 @@
use libafl::{
corpus::Corpus,
events::{Event, EventManagerHook},
state::{State, Stoppable},
state::{HasCorpus, Stoppable},
Error,
};
use libafl_bolts::ClientId;
@ -10,15 +11,15 @@ pub struct LibAflFuzzEventHook {
exit_on_solution: bool,
}
impl<S> EventManagerHook<S> for LibAflFuzzEventHook
impl<S> EventManagerHook<<S::Corpus as Corpus>::Input, S> for LibAflFuzzEventHook
where
S: State + Stoppable,
S: HasCorpus + Stoppable,
{
fn pre_exec(
&mut self,
state: &mut S,
_client_id: ClientId,
event: &Event<S::Input>,
event: &Event<<S::Corpus as Corpus>::Input>,
) -> Result<bool, Error> {
if self.exit_on_solution && matches!(event, Event::Objective { .. }) {
// TODO: dump state

View File

@ -4,7 +4,7 @@ use core::time::Duration;
use std::{env, path::PathBuf, process};
#[cfg(not(feature = "nyx"))]
use libafl::state::{HasExecutions, State};
use libafl::state::HasExecutions;
use libafl::{
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
events::{launcher::Launcher, EventConfig},
@ -80,7 +80,7 @@ fn get_emulator<C, ET, I, S>(
where
ET: EmulatorModuleTuple<I, S>,
I: HasTargetBytes + Unpin,
S: State + HasExecutions + Unpin,
S: HasExecutions + Unpin,
{
// Allow linux process address space addresses as feedback
modules.allow_address_range_all(LINUX_PROCESS_ADDRESS_RANGE);

View File

@ -4,7 +4,7 @@ use core::time::Duration;
use std::{env, path::PathBuf, process};
#[cfg(not(feature = "nyx"))]
use libafl::state::{HasExecutions, State};
use libafl::state::HasExecutions;
use libafl::{
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
events::{launcher::Launcher, EventConfig},
@ -80,7 +80,7 @@ fn get_emulator<C, ET, I, S>(
where
ET: EmulatorModuleTuple<I, S>,
I: HasTargetBytes + Unpin,
S: State + HasExecutions + Unpin,
S: HasExecutions + Unpin,
{
// Allow linux process address space addresses as feedback
modules.allow_address_range_all(LINUX_PROCESS_ADDRESS_RANGE);

View File

@ -30,7 +30,6 @@ libafl = { path = "../../../libafl", features = [
"prelude",
"gzip",
"regex",
"scalability_introspection",
] }
libafl_bolts = { path = "../../../libafl_bolts", features = [
"errors_backtrace",

View File

@ -7,7 +7,10 @@ use std::{env, path::PathBuf};
use libafl::{
corpus::{minimizer::StdCorpusMinimizer, Corpus, InMemoryCorpus, OnDiskCorpus},
events::{setup_restarting_mgr_std, EventConfig, EventFirer, EventRestarter, LogSeverity},
events::{
setup_restarting_mgr_std, EventConfig, EventFirer, EventRestarter,
LlmpRestartingEventManager, LogSeverity,
},
executors::{inprocess::InProcessExecutor, ExitKind},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
@ -216,10 +219,20 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let orig_size = state.corpus().count();
let msg = "Started distillation...".to_string();
restarting_mgr.log(&mut state, LogSeverity::Info, msg)?;
<LlmpRestartingEventManager<_, _, _> as EventFirer<BytesInput, _>>::log(
&mut restarting_mgr,
&mut state,
LogSeverity::Info,
msg,
)?;
minimizer.minimize(&mut fuzzer, &mut executor, &mut restarting_mgr, &mut state)?;
let msg = format!("Distilled out {} cases", orig_size - state.corpus().count());
restarting_mgr.log(&mut state, LogSeverity::Info, msg)?;
<LlmpRestartingEventManager<_, _, _> as EventFirer<BytesInput, _>>::log(
&mut restarting_mgr,
&mut state,
LogSeverity::Info,
msg,
)?;
// It's important, that we store the state before restarting!
// Else, the parent will not respawn a new child and quit.

View File

@ -43,7 +43,6 @@ libafl = { path = "../../../libafl", default-features = false, features = [
"prelude",
"gzip",
"regex",
"scalability_introspection",
"multi_machine",
"errors_backtrace",
] }

View File

@ -71,9 +71,6 @@ value_bloom_feedback = ["fastbloom", "fastbloom/serde"]
## Collects performance statistics of the fuzzing pipeline and displays it on `Monitor` components
introspection = []
## Collects stats about scalability
scalability_introspection = []
## Expose `libafl::prelude` for access without additional using directives
prelude = ["libafl_bolts/prelude"]

View File

@ -17,7 +17,7 @@ use crate::{
corpus::Corpus,
events::{Event, EventFirer, LogSeverity},
executors::{Executor, HasObservers},
inputs::{Input, UsesInput},
inputs::Input,
monitors::{AggregatorOps, UserStats, UserStatsValue},
observers::{MapObserver, ObserversTuple},
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
@ -56,7 +56,7 @@ impl<C, E, O, S, T, TS> MapCorpusMinimizer<C, E, O, S, T, TS>
where
for<'a> O: MapObserver<Entry = T> + AsIter<'a, Item = T>,
C: AsRef<O>,
S: HasMetadata + HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasMetadata + HasCorpus + HasExecutions,
<S::Corpus as Corpus>::Input: Input,
T: Copy + Hash + Eq,
TS: TestcaseScore<S>,
@ -75,7 +75,7 @@ where
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>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
Z: HasScheduler<<S::Corpus as Corpus>::Input, S, Scheduler = CS>,
{
// don't delete this else it won't work after restart

View File

@ -8,13 +8,11 @@ use libafl_bolts::{
shmem::ShMemProvider,
ClientId, Error,
};
use serde::de::DeserializeOwned;
#[cfg(feature = "llmp_compression")]
use crate::events::COMPRESS_THRESHOLD;
use crate::{
events::{BrokerEventResult, Event, _LLMP_TAG_TO_MAIN},
inputs::Input,
};
use crate::events::{BrokerEventResult, Event, _LLMP_TAG_TO_MAIN};
/// An LLMP-backed event manager for scalable multi-processed fuzzing
pub struct CentralizedLlmpHook<I> {
@ -25,7 +23,7 @@ pub struct CentralizedLlmpHook<I> {
impl<I, SP> LlmpHook<SP> for CentralizedLlmpHook<I>
where
I: Input,
I: DeserializeOwned,
SP: ShMemProvider,
{
fn on_new_message(
@ -75,10 +73,7 @@ impl<I> Debug for CentralizedLlmpHook<I> {
}
}
impl<I> CentralizedLlmpHook<I>
where
I: Input,
{
impl<I> CentralizedLlmpHook<I> {
/// Create an event broker from a raw broker.
pub fn new() -> Result<Self, Error> {
Ok(Self {

View File

@ -14,6 +14,7 @@ use libafl_bolts::{
shmem::ShMemProvider,
ClientId, Error,
};
use serde::Serialize;
use tokio::{
net::ToSocketAddrs,
runtime::Runtime,
@ -70,10 +71,7 @@ impl<T> NullLock<T> {
/// It is responsible for receiving messages from other neighbours.
/// Please check [`crate::events::multi_machine`] for more information.
#[derive(Debug)]
pub struct TcpMultiMachineLlmpSenderHook<A, I>
where
I: Input,
{
pub struct TcpMultiMachineLlmpSenderHook<A, I> {
/// the actual state of the broker hook
shared_state: Arc<RwLock<TcpMultiMachineState<A>>>,
/// the tokio runtime used to interact with other machines. Keep it outside to avoid locking it.
@ -85,10 +83,7 @@ where
/// It is responsible for receiving messages from other neighbours.
/// Please check [`crate::events::multi_machine`] for more information.
#[derive(Debug)]
pub struct TcpMultiMachineLlmpReceiverHook<A, I>
where
I: Input,
{
pub struct TcpMultiMachineLlmpReceiverHook<A, I> {
/// the actual state of the broker hook
shared_state: Arc<RwLock<TcpMultiMachineState<A>>>,
/// the tokio runtime used to interact with other machines. Keep it outside to avoid locking it.
@ -96,11 +91,7 @@ where
phantom: PhantomData<I>,
}
impl<A, I> TcpMultiMachineLlmpSenderHook<A, I>
where
A: Clone + Display + ToSocketAddrs + Send + Sync + 'static,
I: Input + Send + Sync + 'static,
{
impl<A, I> TcpMultiMachineLlmpSenderHook<A, I> {
/// Should not be created alone. Use [`TcpMultiMachineHooksBuilder`] instead.
pub(crate) fn new(
shared_state: Arc<RwLock<TcpMultiMachineState<A>>>,
@ -117,7 +108,7 @@ where
impl<A, I> TcpMultiMachineLlmpReceiverHook<A, I>
where
A: Clone + Display + ToSocketAddrs + Send + Sync + 'static,
I: Input + Send + Sync + 'static,
I: Serialize,
{
/// Should not be created alone. Use [`TcpMultiMachineHooksBuilder`] instead.
///
@ -160,9 +151,9 @@ where
impl<A, I, SP> LlmpHook<SP> for TcpMultiMachineLlmpSenderHook<A, I>
where
A: Clone + Debug + Display + ToSocketAddrs + Send + Sync + 'static,
I: Input,
A: Clone + Display + ToSocketAddrs + Send + Sync + 'static,
SP: ShMemProvider,
I: Input + Send + Sync + 'static,
{
/// check for received messages, and forward them alongside the incoming message to inner.
fn on_new_message(
@ -222,9 +213,9 @@ where
impl<A, I, SP> LlmpHook<SP> for TcpMultiMachineLlmpReceiverHook<A, I>
where
A: Clone + Debug + Display + ToSocketAddrs + Send + Sync + 'static,
I: Input,
A: Clone + Display + ToSocketAddrs + Send + Sync + 'static,
SP: ShMemProvider,
I: Input + Send + Sync + 'static,
{
/// check for received messages, and forward them alongside the incoming message to inner.
fn on_new_message(

View File

@ -9,12 +9,12 @@ use libafl_bolts::{
shmem::ShMemProvider,
ClientId,
};
use serde::de::DeserializeOwned;
#[cfg(feature = "llmp_compression")]
use crate::events::llmp::COMPRESS_THRESHOLD;
use crate::{
events::{llmp::LLMP_TAG_EVENT_TO_BOTH, BrokerEventResult, Event},
inputs::Input,
monitors::Monitor,
Error,
};
@ -42,9 +42,9 @@ pub struct StdLlmpEventHook<I, MT> {
impl<I, MT, SP> LlmpHook<SP> for StdLlmpEventHook<I, MT>
where
I: Input,
MT: Monitor,
I: DeserializeOwned,
SP: ShMemProvider,
MT: Monitor,
{
fn on_new_message(
&mut self,
@ -90,7 +90,6 @@ where
impl<I, MT> StdLlmpEventHook<I, MT>
where
I: Input,
MT: Monitor,
{
/// Create an event broker from a raw broker.

View File

@ -8,8 +8,8 @@
// 4. The "main broker", the gathers the stats from the fuzzer clients and broadcast the newly found testcases from the main evaluator.
use alloc::{string::String, vec::Vec};
use core::{fmt::Debug, time::Duration};
use std::{marker::PhantomData, process};
use core::{fmt::Debug, marker::PhantomData, time::Duration};
use std::process;
#[cfg(feature = "llmp_compression")]
use libafl_bolts::{
@ -19,27 +19,30 @@ use libafl_bolts::{
use libafl_bolts::{
llmp::{LlmpClient, LlmpClientDescription, Tag},
shmem::{NopShMemProvider, ShMemProvider},
tuples::Handle,
tuples::{Handle, MatchNameRef},
ClientId,
};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use super::NopEventManager;
use super::{CanSerializeObserver, ManagerExit, NopEventManager};
#[cfg(feature = "llmp_compression")]
use crate::events::llmp::COMPRESS_THRESHOLD;
use crate::{
common::HasMetadata,
corpus::Corpus,
events::{
AdaptiveSerializer, Event, EventConfig, EventFirer, EventManager, EventManagerHooksTuple,
EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, LogSeverity,
ProgressReporter,
serialize_observers_adaptive, std_maybe_report_progress, std_report_progress,
AdaptiveSerializer, Event, EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId,
EventProcessor, EventRestarter, HasEventManagerId, LogSeverity, ProgressReporter,
},
executors::{Executor, HasObservers},
executors::HasObservers,
fuzzer::{EvaluatorObservers, ExecutionProcessor},
inputs::{Input, NopInput, UsesInput},
observers::{ObserversTuple, TimeObserver},
state::{HasCorpus, HasExecutions, HasLastReportTime, NopState, State, Stoppable, UsesState},
Error, HasMetadata,
inputs::{Input, NopInput},
observers::TimeObserver,
state::{
HasCorpus, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, NopState, Stoppable,
},
Error,
};
pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453);
@ -48,9 +51,6 @@ pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453);
#[derive(Debug)]
pub struct CentralizedEventManager<EM, EMH, S, SP>
where
EM: UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider,
{
inner: EM,
@ -64,14 +64,7 @@ where
phantom: PhantomData<S>,
}
impl
CentralizedEventManager<
NopEventManager<NopState<NopInput>>,
(),
NopState<NopInput>,
NopShMemProvider,
>
{
impl CentralizedEventManager<NopEventManager, (), NopState<NopInput>, NopShMemProvider> {
/// Creates a builder for [`CentralizedEventManager`]
#[must_use]
pub fn builder() -> CentralizedEventManagerBuilder {
@ -113,9 +106,6 @@ impl CentralizedEventManagerBuilder {
time_obs: Option<Handle<TimeObserver>>,
) -> Result<CentralizedEventManager<EM, EMH, S, SP>, Error>
where
EM: UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider,
{
Ok(CentralizedEventManager {
@ -143,22 +133,10 @@ impl CentralizedEventManagerBuilder {
time_obs: Option<Handle<TimeObserver>>,
) -> Result<CentralizedEventManager<EM, EMH, S, SP>, Error>
where
EM: UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider,
{
let client = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
Ok(CentralizedEventManager {
inner,
hooks,
client,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
time_ref: time_obs,
is_main: self.is_main,
phantom: PhantomData,
})
Self::build_from_client(self, inner, hooks, client, time_obs)
}
/// If a client respawns, it may reuse the existing connection, previously
@ -172,21 +150,10 @@ impl CentralizedEventManagerBuilder {
time_obs: Option<Handle<TimeObserver>>,
) -> Result<CentralizedEventManager<EM, EMH, S, SP>, Error>
where
EM: UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider,
{
Ok(CentralizedEventManager {
inner,
hooks,
client: LlmpClient::on_existing_from_env(shmem_provider, env_name)?,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
time_ref: time_obs,
is_main: self.is_main,
phantom: PhantomData,
})
let client = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
Self::build_from_client(self, inner, hooks, client, time_obs)
}
/// Create an existing client from description
@ -199,38 +166,16 @@ impl CentralizedEventManagerBuilder {
time_obs: Option<Handle<TimeObserver>>,
) -> Result<CentralizedEventManager<EM, EMH, S, SP>, Error>
where
EM: UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider,
{
Ok(CentralizedEventManager {
inner,
hooks,
client: LlmpClient::existing_client_from_description(shmem_provider, description)?,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
time_ref: time_obs,
is_main: self.is_main,
phantom: PhantomData,
})
let client = LlmpClient::existing_client_from_description(shmem_provider, description)?;
Self::build_from_client(self, inner, hooks, client, time_obs)
}
}
impl<EM, EMH, S, SP> UsesState for CentralizedEventManager<EM, EMH, S, SP>
where
EM: UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider,
{
type State = EM::State;
}
impl<EM, EMH, S, SP> AdaptiveSerializer for CentralizedEventManager<EM, EMH, S, SP>
where
EM: AdaptiveSerializer + UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State,
EM: AdaptiveSerializer,
SP: ShMemProvider,
{
fn serialization_time(&self) -> Duration {
@ -264,13 +209,14 @@ where
}
}
impl<EM, EMH, S, SP> EventFirer for CentralizedEventManager<EM, EMH, S, SP>
impl<EM, EMH, S, SP> EventFirer<<S::Corpus as Corpus>::Input, S>
for CentralizedEventManager<EM, EMH, S, SP>
where
EM: AdaptiveSerializer + EventFirer<State = S> + HasEventManagerId,
EMH: EventManagerHooksTuple<S>,
S: State + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
EM: HasEventManagerId + EventFirer<<S::Corpus as Corpus>::Input, S>,
EMH: EventManagerHooksTuple<<<S as HasCorpus>::Corpus as Corpus>::Input, S>,
SP: ShMemProvider,
S: HasCorpus + Stoppable,
<<S as HasCorpus>::Corpus as Corpus>::Input: Input,
{
fn should_send(&self) -> bool {
self.inner.should_send()
@ -279,8 +225,8 @@ where
#[expect(clippy::match_same_arms)]
fn fire(
&mut self,
state: &mut Self::State,
mut event: Event<<Self::State as UsesInput>::Input>,
state: &mut S,
mut event: Event<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> {
if !self.is_main {
// secondary node
@ -312,45 +258,52 @@ where
fn log(
&mut self,
state: &mut Self::State,
state: &mut S,
severity_level: LogSeverity,
message: String,
) -> Result<(), Error> {
self.inner.log(state, severity_level, message)
}
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error>
where
OT: ObserversTuple<Self::Input, Self::State> + Serialize,
{
const SERIALIZE_TIME_FACTOR: u32 = 4; // twice as much as the normal llmp em's value cuz it does this job twice.
const SERIALIZE_PERCENTAGE_THRESHOLD: usize = 80;
self.inner.serialize_observers_adaptive(
observers,
SERIALIZE_TIME_FACTOR,
SERIALIZE_PERCENTAGE_THRESHOLD,
)
}
fn configuration(&self) -> EventConfig {
self.inner.configuration()
}
}
impl<EM, EMH, S, SP> EventRestarter for CentralizedEventManager<EM, EMH, S, SP>
impl<EM, EMH, S, SP> EventRestarter<S> for CentralizedEventManager<EM, EMH, S, SP>
where
EM: EventRestarter<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider,
EM: EventRestarter<S>,
{
#[inline]
fn on_restart(&mut self, state: &mut Self::State) -> Result<(), Error> {
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
self.client.await_safe_to_unmap_blocking();
self.inner.on_restart(state)?;
Ok(())
}
}
impl<EM, EMH, OT, S, SP> CanSerializeObserver<OT> for CentralizedEventManager<EM, EMH, S, SP>
where
EM: AdaptiveSerializer,
SP: ShMemProvider,
OT: Serialize + MatchNameRef,
{
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
serialize_observers_adaptive::<EM, OT>(
&mut self.inner,
observers,
4, // twice as much as the normal llmp em's value cuz it does this job twice.
80,
)
}
}
impl<EM, EMH, S, SP> ManagerExit for CentralizedEventManager<EM, EMH, S, SP>
where
EM: ManagerExit,
SP: ShMemProvider,
{
fn send_exiting(&mut self) -> Result<(), Error> {
self.client.sender_mut().send_exiting()?;
self.inner.send_exiting()
@ -363,27 +316,19 @@ where
}
}
impl<E, EM, EMH, S, SP, Z> EventProcessor<E, Z> for CentralizedEventManager<EM, EMH, S, SP>
impl<E, EM, EMH, S, SP, Z> EventProcessor<E, S, Z> for CentralizedEventManager<EM, EMH, S, SP>
where
EM: AdaptiveSerializer + EventProcessor<E, Z> + EventFirer<State = S> + HasEventManagerId,
EMH: EventManagerHooksTuple<S>,
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>,
S: State + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
Self::State: HasExecutions + HasMetadata,
E: HasObservers,
E::Observers: DeserializeOwned,
EM: EventProcessor<E, S, Z> + HasEventManagerId + EventFirer<<S::Corpus as Corpus>::Input, S>,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus + Stoppable,
<S::Corpus as Corpus>::Input: Input,
SP: ShMemProvider,
Z: EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>
+ ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>,
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>,
{
fn process(
&mut self,
fuzzer: &mut Z,
state: &mut Self::State,
executor: &mut E,
) -> Result<usize, Error> {
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
if self.is_main {
// main node
self.receive_from_secondary(fuzzer, state, executor)
@ -400,40 +345,35 @@ where
}
}
impl<E, EM, EMH, S, SP, Z> EventManager<E, Z> for CentralizedEventManager<EM, EMH, S, SP>
impl<EM, EMH, S, SP> ProgressReporter<S> for CentralizedEventManager<EM, EMH, S, SP>
where
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>,
EM: AdaptiveSerializer + EventManager<E, Z, State = S>,
EM::State: HasExecutions + HasMetadata + HasLastReportTime,
EMH: EventManagerHooksTuple<S>,
S: State + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S> + HasEventManagerId,
EMH: EventManagerHooksTuple<<<S as HasCorpus>::Corpus as Corpus>::Input, S>,
S: HasExecutions
+ HasMetadata
+ HasLastReportTime
+ Stoppable
+ HasCorpus
+ MaybeHasClientPerfMonitor,
<S::Corpus as Corpus>::Input: Input,
SP: ShMemProvider,
Z: EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>
+ ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>,
{
}
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
std_maybe_report_progress(self, state, monitor_timeout)
}
impl<EM, EMH, S, SP> ProgressReporter for CentralizedEventManager<EM, EMH, S, SP>
where
EM: AdaptiveSerializer + ProgressReporter<State = S> + HasEventManagerId,
EM::State: HasMetadata + HasExecutions + HasLastReportTime,
EMH: EventManagerHooksTuple<S>,
S: State + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
SP: ShMemProvider,
{
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
std_report_progress(self, state)
}
}
impl<EM, EMH, S, SP> HasEventManagerId for CentralizedEventManager<EM, EMH, S, SP>
where
EM: HasEventManagerId + UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
EM: HasEventManagerId,
SP: ShMemProvider,
{
fn mgr_id(&self) -> EventManagerId {
@ -443,10 +383,6 @@ where
impl<EM, EMH, S, SP> CentralizedEventManager<EM, EMH, S, SP>
where
EM: UsesState<State = S>,
EMH: EventManagerHooksTuple<S>,
S: State + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
SP: ShMemProvider,
{
/// Describe the client event manager's LLMP parts in a restorable fashion
@ -454,7 +390,7 @@ where
self.client.describe()
}
/// Write the config for a client [`EventManager`] to env vars, a new
/// Write the config for a client `EventManager` to env vars, a new
/// client can reattach using [`CentralizedEventManagerBuilder::build_existing_client_from_env()`].
pub fn to_env(&self, env_name: &str) {
self.client.to_env(env_name).unwrap();
@ -468,10 +404,10 @@ where
impl<EM, EMH, S, SP> CentralizedEventManager<EM, EMH, S, SP>
where
EM: UsesState<State = S> + EventFirer + AdaptiveSerializer + HasEventManagerId,
EMH: EventManagerHooksTuple<S>,
S: State + Stoppable + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
EM: HasEventManagerId + EventFirer<<S::Corpus as Corpus>::Input, S>,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus + Stoppable,
<S::Corpus as Corpus>::Input: Input,
SP: ShMemProvider,
{
#[cfg(feature = "llmp_compression")]
@ -510,17 +446,14 @@ where
fn receive_from_secondary<E, Z>(
&mut self,
fuzzer: &mut Z,
state: &mut <Self as UsesState>::State,
state: &mut S,
executor: &mut E,
) -> Result<usize, Error>
where
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,
for<'a> E::Observers: Deserialize<'a>,
Z: EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>
+ ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>,
E: HasObservers,
E::Observers: DeserializeOwned,
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>,
{
// TODO: Get around local event copy by moving handle_in_client
let self_id = self.client.sender().id();
@ -545,8 +478,7 @@ where
} else {
msg
};
let event: Event<<<Self as UsesState>::State as UsesInput>::Input> =
postcard::from_bytes(event_bytes)?;
let event: Event<<S::Corpus as Corpus>::Input> = postcard::from_bytes(event_bytes)?;
log::debug!("Processor received message {}", event.name_detailed());
self.handle_in_main(fuzzer, executor, state, client_id, event)?;
count += 1;
@ -559,18 +491,15 @@ where
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut <Self as UsesState>::State,
state: &mut S,
client_id: ClientId,
event: Event<<<Self as UsesState>::State as UsesInput>::Input>,
event: Event<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error>
where
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,
for<'a> E::Observers: Deserialize<'a> + Serialize,
Z: EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>
+ ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>,
E: HasObservers,
E::Observers: DeserializeOwned,
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>,
{
log::debug!("handle_in_main!");
@ -597,10 +526,6 @@ where
if client_config.match_with(&self.configuration()) && observers_buf.is_some() {
let observers: E::Observers =
postcard::from_bytes(observers_buf.as_ref().unwrap())?;
#[cfg(feature = "scalability_introspection")]
{
state.scalability_monitor_mut().testcase_with_observers += 1;
}
log::debug!(
"[{}] Running fuzzer with event {}",
process::id(),
@ -615,10 +540,6 @@ where
false,
)?
} else {
#[cfg(feature = "scalability_introspection")]
{
state.scalability_monitor_mut().testcase_without_observers += 1;
}
log::debug!(
"[{}] Running fuzzer with event {}",
process::id(),

View File

@ -4,20 +4,17 @@
//! other clients
use libafl_bolts::ClientId;
use crate::{events::Event, state::State, Error};
use crate::{events::Event, Error};
/// The `broker_hooks` that are run before and after the event manager calls `handle_in_client`
pub trait EventManagerHook<S>
where
S: State,
{
pub trait EventManagerHook<I, S> {
/// The hook that runs before `handle_in_client`
/// Return false if you want to cancel the subsequent event handling
fn pre_exec(
&mut self,
state: &mut S,
client_id: ClientId,
event: &Event<S::Input>,
event: &Event<I>,
) -> Result<bool, Error>;
/// Triggered when the even manager decides to fire the event after processing
@ -25,7 +22,7 @@ where
&mut self,
_state: &mut S,
_client_id: ClientId,
_event: &Event<S::Input>,
_event: &Event<I>,
) -> Result<(), Error> {
Ok(())
}
@ -38,16 +35,13 @@ where
}
/// The tuples contains `broker_hooks` to be executed for `handle_in_client`
pub trait EventManagerHooksTuple<S>
where
S: State,
{
pub trait EventManagerHooksTuple<I, S> {
/// The hook that runs before `handle_in_client`
fn pre_exec_all(
&mut self,
state: &mut S,
client_id: ClientId,
event: &Event<S::Input>,
event: &Event<I>,
) -> Result<bool, Error>;
/// Ran when the Event Manager decides to accept an event and propagates it
@ -55,23 +49,20 @@ where
&mut self,
state: &mut S,
client_id: ClientId,
event: &Event<S::Input>,
event: &Event<I>,
) -> Result<(), Error>;
/// The hook that runs after `handle_in_client`
fn post_exec_all(&mut self, state: &mut S, client_id: ClientId) -> Result<bool, Error>;
}
impl<S> EventManagerHooksTuple<S> for ()
where
S: State,
{
impl<I, S> EventManagerHooksTuple<I, S> for () {
/// The hook that runs before `handle_in_client`
fn pre_exec_all(
&mut self,
_state: &mut S,
_client_id: ClientId,
_event: &Event<S::Input>,
_event: &Event<I>,
) -> Result<bool, Error> {
Ok(true)
}
@ -80,7 +71,7 @@ where
&mut self,
_state: &mut S,
_client_id: ClientId,
_event: &Event<S::Input>,
_event: &Event<I>,
) -> Result<(), Error> {
Ok(())
}
@ -91,18 +82,17 @@ where
}
}
impl<Head, Tail, S> EventManagerHooksTuple<S> for (Head, Tail)
impl<Head, Tail, I, S> EventManagerHooksTuple<I, S> for (Head, Tail)
where
Head: EventManagerHook<S>,
Tail: EventManagerHooksTuple<S>,
S: State,
Head: EventManagerHook<I, S>,
Tail: EventManagerHooksTuple<I, S>,
{
/// The hook that runs before `handle_in_client`
fn pre_exec_all(
&mut self,
state: &mut S,
client_id: ClientId,
event: &Event<S::Input>,
event: &Event<I>,
) -> Result<bool, Error> {
let first = self.0.pre_exec(state, client_id, event)?;
let second = self.1.pre_exec_all(state, client_id, event)?;
@ -113,7 +103,7 @@ where
&mut self,
state: &mut S,
client_id: ClientId,
event: &Event<S::Input>,
event: &Event<I>,
) -> Result<(), Error> {
self.0.on_fire(state, client_id, event)?;
self.1.on_fire_all(state, client_id, event)

View File

@ -24,14 +24,13 @@ use libafl_bolts::{
shmem::ShMemProvider,
tuples::{tuple_list, Handle},
};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use typed_builder::TypedBuilder;
#[cfg(all(unix, feature = "fork"))]
use {
crate::{
events::{centralized::CentralizedEventManager, CentralizedLlmpHook, StdLlmpEventHook},
inputs::UsesInput,
state::UsesState,
inputs::Input,
},
alloc::string::ToString,
libafl_bolts::{
@ -52,13 +51,14 @@ use {libafl_bolts::os::startable_self, std::process::Stdio};
#[cfg(all(unix, feature = "fork", feature = "multi_machine"))]
use crate::events::multi_machine::{NodeDescriptor, TcpMultiMachineHooks};
use crate::{
corpus::Corpus,
events::{
llmp::{LlmpRestartingEventManager, LlmpShouldSaveState, ManagerKind, RestartingMgr},
EventConfig, EventManagerHooksTuple,
},
monitors::Monitor,
observers::TimeObserver,
state::{HasExecutions, State},
state::HasCorpus,
Error,
};
@ -216,7 +216,8 @@ where
#[cfg(any(windows, not(feature = "fork"), all(unix, feature = "fork")))]
pub fn launch<S>(&mut self) -> Result<(), Error>
where
S: State + HasExecutions,
S: DeserializeOwned + HasCorpus + Serialize,
<S::Corpus as Corpus>::Input: DeserializeOwned,
CF: FnOnce(
Option<S>,
LlmpRestartingEventManager<(), S, SP>,
@ -236,8 +237,9 @@ where
#[cfg(all(unix, feature = "fork"))]
pub fn launch_with_hooks<EMH, S>(&mut self, hooks: EMH) -> Result<(), Error>
where
S: State + HasExecutions,
EMH: EventManagerHooksTuple<S> + Clone + Copy,
S: DeserializeOwned + HasCorpus + Serialize,
<S::Corpus as Corpus>::Input: DeserializeOwned,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S> + Clone + Copy,
CF: FnOnce(
Option<S>,
LlmpRestartingEventManager<EMH, S, SP>,
@ -383,8 +385,9 @@ where
#[expect(clippy::too_many_lines, clippy::match_wild_err_arm)]
pub fn launch_with_hooks<EMH, S>(&mut self, hooks: EMH) -> Result<(), Error>
where
S: State + HasExecutions,
EMH: EventManagerHooksTuple<S> + Clone + Copy,
S: DeserializeOwned + HasCorpus + Serialize,
<S::Corpus as Corpus>::Input: DeserializeOwned,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S> + Clone + Copy,
CF: FnOnce(
Option<S>,
LlmpRestartingEventManager<EMH, S, SP>,
@ -547,9 +550,6 @@ pub struct CentralizedLauncher<'a, CF, MF, MT, SP> {
monitor: MT,
/// The configuration
configuration: EventConfig,
/// Consider this testcase as interesting always if true
#[builder(default = false)]
always_interesting: bool,
/// The 'main' function to run for each secondary client forked. This probably shouldn't return
#[builder(default, setter(strip_option))]
secondary_run_client: Option<CF>,
@ -633,8 +633,8 @@ where
/// Launch a standard Centralized-based fuzzer
pub fn launch<S>(&mut self) -> Result<(), Error>
where
S: State,
S::Input: Send + Sync + 'static,
S: DeserializeOwned + HasCorpus + Serialize,
<S::Corpus as Corpus>::Input: DeserializeOwned + Input + Send + Sync + 'static,
CF: FnOnce(
Option<S>,
CentralizedEventManager<StdCentralizedInnerMgr<S, SP>, (), S, SP>,
@ -650,7 +650,6 @@ where
|centralized_launcher: &Self, client_description: ClientDescription| {
// Fuzzer client. keeps retrying the connection to broker till the broker starts
let builder = RestartingMgr::<(), MT, S, SP>::builder()
.always_interesting(centralized_launcher.always_interesting)
.shmem_provider(centralized_launcher.shmem_provider.clone())
.broker_port(centralized_launcher.broker_port)
.kind(ManagerKind::Client { client_description })
@ -682,21 +681,19 @@ where
secondary_inner_mgr_builder: EMB,
) -> Result<(), Error>
where
S: State,
S::Input: Send + Sync + 'static,
S: HasCorpus,
<S::Corpus as Corpus>::Input: Input + Send + Sync + 'static,
CF: FnOnce(
Option<S>,
CentralizedEventManager<EM, (), S, SP>,
ClientDescription,
) -> Result<(), Error>,
EM: UsesState<State = S>,
EMB: FnOnce(&Self, ClientDescription) -> Result<(Option<S>, EM), Error>,
MF: FnOnce(
Option<S>,
CentralizedEventManager<EM, (), S, SP>, // No broker_hooks for centralized EM
ClientDescription,
) -> Result<(), Error>,
<<EM as UsesState>::State as UsesInput>::Input: Send + Sync + 'static,
{
let mut main_inner_mgr_builder = Some(main_inner_mgr_builder);
let mut secondary_inner_mgr_builder = Some(secondary_inner_mgr_builder);
@ -838,7 +835,7 @@ where
} = unsafe {
TcpMultiMachineHooks::builder()
.node_descriptor(self.multi_machine_node_descriptor.clone())
.build::<<<EM as UsesState>::State as UsesInput>::Input>()?
.build::<<S::Corpus as Corpus>::Input>()?
};
let mut brokers = Brokers::new();
@ -848,12 +845,13 @@ where
brokers.add(Box::new({
#[cfg(feature = "multi_machine")]
let centralized_hooks = tuple_list!(
CentralizedLlmpHook::<S::Input>::new()?,
CentralizedLlmpHook::<<S::Corpus as Corpus>::Input>::new()?,
multi_machine_receiver_hook,
);
#[cfg(not(feature = "multi_machine"))]
let centralized_hooks = tuple_list!(CentralizedLlmpHook::<S::Input>::new()?);
let centralized_hooks =
tuple_list!(CentralizedLlmpHook::<<S::Corpus as Corpus>::Input>::new()?);
// TODO switch to false after solving the bug
let mut broker = LlmpBroker::with_keep_pages_attach_to_tcp(
@ -877,12 +875,13 @@ where
log::info!("I am broker!!.");
#[cfg(not(feature = "multi_machine"))]
let llmp_hook =
tuple_list!(StdLlmpEventHook::<S::Input, MT>::new(self.monitor.clone())?);
let llmp_hook = tuple_list!(StdLlmpEventHook::<<S::Corpus as Corpus>::Input, MT>::new(
self.monitor.clone()
)?);
#[cfg(feature = "multi_machine")]
let llmp_hook = tuple_list!(
StdLlmpEventHook::<S::Input, MT>::new(self.monitor.clone())?,
StdLlmpEventHook::<<S::Corpus as Corpus>::Input, MT>::new(self.monitor.clone())?,
multi_machine_sender_hook,
);

View File

@ -1,4 +1,4 @@
//! An [`crate::events::EventManager`] that forwards all events to other attached fuzzers on shared maps or via tcp,
//! An event manager that forwards all events to other attached fuzzers on shared maps or via tcp,
//! using low-level message passing, [`libafl_bolts::llmp`].
#[cfg(feature = "std")]
@ -8,6 +8,8 @@ use core::{marker::PhantomData, time::Duration};
#[cfg(feature = "std")]
use std::net::TcpStream;
#[cfg(feature = "std")]
use libafl_bolts::tuples::MatchNameRef;
#[cfg(feature = "llmp_compression")]
use libafl_bolts::{
compress::GzipCompressor,
@ -25,39 +27,43 @@ use libafl_bolts::{
llmp::{recv_tcp_msg, send_tcp_msg, TcpRequest, TcpResponse},
IP_LOCALHOST,
};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
#[cfg(feature = "llmp_compression")]
use crate::events::llmp::COMPRESS_THRESHOLD;
#[cfg(feature = "std")]
use crate::events::{serialize_observers_adaptive, CanSerializeObserver};
use crate::{
corpus::Corpus,
events::{
llmp::{LLMP_TAG_EVENT_TO_BOTH, _LLMP_TAG_EVENT_TO_BROKER},
AdaptiveSerializer, Event, EventConfig, EventFirer, EventManager, EventManagerHooksTuple,
EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, ProgressReporter,
std_maybe_report_progress, std_on_restart, std_report_progress, AdaptiveSerializer, Event,
EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, EventProcessor,
EventRestarter, HasEventManagerId, ManagerExit, ProgressReporter,
},
executors::HasObservers,
fuzzer::{EvaluatorObservers, ExecutionProcessor},
inputs::{Input, NopInput},
observers::TimeObserver,
stages::HasCurrentStageId,
state::{
HasCorpus, HasExecutions, HasImported, HasLastReportTime, MaybeHasClientPerfMonitor,
NopState, Stoppable,
},
executors::{Executor, HasObservers},
fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor},
inputs::{NopInput, UsesInput},
observers::{ObserversTuple, TimeObserver},
state::{HasCorpus, HasExecutions, HasImported, HasLastReportTime, NopState, State, UsesState},
Error, HasMetadata,
};
/// Default initial capacity of the event buffer - 4KB
const INITIAL_EVENT_BUFFER_SIZE: usize = 1024 * 4;
/// An [`EventManager`] that forwards all events to other attached fuzzers on shared maps or via tcp,
/// An `EventManager` that forwards all events to other attached fuzzers on shared maps or via tcp,
/// using low-level message passing, `llmp`.
pub struct LlmpEventManager<EMH, S, SP>
where
S: State,
SP: ShMemProvider,
{
/// We only send 1 testcase for every `throttle` second
pub(crate) throttle: Option<Duration>,
/// Treat the incoming testcase as interesting always without evaluating them
always_interesting: bool,
/// We sent last message at `last_sent`
last_sent: Duration,
hooks: EMH,
@ -91,7 +97,6 @@ impl LlmpEventManager<(), NopState<NopInput>, NopShMemProvider> {
pub struct LlmpEventManagerBuilder<EMH> {
throttle: Option<Duration>,
hooks: EMH,
always_interesting: bool,
}
impl Default for LlmpEventManagerBuilder<()> {
@ -107,7 +112,6 @@ impl LlmpEventManagerBuilder<()> {
Self {
throttle: None,
hooks: (),
always_interesting: false,
}
}
@ -116,17 +120,6 @@ impl LlmpEventManagerBuilder<()> {
LlmpEventManagerBuilder {
throttle: self.throttle,
hooks,
always_interesting: self.always_interesting,
}
}
/// Set `always_interesting`
#[must_use]
pub fn always_interesting(self, always_interesting: bool) -> LlmpEventManagerBuilder<()> {
LlmpEventManagerBuilder {
throttle: self.throttle,
hooks: self.hooks,
always_interesting,
}
}
}
@ -148,13 +141,11 @@ impl<EMH> LlmpEventManagerBuilder<EMH> {
) -> Result<LlmpEventManager<EMH, S, SP>, Error>
where
SP: ShMemProvider,
S: State,
{
Ok(LlmpEventManager {
throttle: self.throttle,
last_sent: Duration::from_secs(0),
hooks: self.hooks,
always_interesting: self.always_interesting,
llmp,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
@ -181,26 +172,9 @@ impl<EMH> LlmpEventManagerBuilder<EMH> {
) -> Result<LlmpEventManager<EMH, S, SP>, Error>
where
SP: ShMemProvider,
S: State,
{
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
Ok(LlmpEventManager {
throttle: self.throttle,
last_sent: Duration::from_secs(0),
hooks: self.hooks,
always_interesting: self.always_interesting,
llmp,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
configuration,
serialization_time: Duration::ZERO,
deserialization_time: Duration::ZERO,
serializations_cnt: 0,
should_serialize_cnt: 0,
time_ref,
phantom: PhantomData,
event_buffer: Vec::with_capacity(INITIAL_EVENT_BUFFER_SIZE),
})
Self::build_from_client(self, llmp, configuration, time_ref)
}
/// If a client respawns, it may reuse the existing connection, previously
@ -215,26 +189,9 @@ impl<EMH> LlmpEventManagerBuilder<EMH> {
) -> Result<LlmpEventManager<EMH, S, SP>, Error>
where
SP: ShMemProvider,
S: State,
{
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
Ok(LlmpEventManager {
throttle: self.throttle,
last_sent: Duration::from_secs(0),
hooks: self.hooks,
always_interesting: self.always_interesting,
llmp,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
configuration,
serialization_time: Duration::ZERO,
deserialization_time: Duration::ZERO,
serializations_cnt: 0,
should_serialize_cnt: 0,
time_ref,
phantom: PhantomData,
event_buffer: Vec::with_capacity(INITIAL_EVENT_BUFFER_SIZE),
})
Self::build_from_client(self, llmp, configuration, time_ref)
}
/// Create an existing client from description
@ -247,33 +204,26 @@ impl<EMH> LlmpEventManagerBuilder<EMH> {
) -> Result<LlmpEventManager<EMH, S, SP>, Error>
where
SP: ShMemProvider,
S: State,
{
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
Ok(LlmpEventManager {
throttle: self.throttle,
last_sent: Duration::from_secs(0),
hooks: self.hooks,
always_interesting: self.always_interesting,
llmp,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
configuration,
serialization_time: Duration::ZERO,
deserialization_time: Duration::ZERO,
serializations_cnt: 0,
should_serialize_cnt: 0,
time_ref,
phantom: PhantomData,
event_buffer: Vec::with_capacity(INITIAL_EVENT_BUFFER_SIZE),
})
Self::build_from_client(self, llmp, configuration, time_ref)
}
}
#[cfg(feature = "std")]
impl<EMH, OT, S, SP> CanSerializeObserver<OT> for LlmpEventManager<EMH, S, SP>
where
SP: ShMemProvider,
OT: Serialize + MatchNameRef,
{
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
serialize_observers_adaptive::<Self, OT>(self, observers, 2, 80)
}
}
impl<EMH, S, SP> AdaptiveSerializer for LlmpEventManager<EMH, S, SP>
where
SP: ShMemProvider,
S: State,
{
fn serialization_time(&self) -> Duration {
self.serialization_time
@ -309,7 +259,6 @@ where
impl<EMH, S, SP> core::fmt::Debug for LlmpEventManager<EMH, S, SP>
where
SP: ShMemProvider,
S: State,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut debug_struct = f.debug_struct("LlmpEventManager");
@ -327,7 +276,6 @@ where
impl<EMH, S, SP> Drop for LlmpEventManager<EMH, S, SP>
where
SP: ShMemProvider,
S: State,
{
/// LLMP clients will have to wait until their pages are mapped by somebody.
fn drop(&mut self) {
@ -337,7 +285,6 @@ where
impl<EMH, S, SP> LlmpEventManager<EMH, S, SP>
where
S: State,
SP: ShMemProvider,
{
/// Calling this function will tell the llmp broker that this client is exiting
@ -378,7 +325,7 @@ where
self.llmp.describe()
}
/// Write the config for a client [`EventManager`] to env vars, a new
/// Write the config for a client `EventManager` to env vars, a new
/// client can reattach using [`LlmpEventManagerBuilder::build_existing_client_from_env()`].
#[cfg(feature = "std")]
pub fn to_env(&self, env_name: &str) {
@ -388,9 +335,6 @@ where
impl<EMH, S, SP> LlmpEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
SP: ShMemProvider,
{
// Handle arriving events in the client
@ -400,15 +344,16 @@ where
executor: &mut E,
state: &mut S,
client_id: ClientId,
event: Event<S::Input>,
event: Event<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error>
where
E: Executor<Self, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
E::Observers: ObserversTuple<S::Input, S> + Serialize,
for<'a> E::Observers: Deserialize<'a>,
S: HasCorpus + HasImported + Stoppable,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: Input,
E: HasObservers,
E::Observers: DeserializeOwned,
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>
+ Evaluator<E, Self, <S::Corpus as Corpus>::Input, S>,
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>,
{
log::trace!("Got event in client: {} from {client_id:?}", event.name());
if !self.hooks.pre_exec_all(state, client_id, &event)? {
@ -428,38 +373,24 @@ where
#[cfg(feature = "std")]
log::debug!("[{}] Received new Testcase {evt_name} from {client_id:?} ({client_config:?}, forward {forward_id:?})", std::process::id());
if self.always_interesting {
let item = fuzzer.add_input(state, executor, self, input)?;
log::debug!("Added received Testcase as item #{item}");
} else {
let res = if client_config.match_with(&self.configuration)
&& observers_buf.is_some()
let res = if client_config.match_with(&self.configuration)
&& observers_buf.is_some()
{
let start = current_time();
let observers: E::Observers =
postcard::from_bytes(observers_buf.as_ref().unwrap())?;
{
let start = current_time();
let observers: E::Observers =
postcard::from_bytes(observers_buf.as_ref().unwrap())?;
{
self.deserialization_time = current_time() - start;
}
#[cfg(feature = "scalability_introspection")]
{
state.scalability_monitor_mut().testcase_with_observers += 1;
}
fuzzer
.evaluate_execution(state, self, input, &observers, &exit_kind, false)?
} else {
#[cfg(feature = "scalability_introspection")]
{
state.scalability_monitor_mut().testcase_without_observers += 1;
}
fuzzer.evaluate_input_with_observers(state, executor, self, input, false)?
};
if let Some(item) = res.1 {
*state.imported_mut() += 1;
log::debug!("Added received Testcase {evt_name} as item #{item}");
} else {
log::debug!("Testcase {evt_name} was discarded");
self.deserialization_time = current_time() - start;
}
fuzzer.evaluate_execution(state, self, input, &observers, &exit_kind, false)?
} else {
fuzzer.evaluate_input_with_observers(state, executor, self, input, false)?
};
if let Some(item) = res.1 {
*state.imported_mut() += 1;
log::debug!("Added received Testcase {evt_name} as item #{item}");
} else {
log::debug!("Testcase {evt_name} was discarded");
}
}
Event::Stop => {
@ -478,7 +409,7 @@ where
}
}
impl<EMH, S: State, SP: ShMemProvider> LlmpEventManager<EMH, S, SP> {
impl<EMH, S, SP: ShMemProvider> LlmpEventManager<EMH, S, SP> {
/// Send information that this client is exiting.
/// The other side may free up all allocated memory.
/// We are no longer allowed to send anything afterwards.
@ -487,17 +418,9 @@ impl<EMH, S: State, SP: ShMemProvider> LlmpEventManager<EMH, S, SP> {
}
}
impl<EMH, S, SP> UsesState for LlmpEventManager<EMH, S, SP>
impl<EMH, I, S, SP> EventFirer<I, S> for LlmpEventManager<EMH, S, SP>
where
S: State,
SP: ShMemProvider,
{
type State = S;
}
impl<EMH, S, SP> EventFirer for LlmpEventManager<EMH, S, SP>
where
S: State,
I: Serialize,
SP: ShMemProvider,
{
fn should_send(&self) -> bool {
@ -507,11 +430,7 @@ where
true
}
}
fn fire(
&mut self,
_state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
fn fire(&mut self, _state: &mut S, event: Event<I>) -> Result<(), Error> {
#[cfg(feature = "llmp_compression")]
let flags = LLMP_FLAG_INITIALIZED;
@ -557,27 +476,24 @@ where
self.last_sent = current_time();
Ok(())
}
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error>
where
OT: ObserversTuple<Self::Input, Self::State> + Serialize,
{
const SERIALIZE_TIME_FACTOR: u32 = 2;
const SERIALIZE_PERCENTAGE_THRESHOLD: usize = 80;
self.serialize_observers_adaptive(
observers,
SERIALIZE_TIME_FACTOR,
SERIALIZE_PERCENTAGE_THRESHOLD,
)
}
fn configuration(&self) -> EventConfig {
self.configuration
}
}
impl<EMH, S, SP> EventRestarter for LlmpEventManager<EMH, S, SP>
impl<EMH, S, SP> EventRestarter<S> for LlmpEventManager<EMH, S, SP>
where
SP: ShMemProvider,
S: HasCurrentStageId,
{
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
std_on_restart(self, state)
}
}
impl<EMH, S, SP> ManagerExit for LlmpEventManager<EMH, S, SP>
where
S: State,
SP: ShMemProvider,
{
/// The LLMP client needs to wait until a broker has mapped all pages before shutting down.
@ -586,27 +502,24 @@ where
// wait until we can drop the message safely.
self.llmp.await_safe_to_unmap_blocking();
}
fn send_exiting(&mut self) -> Result<(), Error> {
self.llmp.sender_mut().send_exiting()
}
}
impl<E, EMH, S, SP, Z> EventProcessor<E, Z> for LlmpEventManager<EMH, S, SP>
impl<E, EMH, S, SP, Z> EventProcessor<E, S, Z> for LlmpEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
E: HasObservers,
E::Observers: DeserializeOwned,
S: HasCorpus + HasImported + Stoppable,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: DeserializeOwned + Input,
SP: ShMemProvider,
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>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>
+ Evaluator<E, Self, <S::Corpus as Corpus>::Input, S>,
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>,
{
fn process(
&mut self,
fuzzer: &mut Z,
state: &mut Self::State,
executor: &mut E,
) -> Result<usize, Error> {
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
// TODO: Get around local event copy by moving handle_in_client
let self_id = self.llmp.sender().id();
let mut count = 0;
@ -630,7 +543,7 @@ where
} else {
msg
};
let event: Event<S::Input> = postcard::from_bytes(event_bytes)?;
let event: Event<<S::Corpus as Corpus>::Input> = postcard::from_bytes(event_bytes)?;
log::debug!("Received event in normal llmp {}", event.name_detailed());
// If the message comes from another machine, do not
@ -650,31 +563,27 @@ where
}
}
impl<E, EMH, S, SP, Z> EventManager<E, Z> for LlmpEventManager<EMH, S, SP>
impl<EMH, S, SP> ProgressReporter<S> for LlmpEventManager<EMH, S, SP>
where
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>,
S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
S: HasExecutions + HasLastReportTime + HasMetadata + HasCorpus + MaybeHasClientPerfMonitor,
SP: ShMemProvider,
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>
+ Evaluator<E, Self, <S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: Serialize,
{
}
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
std_maybe_report_progress(self, state, monitor_timeout)
}
impl<EMH, S, SP> ProgressReporter for LlmpEventManager<EMH, S, SP>
where
S: State + HasExecutions + HasMetadata + HasLastReportTime,
SP: ShMemProvider,
{
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
std_report_progress(self, state)
}
}
impl<EMH, S, SP> HasEventManagerId for LlmpEventManager<EMH, S, SP>
where
S: State,
SP: ShMemProvider,
{
/// Gets the id assigned to this staterestorer.

View File

@ -1,6 +1,6 @@
//! LLMP-backed event manager for scalable multi-processed fuzzing
use core::{marker::PhantomData, time::Duration};
use core::{fmt::Debug, marker::PhantomData, time::Duration};
#[cfg(feature = "llmp_compression")]
use libafl_bolts::{
@ -12,16 +12,15 @@ use libafl_bolts::{
shmem::{NopShMemProvider, ShMemProvider},
ClientId,
};
use serde::Deserialize;
use serde::{de::DeserializeOwned, Serialize};
use crate::{
corpus::Corpus,
events::{Event, EventFirer},
executors::{Executor, HasObservers},
fuzzer::{EvaluatorObservers, ExecutionProcessor},
inputs::{Input, InputConverter, NopInput, NopInputConverter, UsesInput},
state::{HasCorpus, HasExecutions, NopState, State, Stoppable, UsesState},
Error, HasMetadata,
fuzzer::EvaluatorObservers,
inputs::{Input, InputConverter, NopInput, NopInputConverter},
state::{HasCorpus, NopState},
Error,
};
/// The llmp event manager
@ -84,13 +83,9 @@ impl LlmpShouldSaveState {
}
/// A manager-like llmp client that converts between input types
pub struct LlmpEventConverter<DI, IC, ICB, S, SP>
pub struct LlmpEventConverter<IC, ICB, S, SP>
where
S: UsesInput,
SP: ShMemProvider,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
{
throttle: Option<Duration>,
llmp: LlmpClient<SP>,
@ -104,7 +99,6 @@ where
impl
LlmpEventConverter<
NopInput,
NopInputConverter<NopInput>,
NopInputConverter<NopInput>,
NopState<NopInput>,
@ -140,18 +134,14 @@ impl LlmpEventConverterBuilder {
}
/// Create a event converter from a raw llmp client
pub fn build_from_client<DI, IC, ICB, S, SP>(
pub fn build_from_client<IC, ICB, S, SP>(
self,
llmp: LlmpClient<SP>,
converter: Option<IC>,
converter_back: Option<ICB>,
) -> Result<LlmpEventConverter<DI, IC, ICB, S, SP>, Error>
) -> Result<LlmpEventConverter<IC, ICB, S, SP>, Error>
where
SP: ShMemProvider,
S: UsesInput,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
{
Ok(LlmpEventConverter {
throttle: self.throttle,
@ -167,19 +157,15 @@ impl LlmpEventConverterBuilder {
/// Create a client from port and the input converters
#[cfg(feature = "std")]
pub fn build_on_port<DI, IC, ICB, S, SP>(
pub fn build_on_port<IC, ICB, S, SP>(
self,
shmem_provider: SP,
port: u16,
converter: Option<IC>,
converter_back: Option<ICB>,
) -> Result<LlmpEventConverter<DI, IC, ICB, S, SP>, Error>
) -> Result<LlmpEventConverter<IC, ICB, S, SP>, Error>
where
SP: ShMemProvider,
S: UsesInput,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
{
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
Ok(LlmpEventConverter {
@ -196,19 +182,15 @@ impl LlmpEventConverterBuilder {
/// If a client respawns, it may reuse the existing connection, previously stored by [`LlmpClient::to_env()`].
#[cfg(feature = "std")]
pub fn build_existing_client_from_env<DI, IC, ICB, S, SP>(
pub fn build_existing_client_from_env<IC, ICB, S, SP>(
self,
shmem_provider: SP,
env_name: &str,
converter: Option<IC>,
converter_back: Option<ICB>,
) -> Result<LlmpEventConverter<DI, IC, ICB, S, SP>, Error>
) -> Result<LlmpEventConverter<IC, ICB, S, SP>, Error>
where
SP: ShMemProvider,
S: UsesInput,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
{
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
Ok(LlmpEventConverter {
@ -224,13 +206,11 @@ impl LlmpEventConverterBuilder {
}
}
impl<DI, IC, ICB, S, SP> core::fmt::Debug for LlmpEventConverter<DI, IC, ICB, S, SP>
impl<IC, ICB, S, SP> Debug for LlmpEventConverter<IC, ICB, S, SP>
where
SP: ShMemProvider,
S: UsesInput,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
ICB: Debug,
IC: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut debug_struct = f.debug_struct("LlmpEventConverter");
@ -246,13 +226,10 @@ where
}
}
impl<DI, IC, ICB, S, SP> LlmpEventConverter<DI, IC, ICB, S, SP>
impl<IC, ICB, S, SP> LlmpEventConverter<IC, ICB, S, SP>
where
S: UsesInput + HasExecutions + HasMetadata + Stoppable + HasCorpus,
S: HasCorpus,
SP: ShMemProvider,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
{
// TODO other new_* routines
@ -278,7 +255,7 @@ where
}
// Handle arriving events in the client
fn handle_in_client<E, EM, Z>(
fn handle_in_client<DI, E, EM, Z>(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
@ -288,12 +265,8 @@ where
event: Event<DI>,
) -> Result<(), Error>
where
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>,
Z: ExecutionProcessor<EM, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, EM, <S::Corpus as Corpus>::Input, S>,
ICB: InputConverter<To = <S::Corpus as Corpus>::Input, From = DI>,
Z: EvaluatorObservers<E, EM, <S::Corpus as Corpus>::Input, S>,
{
match event {
Event::NewTestcase {
@ -327,7 +300,7 @@ where
}
/// Handle arriving events in the client
pub fn process<E, EM, Z>(
pub fn process<DI, E, EM, Z>(
&mut self,
fuzzer: &mut Z,
state: &mut S,
@ -335,12 +308,9 @@ where
manager: &mut EM,
) -> Result<usize, Error>
where
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>,
Z: ExecutionProcessor<EM, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, EM, <S::Corpus as Corpus>::Input, S>,
ICB: InputConverter<To = <S::Corpus as Corpus>::Input, From = DI>,
DI: DeserializeOwned + Input,
Z: EvaluatorObservers<E, EM, <S::Corpus as Corpus>::Input, S>,
{
// TODO: Get around local event copy by moving handle_in_client
let self_id = self.llmp.sender().id();
@ -375,24 +345,13 @@ where
}
}
impl<DI, IC, ICB, S, SP> UsesState for LlmpEventConverter<DI, IC, ICB, S, SP>
impl<IC, ICB, S, SP> EventFirer<<S::Corpus as Corpus>::Input, S>
for LlmpEventConverter<IC, ICB, S, SP>
where
S: State,
IC: InputConverter<From = <S::Corpus as Corpus>::Input>,
S: HasCorpus,
SP: ShMemProvider,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
{
type State = S;
}
impl<DI, IC, ICB, S, SP> EventFirer for LlmpEventConverter<DI, IC, ICB, S, SP>
where
S: State,
SP: ShMemProvider,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
IC::To: Serialize,
{
fn should_send(&self) -> bool {
if let Some(throttle) = self.throttle {
@ -405,8 +364,8 @@ where
#[cfg(feature = "llmp_compression")]
fn fire(
&mut self,
_state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
_state: &mut S,
event: Event<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> {
if self.converter.is_none() {
return Ok(());
@ -461,8 +420,8 @@ where
#[cfg(not(feature = "llmp_compression"))]
fn fire(
&mut self,
_state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
_state: &mut S,
event: Event<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> {
if self.converter.is_none() {
return Ok(());

View File

@ -24,37 +24,41 @@ use libafl_bolts::{
os::CTRL_C_EXIT,
shmem::{ShMemProvider, StdShMemProvider},
staterestore::StateRestorer,
tuples::{tuple_list, Handle},
tuples::{tuple_list, Handle, MatchNameRef},
};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use typed_builder::TypedBuilder;
#[cfg(all(unix, not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE;
use crate::{
common::HasMetadata,
corpus::Corpus,
events::{
launcher::ClientDescription, AdaptiveSerializer, Event, EventConfig, EventFirer,
EventManager, EventManagerHooksTuple, EventManagerId, EventProcessor, EventRestarter,
HasEventManagerId, LlmpEventManager, LlmpShouldSaveState, ProgressReporter,
launcher::ClientDescription, serialize_observers_adaptive, std_maybe_report_progress,
std_report_progress, AdaptiveSerializer, CanSerializeObserver, Event, EventConfig,
EventFirer, EventManagerHooksTuple, EventManagerId, EventProcessor, EventRestarter,
HasEventManagerId, LlmpEventManager, LlmpShouldSaveState, ManagerExit, ProgressReporter,
StdLlmpEventHook,
},
executors::{Executor, HasObservers},
fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor},
inputs::UsesInput,
executors::HasObservers,
fuzzer::{EvaluatorObservers, ExecutionProcessor},
inputs::Input,
monitors::Monitor,
observers::{ObserversTuple, TimeObserver},
state::{HasCorpus, HasExecutions, HasImported, HasLastReportTime, State, UsesState},
Error, HasMetadata,
observers::TimeObserver,
stages::HasCurrentStageId,
state::{
HasCorpus, HasExecutions, HasImported, HasLastReportTime, MaybeHasClientPerfMonitor,
Stoppable,
},
Error,
};
/// A manager that can restart on the fly, storing states in-between (in `on_restart`)
#[derive(Debug)]
pub struct LlmpRestartingEventManager<EMH, S, SP>
where
S: State,
SP: ShMemProvider,
//CE: CustomEvent<I>,
{
/// The embedded LLMP event manager
llmp_mgr: LlmpEventManager<EMH, S, SP>,
@ -67,7 +71,6 @@ where
impl<EMH, S, SP> AdaptiveSerializer for LlmpRestartingEventManager<EMH, S, SP>
where
SP: ShMemProvider,
S: State,
{
fn serialization_time(&self) -> Duration {
self.llmp_mgr.serialization_time()
@ -100,67 +103,68 @@ where
}
}
impl<EMH, S, SP> UsesState for LlmpRestartingEventManager<EMH, S, SP>
impl<EMH, S, SP> ProgressReporter<S> for LlmpRestartingEventManager<EMH, S, SP>
where
S: State,
S: HasExecutions
+ HasLastReportTime
+ HasMetadata
+ HasCorpus
+ Serialize
+ MaybeHasClientPerfMonitor,
SP: ShMemProvider,
<S::Corpus as Corpus>::Input: Serialize,
{
type State = S;
}
impl<EMH, S, SP> ProgressReporter for LlmpRestartingEventManager<EMH, S, SP>
where
S: State + HasExecutions + HasMetadata + HasLastReportTime,
SP: ShMemProvider,
{
}
impl<EMH, S, SP> EventFirer for LlmpRestartingEventManager<EMH, S, SP>
where
SP: ShMemProvider,
S: State,
//CE: CustomEvent<I>,
{
fn should_send(&self) -> bool {
self.llmp_mgr.should_send()
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
std_maybe_report_progress(self, state, monitor_timeout)
}
fn fire(
&mut self,
state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
std_report_progress(self, state)
}
}
impl<EMH, I, S, SP> EventFirer<I, S> for LlmpRestartingEventManager<EMH, S, SP>
where
I: Serialize,
S: HasCorpus + Serialize,
SP: ShMemProvider,
{
fn should_send(&self) -> bool {
<LlmpEventManager<EMH, S, SP> as EventFirer<I, S>>::should_send(&self.llmp_mgr)
}
fn fire(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error> {
// Check if we are going to crash in the event, in which case we store our current state for the next runner
self.llmp_mgr.fire(state, event)?;
self.intermediate_save()?;
Ok(())
}
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error>
where
OT: ObserversTuple<Self::Input, Self::State> + Serialize,
{
self.llmp_mgr.serialize_observers(observers)
}
fn configuration(&self) -> EventConfig {
self.llmp_mgr.configuration()
<LlmpEventManager<EMH, S, SP> as EventFirer<I, S>>::configuration(&self.llmp_mgr)
}
}
impl<EMH, S, SP> EventRestarter for LlmpRestartingEventManager<EMH, S, SP>
#[cfg(feature = "std")]
impl<EMH, OT, S, SP> CanSerializeObserver<OT> for LlmpRestartingEventManager<EMH, S, SP>
where
S: State + HasExecutions,
SP: ShMemProvider,
//CE: CustomEvent<I>,
OT: Serialize + MatchNameRef,
{
/// The llmp client needs to wait until a broker mapped all pages, before shutting down.
/// Otherwise, the OS may already have removed the shared maps,
#[inline]
fn await_restart_safe(&mut self) {
self.llmp_mgr.await_restart_safe();
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
serialize_observers_adaptive::<Self, OT>(self, observers, 2, 80)
}
}
impl<EMH, S, SP> EventRestarter<S> for LlmpRestartingEventManager<EMH, S, SP>
where
SP: ShMemProvider,
S: Serialize + HasCurrentStageId,
{
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
state.on_restart()?;
@ -180,31 +184,42 @@ where
self.await_restart_safe();
Ok(())
}
}
impl<EMH, S, SP> ManagerExit for LlmpRestartingEventManager<EMH, S, SP>
where
SP: ShMemProvider,
{
fn send_exiting(&mut self) -> Result<(), Error> {
self.staterestorer.send_exiting();
// Also inform the broker that we are about to exit.
// This way, the broker can clean up the pages, and eventually exit.
self.llmp_mgr.send_exiting()
}
/// The llmp client needs to wait until a broker mapped all pages, before shutting down.
/// Otherwise, the OS may already have removed the shared maps,
#[inline]
fn await_restart_safe(&mut self) {
self.llmp_mgr.await_restart_safe();
}
}
impl<E, EMH, S, SP, Z> EventProcessor<E, Z> for LlmpRestartingEventManager<EMH, S, SP>
impl<E, EMH, S, SP, Z> EventProcessor<E, S, Z> for LlmpRestartingEventManager<EMH, S, SP>
where
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>,
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
E: HasObservers,
E::Observers: DeserializeOwned,
S: HasCorpus + HasImported + Stoppable + Serialize,
<S::Corpus as Corpus>::Input: DeserializeOwned + Input,
S::Corpus: Serialize,
SP: ShMemProvider,
Z: ExecutionProcessor<
LlmpEventManager<EMH, S, SP>,
<S::Corpus as Corpus>::Input,
E::Observers,
S,
> + EvaluatorObservers<E, LlmpEventManager<EMH, S, SP>, <S::Corpus as Corpus>::Input, S>
+ Evaluator<E, LlmpEventManager<EMH, S, SP>, <S::Corpus as Corpus>::Input, S>,
> + EvaluatorObservers<E, LlmpEventManager<EMH, S, SP>, <S::Corpus as Corpus>::Input, S>,
{
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
let res = self.llmp_mgr.process(fuzzer, state, executor)?;
@ -217,28 +232,8 @@ where
}
}
impl<E, EMH, S, SP, Z> EventManager<E, Z> for LlmpRestartingEventManager<EMH, S, SP>
where
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>,
S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
SP: ShMemProvider,
Z: ExecutionProcessor<
LlmpEventManager<EMH, S, SP>,
<S::Corpus as Corpus>::Input,
E::Observers,
S,
> + EvaluatorObservers<E, LlmpEventManager<EMH, S, SP>, <S::Corpus as Corpus>::Input, S>
+ Evaluator<E, LlmpEventManager<EMH, S, SP>, <S::Corpus as Corpus>::Input, S>,
{
}
impl<EMH, S, SP> HasEventManagerId for LlmpRestartingEventManager<EMH, S, SP>
where
S: State,
SP: ShMemProvider,
{
fn mgr_id(&self) -> EventManagerId {
@ -254,9 +249,8 @@ const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
impl<EMH, S, SP> LlmpRestartingEventManager<EMH, S, SP>
where
S: State,
SP: ShMemProvider,
//CE: CustomEvent<I>,
S: Serialize,
{
/// Create a new runner, the executed child doing the actual fuzzing.
pub fn new(llmp_mgr: LlmpEventManager<EMH, S, SP>, staterestorer: StateRestorer<SP>) -> Self {
@ -334,7 +328,8 @@ pub fn setup_restarting_mgr_std<MT, S>(
>
where
MT: Monitor + Clone,
S: State,
S: HasCorpus + Serialize + DeserializeOwned,
<S::Corpus as Corpus>::Input: DeserializeOwned,
{
RestartingMgr::builder()
.shmem_provider(StdShMemProvider::new()?)
@ -366,7 +361,8 @@ pub fn setup_restarting_mgr_std_adaptive<MT, S>(
>
where
MT: Monitor + Clone,
S: State,
S: HasCorpus + Serialize + DeserializeOwned,
<S::Corpus as Corpus>::Input: DeserializeOwned,
{
RestartingMgr::builder()
.shmem_provider(StdShMemProvider::new()?)
@ -389,9 +385,6 @@ pub struct RestartingMgr<EMH, MT, S, SP> {
/// The shared memory provider to use for the broker or client spawned by the restarting
/// manager.
shmem_provider: SP,
#[builder(default = false)]
/// Consider this testcase as interesting always if true
always_interesting: bool,
/// The configuration
configuration: EventConfig,
/// The monitor to use
@ -428,9 +421,10 @@ pub struct RestartingMgr<EMH, MT, S, SP> {
#[expect(clippy::type_complexity, clippy::too_many_lines)]
impl<EMH, MT, S, SP> RestartingMgr<EMH, MT, S, SP>
where
EMH: EventManagerHooksTuple<S> + Copy + Clone,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S> + Copy + Clone,
SP: ShMemProvider,
S: State,
S: HasCorpus + Serialize + DeserializeOwned,
<S::Corpus as Corpus>::Input: DeserializeOwned,
MT: Monitor + Clone,
{
/// Launch the broker and the clients and fuzz
@ -463,9 +457,10 @@ where
LlmpConnection::on_port(self.shmem_provider.clone(), self.broker_port)?;
match connection {
LlmpConnection::IsBroker { broker } => {
let llmp_hook = StdLlmpEventHook::<S::Input, MT>::new(
self.monitor.take().unwrap(),
)?;
let llmp_hook =
StdLlmpEventHook::<<S::Corpus as Corpus>::Input, MT>::new(
self.monitor.take().unwrap(),
)?;
// Yep, broker. Just loop here.
log::info!(
@ -481,7 +476,6 @@ where
}
LlmpConnection::IsClient { client } => {
let mgr: LlmpEventManager<EMH, S, SP> = LlmpEventManager::builder()
.always_interesting(self.always_interesting)
.hooks(self.hooks)
.build_from_client(
client,
@ -507,7 +501,6 @@ where
ManagerKind::Client { client_description } => {
// We are a client
let mgr = LlmpEventManager::builder()
.always_interesting(self.always_interesting)
.hooks(self.hooks)
.build_on_port(
self.shmem_provider.clone(),

View File

@ -1,4 +1,4 @@
//! An [`EventManager`] manages all events that go to other instances of the fuzzer.
//! An `EventManager` manages all events that go to other instances of the fuzzer.
//! The messages are commonly information about new Testcases as well as stats and other [`Event`]s.
pub mod events_hooks;
@ -37,29 +37,21 @@ pub use launcher::*;
use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Signal, SignalHandler};
#[cfg(all(unix, feature = "std"))]
use libafl_bolts::os::CTRL_C_EXIT;
use libafl_bolts::{
current_time,
tuples::{Handle, MatchNameRef},
};
#[cfg(feature = "std")]
use libafl_bolts::tuples::MatchNameRef;
use libafl_bolts::{current_time, tuples::Handle};
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
use uuid::Uuid;
#[cfg(feature = "introspection")]
use crate::state::HasClientPerfMonitor;
use crate::{
corpus::Corpus,
executors::ExitKind,
inputs::Input,
monitors::UserStats,
observers::ObserversTuple,
state::{HasExecutions, HasLastReportTime, State},
state::{HasCorpus, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor},
Error, HasMetadata,
};
#[cfg(feature = "scalability_introspection")]
use crate::{
monitors::{AggregatorOps, UserStatsValue},
state::HasScalabilityMonitor,
};
/// Multi-machine mode
#[cfg(all(unix, feature = "std", feature = "multi_machine"))]
@ -105,7 +97,7 @@ impl SignalHandler for ShutdownSignalData {
}
/// A per-fuzzer unique `ID`, usually starting with `0` and increasing
/// by `1` in multiprocessed [`EventManager`]s, such as [`LlmpEventManager`].
/// by `1` in multiprocessed `EventManagers`, such as [`LlmpEventManager`].
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct EventManagerId(
@ -117,9 +109,7 @@ pub struct EventManagerId(
use crate::events::multi_machine::NodeId;
#[cfg(feature = "introspection")]
use crate::monitors::ClientPerfMonitor;
use crate::{
inputs::UsesInput, observers::TimeObserver, stages::HasCurrentStageId, state::UsesState,
};
use crate::{observers::TimeObserver, stages::HasCurrentStageId};
/// The log event severity
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
@ -256,11 +246,7 @@ where
// TODO remove forward_id as not anymore needed for centralized
/// Events sent around in the library
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub enum Event<I>
where
I: Input,
{
pub enum Event<I> {
// TODO use an ID to keep track of the original index in the sender Corpus
// The sender can then use it to send Testcase metadata with CustomEvent
/// A fuzzer found a new testcase. Rejoice!
@ -339,10 +325,7 @@ where
},*/
}
impl<I> Event<I>
where
I: Input,
{
impl<I> Event<I> {
/// Event's corresponding name
pub fn name(&self) -> &str {
match self {
@ -361,7 +344,10 @@ where
}
/// Event's corresponding name with additional info
fn name_detailed(&self) -> Cow<'static, str> {
fn name_detailed(&self) -> Cow<'static, str>
where
I: Input,
{
match self {
Event::NewTestcase { input, .. } => {
Cow::Owned(format!("Testcase {}", input.generate_name(None)))
@ -386,7 +372,7 @@ where
}
/// [`EventFirer`] fires an event.
pub trait EventFirer: UsesState {
pub trait EventFirer<I, S> {
/// Send off an [`Event`] to the broker
///
/// For multi-processed managers, such as [`LlmpEventManager`],
@ -395,17 +381,13 @@ pub trait EventFirer: UsesState {
/// (for example for each [`Input`], on multiple cores)
/// the [`llmp`] shared map may fill up and the client will eventually OOM or [`panic`].
/// This should not happen for a normal use-case.
fn fire(
&mut self,
state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
) -> Result<(), Error>;
fn fire(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error>;
/// Send off an [`Event::Log`] event to the broker.
/// This is a shortcut for [`EventFirer::fire`] with [`Event::Log`] as argument.
fn log(
&mut self,
state: &mut Self::State,
state: &mut S,
severity_level: LogSeverity,
message: String,
) -> Result<(), Error> {
@ -419,14 +401,6 @@ pub trait EventFirer: UsesState {
)
}
/// Serialize all observers for this type and manager
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error>
where
OT: ObserversTuple<<Self as UsesInput>::Input, Self::State> + Serialize,
{
Ok(Some(postcard::to_allocvec(observers)?))
}
/// Get the configuration
fn configuration(&self) -> EventConfig {
EventConfig::AlwaysUnique
@ -436,208 +410,249 @@ pub trait EventFirer: UsesState {
fn should_send(&self) -> bool;
}
/// [`ProgressReporter`] report progress to the broker.
pub trait ProgressReporter: EventFirer
/// Serialize all observers for this type and manager
/// Serialize the observer using the `time_factor` and `percentage_threshold`.
/// These parameters are unique to each of the different types of `EventManager`
#[cfg(feature = "std")]
pub(crate) fn serialize_observers_adaptive<EM, OT>(
manager: &mut EM,
observers: &OT,
time_factor: u32,
percentage_threshold: usize,
) -> Result<Option<Vec<u8>>, Error>
where
Self::State: HasMetadata + HasExecutions + HasLastReportTime,
EM: AdaptiveSerializer,
OT: MatchNameRef + Serialize,
{
/// Given the last time, if `monitor_timeout` seconds passed, send off an info/monitor/heartbeat message to the broker.
/// Returns the new `last` time (so the old one, unless `monitor_timeout` time has passed and monitor have been sent)
/// Will return an [`Error`], if the stats could not be sent.
fn maybe_report_progress(
&mut self,
state: &mut Self::State,
monitor_timeout: Duration,
) -> Result<(), Error> {
let Some(last_report_time) = state.last_report_time() else {
// this is the first time we execute, no need to report progress just yet.
*state.last_report_time_mut() = Some(current_time());
return Ok(());
};
let cur = current_time();
// default to 0 here to avoid crashes on clock skew
if cur.checked_sub(*last_report_time).unwrap_or_default() > monitor_timeout {
// report_progress sets a new `last_report_time` internally.
self.report_progress(state)?;
match manager.time_ref() {
Some(t) => {
let exec_time = observers
.get(t)
.map(|o| o.last_runtime().unwrap_or(Duration::ZERO))
.unwrap();
let mut must_ser = (manager.serialization_time() + manager.deserialization_time())
* time_factor
< exec_time;
if must_ser {
*manager.should_serialize_cnt_mut() += 1;
}
if manager.serializations_cnt() > 32 {
must_ser = (manager.should_serialize_cnt() * 100 / manager.serializations_cnt())
> percentage_threshold;
}
if manager.serialization_time() == Duration::ZERO
|| must_ser
|| manager.serializations_cnt().trailing_zeros() >= 8
{
let start = current_time();
let ser = postcard::to_allocvec(observers)?;
*manager.serialization_time_mut() = current_time() - start;
*manager.serializations_cnt_mut() += 1;
Ok(Some(ser))
} else {
*manager.serializations_cnt_mut() += 1;
Ok(None)
}
}
Ok(())
None => Ok(None),
}
}
/// Send off an info/monitor/heartbeat message to the broker.
/// Will return an [`Error`], if the stats could not be sent.
fn report_progress(&mut self, state: &mut Self::State) -> Result<(), Error> {
let executions = *state.executions();
let cur = current_time();
/// Default implementation of [`ProgressReporter::maybe_report_progress`] for implementors with the
/// given constraints
pub fn std_maybe_report_progress<PR, S>(
reporter: &mut PR,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error>
where
PR: ProgressReporter<S>,
S: HasMetadata + HasExecutions + HasLastReportTime,
{
let Some(last_report_time) = state.last_report_time() else {
// this is the first time we execute, no need to report progress just yet.
*state.last_report_time_mut() = Some(current_time());
return Ok(());
};
let cur = current_time();
// default to 0 here to avoid crashes on clock skew
if cur.checked_sub(*last_report_time).unwrap_or_default() > monitor_timeout {
// report_progress sets a new `last_report_time` internally.
reporter.report_progress(state)?;
}
Ok(())
}
// Default no introspection implmentation
#[cfg(not(feature = "introspection"))]
self.fire(
/// Default implementation of [`ProgressReporter::report_progress`] for implementors with the
/// given constraints
pub fn std_report_progress<EM, S>(reporter: &mut EM, state: &mut S) -> Result<(), Error>
where
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
S: HasExecutions + HasLastReportTime + HasCorpus + MaybeHasClientPerfMonitor,
{
let executions = *state.executions();
let cur = current_time();
// Default no introspection implmentation
#[cfg(not(feature = "introspection"))]
reporter.fire(
state,
Event::UpdateExecStats {
executions,
time: cur,
phantom: PhantomData,
},
)?;
// If performance monitor are requested, fire the `UpdatePerfMonitor` event
#[cfg(feature = "introspection")]
{
state
.introspection_monitor_mut()
.set_current_time(libafl_bolts::cpu::read_time_counter());
// Send the current monitor over to the manager. This `.clone` shouldn't be
// costly as `ClientPerfMonitor` impls `Copy` since it only contains `u64`s
reporter.fire(
state,
Event::UpdateExecStats {
Event::UpdatePerfMonitor {
executions,
time: cur,
introspection_monitor: Box::new(state.introspection_monitor().clone()),
phantom: PhantomData,
},
)?;
}
// If performance monitor are requested, fire the `UpdatePerfMonitor` event
#[cfg(feature = "introspection")]
{
state
.introspection_monitor_mut()
.set_current_time(libafl_bolts::cpu::read_time_counter());
*state.last_report_time_mut() = Some(cur);
// Send the current monitor over to the manager. This `.clone` shouldn't be
// costly as `ClientPerfMonitor` impls `Copy` since it only contains `u64`s
self.fire(
state,
Event::UpdatePerfMonitor {
executions,
time: cur,
introspection_monitor: Box::new(state.introspection_monitor().clone()),
phantom: PhantomData,
},
)?;
}
Ok(())
}
// If we are measuring scalability stuff..
#[cfg(feature = "scalability_introspection")]
{
let imported_with_observer = state.scalability_monitor().testcase_with_observers;
let imported_without_observer = state.scalability_monitor().testcase_without_observers;
/// [`ProgressReporter`] report progress to the broker.
pub trait ProgressReporter<S> {
/// Given the last time, if `monitor_timeout` seconds passed, send off an info/monitor/heartbeat message to the broker.
/// Returns the new `last` time (so the old one, unless `monitor_timeout` time has passed and monitor have been sent)
/// Will return an [`Error`], if the stats could not be sent.
/// [`std_maybe_report_progress`] is the standard implementation that you can call.
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error>;
self.fire(
state,
Event::UpdateUserStats {
name: Cow::from("total imported"),
value: UserStats::new(
UserStatsValue::Number(
(imported_with_observer + imported_without_observer) as u64,
),
AggregatorOps::Avg,
),
phantom: PhantomData,
},
)?;
}
/// Send off an info/monitor/heartbeat message to the broker.
/// Will return an [`Error`], if the stats could not be sent.
/// [`std_report_progress`] is the standard implementation that you can call.
fn report_progress(&mut self, state: &mut S) -> Result<(), Error>;
}
*state.last_report_time_mut() = Some(cur);
/// Restartable trait
pub trait EventRestarter<S> {
/// For restarting event managers, implement a way to forward state to their next peers.
/// You *must* ensure that [`HasCurrentStageId::on_restart`] will be invoked in this method, by you
/// or an internal [`EventRestarter`], before the state is saved for recovery.
/// [`std_on_restart`] is the standard implementation that you can call.
fn on_restart(&mut self, state: &mut S) -> Result<(), Error>;
}
/// Default implementation of [`EventRestarter::on_restart`] for implementors with the given
/// constraints
pub fn std_on_restart<S>(
restarter: &mut (impl EventRestarter<S> + ManagerExit),
state: &mut S,
) -> Result<(), Error>
where
S: HasCurrentStageId,
{
state.on_restart()?;
restarter.await_restart_safe();
Ok(())
}
/// The class that implements this must be able to serialize an observer.
pub trait CanSerializeObserver<OT> {
/// Do serialize the observer
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error>;
}
/// Routines called before exiting
pub trait ManagerExit {
/// Send information that this client is exiting.
/// No need to restart us any longer, and no need to print an error, either.
fn send_exiting(&mut self) -> Result<(), Error>;
/// Block until we are safe to exit, usually called inside `on_restart`.
fn await_restart_safe(&mut self);
}
/// [`EventProcessor`] process all the incoming messages
pub trait EventProcessor<E, S, Z> {
/// Lookup for incoming events and process them.
/// Return the number of processes events or an error
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error>;
/// Shutdown gracefully; typically without saving state.
fn on_shutdown(&mut self) -> Result<(), Error>;
}
/// The id of this `EventManager`.
/// For multi processed `EventManagers`,
/// each connected client should have a unique ids.
pub trait HasEventManagerId {
/// The id of this manager. For Multiprocessed `EventManagers`,
/// each client should have a unique ids.
fn mgr_id(&self) -> EventManagerId;
}
/// An eventmgr for tests, and as placeholder if you really don't need an event manager.
#[derive(Copy, Clone, Debug, Default)]
pub struct NopEventManager {}
impl NopEventManager {
/// Creates a new [`NopEventManager`]
#[must_use]
pub fn new() -> Self {
NopEventManager {}
}
}
impl<I, S> EventFirer<I, S> for NopEventManager {
fn should_send(&self) -> bool {
true
}
fn fire(&mut self, _state: &mut S, _event: Event<I>) -> Result<(), Error> {
Ok(())
}
}
/// Restartable trait
pub trait EventRestarter: UsesState {
/// For restarting event managers, implement a way to forward state to their next peers.
/// You *must* ensure that [`HasCurrentStageId::on_restart`] will be invoked in this method, by you
/// or an internal [`EventRestarter`], before the state is saved for recovery.
#[inline]
fn on_restart(&mut self, state: &mut Self::State) -> Result<(), Error> {
state.on_restart()?;
self.await_restart_safe();
Ok(())
impl<S> EventRestarter<S> for NopEventManager
where
S: HasCurrentStageId,
{
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
std_on_restart(self, state)
}
}
impl ManagerExit for NopEventManager {
/// Send information that this client is exiting.
/// No need to restart us any longer, and no need to print an error, either.
fn send_exiting(&mut self) -> Result<(), Error> {
Ok(())
}
/// Block until we are safe to exit, usually called inside `on_restart`.
#[inline]
fn await_restart_safe(&mut self) {}
}
/// [`EventProcessor`] process all the incoming messages
pub trait EventProcessor<E, Z>: UsesState {
/// Lookup for incoming events and process them.
/// Return the number of processes events or an error
fn process(
&mut self,
fuzzer: &mut Z,
state: &mut Self::State,
executor: &mut E,
) -> Result<usize, Error>;
/// Shutdown gracefully; typically without saving state.
fn on_shutdown(&mut self) -> Result<(), Error>;
}
/// The id of this [`EventManager`].
/// For multi processed [`EventManager`]s,
/// each connected client should have a unique ids.
pub trait HasEventManagerId {
/// The id of this manager. For Multiprocessed [`EventManager`]s,
/// each client should have a unique ids.
fn mgr_id(&self) -> EventManagerId;
}
/// [`EventManager`] is the main communications hub.
/// For the "normal" multi-processed mode, you may want to look into [`LlmpRestartingEventManager`]
pub trait EventManager<E, Z>:
EventFirer + EventProcessor<E, Z> + EventRestarter + HasEventManagerId + ProgressReporter
where
Self::State: HasMetadata + HasExecutions + HasLastReportTime,
{
}
/// An eventmgr for tests, and as placeholder if you really don't need an event manager.
#[derive(Copy, Clone, Debug)]
pub struct NopEventManager<S> {
phantom: PhantomData<S>,
}
impl<S> NopEventManager<S> {
/// Creates a new [`NopEventManager`]
#[must_use]
pub fn new() -> Self {
NopEventManager {
phantom: PhantomData,
}
}
}
impl<S> Default for NopEventManager<S> {
fn default() -> Self {
Self::new()
}
}
impl<S> UsesState for NopEventManager<S>
where
S: State,
{
type State = S;
}
impl<S> EventFirer for NopEventManager<S>
where
S: State,
{
fn should_send(&self) -> bool {
true
}
fn fire(
&mut self,
_state: &mut Self::State,
_event: Event<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
Ok(())
}
}
impl<S> EventRestarter for NopEventManager<S> where S: State {}
impl<E, S, Z> EventProcessor<E, Z> for NopEventManager<S>
where
S: State + HasExecutions,
{
impl<E, S, Z> EventProcessor<E, S, Z> for NopEventManager {
fn process(
&mut self,
_fuzzer: &mut Z,
_state: &mut Self::State,
_state: &mut S,
_executor: &mut E,
) -> Result<usize, Error> {
Ok(0)
@ -648,23 +663,36 @@ where
}
}
impl<E, S, Z> EventManager<E, Z> for NopEventManager<S> where
S: State + HasExecutions + HasLastReportTime + HasMetadata
impl<OT> CanSerializeObserver<OT> for NopEventManager
where
OT: Serialize,
{
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
Ok(Some(postcard::to_allocvec(observers)?))
}
}
impl<S> ProgressReporter for NopEventManager<S> where
S: State + HasExecutions + HasLastReportTime + HasMetadata
{
impl<S> ProgressReporter<S> for NopEventManager {
fn maybe_report_progress(
&mut self,
_state: &mut S,
_monitor_timeout: Duration,
) -> Result<(), Error> {
Ok(())
}
fn report_progress(&mut self, _state: &mut S) -> Result<(), Error> {
Ok(())
}
}
impl<S> HasEventManagerId for NopEventManager<S> {
impl HasEventManagerId for NopEventManager {
fn mgr_id(&self) -> EventManagerId {
EventManagerId(0)
}
}
/// An [`EventManager`] type that wraps another manager, but captures a `monitor` type as well.
/// An `EventManager` type that wraps another manager, but captures a `monitor` type as well.
/// This is useful to keep the same API between managers with and without an internal `monitor`.
#[derive(Copy, Clone, Debug)]
pub struct MonitorTypedEventManager<EM, M> {
@ -673,7 +701,7 @@ pub struct MonitorTypedEventManager<EM, M> {
}
impl<EM, M> MonitorTypedEventManager<EM, M> {
/// Creates a new [`EventManager`] that wraps another manager, but captures a `monitor` type as well.
/// Creates a new `EventManager` that wraps another manager, but captures a `monitor` type as well.
#[must_use]
pub fn new(inner: EM) -> Self {
MonitorTypedEventManager {
@ -683,63 +711,58 @@ impl<EM, M> MonitorTypedEventManager<EM, M> {
}
}
impl<EM, M> UsesState for MonitorTypedEventManager<EM, M>
impl<EM, M, OT> CanSerializeObserver<OT> for MonitorTypedEventManager<EM, M>
where
EM: UsesState,
OT: Serialize,
{
type State = EM::State;
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
Ok(Some(postcard::to_allocvec(observers)?))
}
}
impl<EM, M> EventFirer for MonitorTypedEventManager<EM, M>
impl<EM, I, M, S> EventFirer<I, S> for MonitorTypedEventManager<EM, M>
where
EM: EventFirer,
EM: EventFirer<I, S>,
{
fn should_send(&self) -> bool {
true
}
#[inline]
fn fire(
&mut self,
state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
fn fire(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error> {
self.inner.fire(state, event)
}
#[inline]
fn log(
&mut self,
state: &mut Self::State,
state: &mut S,
severity_level: LogSeverity,
message: String,
) -> Result<(), Error> {
self.inner.log(state, severity_level, message)
}
#[inline]
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error>
where
OT: ObserversTuple<<Self as UsesInput>::Input, Self::State> + Serialize,
{
self.inner.serialize_observers(observers)
}
#[inline]
fn configuration(&self) -> EventConfig {
self.inner.configuration()
}
}
impl<EM, M> EventRestarter for MonitorTypedEventManager<EM, M>
impl<EM, M, S> EventRestarter<S> for MonitorTypedEventManager<EM, M>
where
EM: EventRestarter,
EM: EventRestarter<S>,
{
#[inline]
fn on_restart(&mut self, state: &mut Self::State) -> Result<(), Error> {
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
self.inner.on_restart(state)
}
}
impl<EM, M> ManagerExit for MonitorTypedEventManager<EM, M>
where
EM: ManagerExit,
{
#[inline]
fn send_exiting(&mut self) -> Result<(), Error> {
self.inner.send_exiting()
@ -751,17 +774,12 @@ where
}
}
impl<E, EM, M, Z> EventProcessor<E, Z> for MonitorTypedEventManager<EM, M>
impl<E, EM, M, S, Z> EventProcessor<E, S, Z> for MonitorTypedEventManager<EM, M>
where
EM: EventProcessor<E, Z>,
EM: EventProcessor<E, S, Z>,
{
#[inline]
fn process(
&mut self,
fuzzer: &mut Z,
state: &mut Self::State,
executor: &mut E,
) -> Result<usize, Error> {
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
self.inner.process(fuzzer, state, executor)
}
@ -770,30 +788,21 @@ where
}
}
impl<E, EM, M, Z> EventManager<E, Z> for MonitorTypedEventManager<EM, M>
impl<EM, M, S> ProgressReporter<S> for MonitorTypedEventManager<EM, M>
where
EM: EventManager<E, Z>,
Self::State: HasLastReportTime + HasExecutions + HasMetadata,
{
}
impl<EM, M> ProgressReporter for MonitorTypedEventManager<EM, M>
where
Self: UsesState,
EM: ProgressReporter<State = Self::State>,
Self::State: HasLastReportTime + HasExecutions + HasMetadata,
EM: ProgressReporter<S>,
{
#[inline]
fn maybe_report_progress(
&mut self,
state: &mut Self::State,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
self.inner.maybe_report_progress(state, monitor_timeout)
}
#[inline]
fn report_progress(&mut self, state: &mut Self::State) -> Result<(), Error> {
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
self.inner.report_progress(state)
}
}
@ -830,56 +839,6 @@ pub trait AdaptiveSerializer {
/// A [`Handle`] to the time observer to determine the `time_factor`
fn time_ref(&self) -> &Option<Handle<TimeObserver>>;
/// Serialize the observer using the `time_factor` and `percentage_threshold`.
/// These parameters are unique to each of the different types of `EventManager`
fn serialize_observers_adaptive<S, OT>(
&mut self,
observers: &OT,
time_factor: u32,
percentage_threshold: usize,
) -> Result<Option<Vec<u8>>, Error>
where
OT: ObserversTuple<S::Input, S> + Serialize,
S: UsesInput,
{
match self.time_ref() {
Some(t) => {
let exec_time = observers
.get(t)
.map(|o| o.last_runtime().unwrap_or(Duration::ZERO))
.unwrap();
let mut must_ser = (self.serialization_time() + self.deserialization_time())
* time_factor
< exec_time;
if must_ser {
*self.should_serialize_cnt_mut() += 1;
}
if self.serializations_cnt() > 32 {
must_ser = (self.should_serialize_cnt() * 100 / self.serializations_cnt())
> percentage_threshold;
}
if self.serialization_time() == Duration::ZERO
|| must_ser
|| self.serializations_cnt().trailing_zeros() >= 8
{
let start = current_time();
let ser = postcard::to_allocvec(observers)?;
*self.serialization_time_mut() = current_time() - start;
*self.serializations_cnt_mut() += 1;
Ok(Some(ser))
} else {
*self.serializations_cnt_mut() += 1;
Ok(None)
}
}
None => Ok(None),
}
}
}
#[cfg(test)]

View File

@ -51,10 +51,7 @@ const DUMMY_BYTE: u8 = 0x14;
/// An owned TCP message for multi machine
#[derive(Clone, Debug)]
// #[serde(bound = "I: serde::de::DeserializeOwned")]
pub enum MultiMachineMsg<'a, I>
where
I: Input,
{
pub enum MultiMachineMsg<'a, I> {
/// A raw llmp message (not deserialized)
LlmpMsg(OwnedRef<'a, [u8]>),
@ -66,10 +63,7 @@ where
unsafe impl<I: Input> Send for MultiMachineMsg<'_, I> {}
unsafe impl<I: Input> Sync for MultiMachineMsg<'_, I> {}
impl<'a, I> MultiMachineMsg<'a, I>
where
I: Input,
{
impl<'a, I> MultiMachineMsg<'a, I> {
/// Create a new [`MultiMachineMsg`] as event.
///
/// # Safety
@ -165,10 +159,7 @@ pub struct NodeDescriptor<A> {
/// passed to the `on_new_message` method (or rather, the memory it points to),
/// lives sufficiently long for an async background task to process it.
#[derive(Debug)]
pub struct TcpMultiMachineHooks<A, I>
where
I: Input,
{
pub struct TcpMultiMachineHooks<A, I> {
/// The sender hooks
pub sender: TcpMultiMachineLlmpSenderHook<A, I>,
/// The hooks

View File

@ -1,12 +1,9 @@
//! A very simple event manager, that just supports log outputs, but no multiprocessing
use alloc::vec::Vec;
use core::{fmt::Debug, marker::PhantomData};
#[cfg(feature = "std")]
use core::{
sync::atomic::{compiler_fence, Ordering},
time::Duration,
};
use core::sync::atomic::{compiler_fence, Ordering};
use core::{fmt::Debug, marker::PhantomData, time::Duration};
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
use libafl_bolts::os::startable_self;
@ -18,25 +15,28 @@ use libafl_bolts::ClientId;
#[cfg(feature = "std")]
use libafl_bolts::{os::CTRL_C_EXIT, shmem::ShMemProvider, staterestore::StateRestorer};
#[cfg(feature = "std")]
use serde::{de::DeserializeOwned, Serialize};
use serde::de::DeserializeOwned;
use serde::Serialize;
use super::ProgressReporter;
use super::{std_on_restart, ProgressReporter};
#[cfg(all(unix, feature = "std", not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE;
use crate::{
corpus::Corpus,
events::{
BrokerEventResult, Event, EventFirer, EventManager, EventManagerId, EventProcessor,
EventRestarter, HasEventManagerId,
std_maybe_report_progress, std_report_progress, BrokerEventResult, CanSerializeObserver,
Event, EventFirer, EventManagerId, EventProcessor, EventRestarter, HasEventManagerId,
ManagerExit,
},
inputs::UsesInput,
monitors::Monitor,
state::{HasExecutions, HasLastReportTime, State, Stoppable, UsesState},
stages::HasCurrentStageId,
state::{HasCorpus, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable},
Error, HasMetadata,
};
#[cfg(feature = "std")]
use crate::{
monitors::{ClientStats, SimplePrintingMonitor},
state::{HasCorpus, HasSolutions},
state::HasSolutions,
};
/// The llmp connection from the actual fuzzer to the process supervising it
@ -46,21 +46,18 @@ const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER";
const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
/// A simple, single-threaded event manager that just logs
pub struct SimpleEventManager<MT, S>
where
S: UsesInput + Stoppable,
{
pub struct SimpleEventManager<I, MT, S> {
/// The monitor
monitor: MT,
/// The events that happened since the last `handle_in_broker`
events: Vec<Event<S::Input>>,
events: Vec<Event<I>>,
phantom: PhantomData<S>,
}
impl<MT, S> Debug for SimpleEventManager<MT, S>
impl<I, MT, S> Debug for SimpleEventManager<I, MT, S>
where
MT: Debug,
S: UsesInput + Stoppable,
I: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SimpleEventManager")
@ -71,27 +68,17 @@ where
}
}
impl<MT, S> UsesState for SimpleEventManager<MT, S>
where
S: State,
{
type State = S;
}
impl<MT, S> EventFirer for SimpleEventManager<MT, S>
impl<I, MT, S> EventFirer<I, S> for SimpleEventManager<I, MT, S>
where
I: Debug,
MT: Monitor,
S: State,
S: Stoppable,
{
fn should_send(&self) -> bool {
true
}
fn fire(
&mut self,
_state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
fn fire(&mut self, _state: &mut S, event: Event<I>) -> Result<(), Error> {
match Self::handle_in_broker(&mut self.monitor, &event)? {
BrokerEventResult::Forward => self.events.push(event),
BrokerEventResult::Handled => (),
@ -100,17 +87,28 @@ where
}
}
impl<MT, S> EventRestarter for SimpleEventManager<MT, S>
where
MT: Monitor,
S: State,
{
impl<I, MT, S> ManagerExit for SimpleEventManager<I, MT, S> {
fn send_exiting(&mut self) -> Result<(), Error> {
Ok(())
}
fn await_restart_safe(&mut self) {}
}
impl<E, MT, S, Z> EventProcessor<E, Z> for SimpleEventManager<MT, S>
impl<I, MT, S> EventRestarter<S> for SimpleEventManager<I, MT, S>
where
S: HasCurrentStageId,
{
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
std_on_restart(self, state)
}
}
impl<E, I, MT, S, Z> EventProcessor<E, S, Z> for SimpleEventManager<I, MT, S>
where
I: Debug,
MT: Monitor,
S: State,
S: Stoppable,
{
fn process(
&mut self,
@ -130,34 +128,51 @@ where
}
}
impl<E, MT, S, Z> EventManager<E, Z> for SimpleEventManager<MT, S>
impl<I, MT, OT, S> CanSerializeObserver<OT> for SimpleEventManager<I, MT, S>
where
MT: Monitor,
S: State + HasExecutions + HasLastReportTime + HasMetadata,
OT: Serialize,
{
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
Ok(Some(postcard::to_allocvec(observers)?))
}
}
impl<MT, S> ProgressReporter for SimpleEventManager<MT, S>
impl<I, MT, S> ProgressReporter<S> for SimpleEventManager<I, MT, S>
where
I: Debug,
MT: Monitor,
S: State + HasExecutions + HasMetadata + HasLastReportTime,
S: HasMetadata
+ HasExecutions
+ HasLastReportTime
+ Stoppable
+ HasCorpus
+ MaybeHasClientPerfMonitor,
S::Corpus: Corpus<Input = I>,
{
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
std_maybe_report_progress(self, state, monitor_timeout)
}
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
std_report_progress(self, state)
}
}
impl<MT, S> HasEventManagerId for SimpleEventManager<MT, S>
where
MT: Monitor,
S: UsesInput + Stoppable,
{
impl<I, MT, S> HasEventManagerId for SimpleEventManager<I, MT, S> {
fn mgr_id(&self) -> EventManagerId {
EventManagerId(0)
}
}
#[cfg(feature = "std")]
impl<S> SimpleEventManager<SimplePrintingMonitor, S>
impl<I, S> SimpleEventManager<I, SimplePrintingMonitor, S>
where
S: UsesInput + Stoppable,
I: Debug,
S: Stoppable,
{
/// Creates a [`SimpleEventManager`] that just prints to `stdout`.
#[must_use]
@ -166,10 +181,11 @@ where
}
}
impl<MT, S> SimpleEventManager<MT, S>
impl<I, MT, S> SimpleEventManager<I, MT, S>
where
MT: Monitor, //TODO CE: CustomEvent,
S: UsesInput + Stoppable,
I: Debug,
MT: Monitor,
S: Stoppable,
{
/// Creates a new [`SimpleEventManager`].
pub fn new(monitor: MT) -> Self {
@ -182,10 +198,7 @@ where
/// Handle arriving events in the broker
#[expect(clippy::unnecessary_wraps)]
fn handle_in_broker(
monitor: &mut MT,
event: &Event<S::Input>,
) -> Result<BrokerEventResult, Error> {
fn handle_in_broker(monitor: &mut MT, event: &Event<I>) -> Result<BrokerEventResult, Error> {
match event {
Event::NewTestcase { corpus_size, .. } => {
monitor.client_stats_insert(ClientId(0));
@ -254,7 +267,7 @@ where
// Handle arriving events in the client
#[allow(clippy::unused_self)]
fn handle_in_client(&mut self, state: &mut S, event: &Event<S::Input>) -> Result<(), Error> {
fn handle_in_client(&mut self, state: &mut S, event: &Event<I>) -> Result<(), Error> {
match event {
Event::Stop => {
state.request_stop();
@ -274,52 +287,39 @@ where
/// `restarter` will start a new process each time the child crashes or times out.
#[cfg(feature = "std")]
#[derive(Debug)]
pub struct SimpleRestartingEventManager<MT, S, SP>
pub struct SimpleRestartingEventManager<I, MT, S, SP>
where
S: UsesInput + Stoppable,
SP: ShMemProvider, //CE: CustomEvent<I, OT>,
SP: ShMemProvider,
{
/// The actual simple event mgr
simple_event_mgr: SimpleEventManager<MT, S>,
inner: SimpleEventManager<I, MT, S>,
/// [`StateRestorer`] for restarts
staterestorer: StateRestorer<SP>,
}
#[cfg(feature = "std")]
impl<MT, S, SP> UsesState for SimpleRestartingEventManager<MT, S, SP>
where
S: State,
SP: ShMemProvider,
{
type State = S;
}
#[cfg(feature = "std")]
impl<MT, S, SP> EventFirer for SimpleRestartingEventManager<MT, S, SP>
impl<I, MT, S, SP> EventFirer<I, S> for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Debug,
MT: Monitor,
S: State,
S: Stoppable,
SP: ShMemProvider,
{
fn should_send(&self) -> bool {
true
}
fn fire(
&mut self,
_state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
self.simple_event_mgr.fire(_state, event)
fn fire(&mut self, _state: &mut S, event: Event<I>) -> Result<(), Error> {
self.inner.fire(_state, event)
}
}
#[cfg(feature = "std")]
impl<MT, S, SP> EventRestarter for SimpleRestartingEventManager<MT, S, SP>
impl<I, MT, S, SP> EventRestarter<S> for SimpleRestartingEventManager<I, MT, S, SP>
where
MT: Monitor,
S: State,
SP: ShMemProvider,
S: HasCurrentStageId + Serialize,
MT: Monitor,
{
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
@ -329,84 +329,109 @@ where
self.staterestorer.reset();
self.staterestorer.save(&(
state,
self.simple_event_mgr.monitor.start_time(),
self.simple_event_mgr.monitor.client_stats(),
self.inner.monitor.start_time(),
self.inner.monitor.client_stats(),
))
}
fn send_exiting(&mut self) -> Result<(), Error> {
self.staterestorer.send_exiting();
Ok(())
}
}
#[cfg(feature = "std")]
impl<E, MT, S, SP, Z> EventProcessor<E, Z> for SimpleRestartingEventManager<MT, S, SP>
impl<I, MT, OT, S, SP> CanSerializeObserver<OT> for SimpleRestartingEventManager<I, MT, S, SP>
where
SP: ShMemProvider,
OT: Serialize,
{
fn serialize_observers(&mut self, observers: &OT) -> Result<Option<Vec<u8>>, Error> {
Ok(Some(postcard::to_allocvec(observers)?))
}
}
#[cfg(feature = "std")]
impl<I, MT, S, SP> ManagerExit for SimpleRestartingEventManager<I, MT, S, SP>
where
MT: Monitor,
S: State + HasExecutions,
SP: ShMemProvider,
{
fn process(
&mut self,
fuzzer: &mut Z,
state: &mut Self::State,
executor: &mut E,
) -> Result<usize, Error> {
self.simple_event_mgr.process(fuzzer, state, executor)
fn send_exiting(&mut self) -> Result<(), Error> {
self.staterestorer.send_exiting();
Ok(())
}
/// Block until we are safe to exit, usually called inside `on_restart`.
#[inline]
fn await_restart_safe(&mut self) {}
}
#[cfg(feature = "std")]
impl<E, I, MT, S, SP, Z> EventProcessor<E, S, Z> for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Debug,
MT: Monitor,
SP: ShMemProvider,
S: Stoppable,
{
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
self.inner.process(fuzzer, state, executor)
}
fn on_shutdown(&mut self) -> Result<(), Error> {
self.send_exiting()
}
}
#[cfg(feature = "std")]
impl<E, MT, S, SP, Z> EventManager<E, Z> for SimpleRestartingEventManager<MT, S, SP>
impl<I, MT, S, SP> ProgressReporter<S> for SimpleRestartingEventManager<I, MT, S, SP>
where
I: Debug,
MT: Monitor,
S: State + HasExecutions + HasMetadata + HasLastReportTime + Serialize,
SP: ShMemProvider,
S: HasExecutions
+ HasMetadata
+ HasLastReportTime
+ Stoppable
+ HasCorpus
+ MaybeHasClientPerfMonitor,
S::Corpus: Corpus<Input = I>,
{
}
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
std_maybe_report_progress(self, state, monitor_timeout)
}
#[cfg(feature = "std")]
impl<MT, S, SP> ProgressReporter for SimpleRestartingEventManager<MT, S, SP>
where
MT: Monitor,
S: State + HasExecutions + HasMetadata + HasLastReportTime,
SP: ShMemProvider,
{
}
#[cfg(feature = "std")]
impl<MT, S, SP> HasEventManagerId for SimpleRestartingEventManager<MT, S, SP>
where
MT: Monitor,
S: UsesInput + Stoppable,
SP: ShMemProvider,
{
fn mgr_id(&self) -> EventManagerId {
self.simple_event_mgr.mgr_id()
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
std_report_progress(self, state)
}
}
#[cfg(feature = "std")]
impl<MT, S, SP> SimpleRestartingEventManager<MT, S, SP>
impl<I, MT, S, SP> HasEventManagerId for SimpleRestartingEventManager<I, MT, S, SP>
where
S: UsesInput + Stoppable,
SP: ShMemProvider,
MT: Monitor, //TODO CE: CustomEvent,
{
fn mgr_id(&self) -> EventManagerId {
self.inner.mgr_id()
}
}
#[cfg(feature = "std")]
impl<I, MT, S, SP> SimpleRestartingEventManager<I, MT, S, SP>
where
I: Debug,
MT: Monitor,
S: Stoppable,
SP: ShMemProvider,
{
/// Creates a new [`SimpleEventManager`].
fn launched(monitor: MT, staterestorer: StateRestorer<SP>) -> Self {
Self {
staterestorer,
simple_event_mgr: SimpleEventManager::new(monitor),
inner: SimpleEventManager::new(monitor),
}
}
/// Launch the simple restarting manager.
/// This [`EventManager`] is simple and single threaded,
/// This `EventManager` is simple and single threaded,
/// but can still used shared maps to recover from crashes and timeouts.
pub fn launch(mut monitor: MT, shmem_provider: &mut SP) -> Result<(Option<S>, Self), Error>
where

View File

@ -38,20 +38,25 @@ use tokio::{
};
use typed_builder::TypedBuilder;
use super::{std_maybe_report_progress, std_report_progress, ManagerExit};
#[cfg(all(unix, not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE;
use crate::{
corpus::Corpus,
events::{
BrokerEventResult, Event, EventConfig, EventFirer, EventManager, EventManagerHooksTuple,
std_on_restart, BrokerEventResult, Event, EventConfig, EventFirer, EventManagerHooksTuple,
EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, ProgressReporter,
},
executors::{Executor, HasObservers},
fuzzer::{EvaluatorObservers, ExecutionProcessor},
inputs::{Input, UsesInput},
inputs::Input,
monitors::Monitor,
observers::ObserversTuple,
state::{HasCorpus, HasExecutions, HasImported, HasLastReportTime, State, UsesState},
stages::HasCurrentStageId,
state::{
HasCorpus, HasExecutions, HasImported, HasLastReportTime, MaybeHasClientPerfMonitor,
Stoppable,
},
Error, HasMetadata,
};
@ -403,12 +408,8 @@ where
}
}
/// An [`EventManager`] that forwards all events to other attached via tcp.
pub struct TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State,
{
/// An `EventManager` that forwards all events to other attached via tcp.
pub struct TcpEventManager<EMH, S> {
/// We send message every `throttle` second
throttle: Option<Duration>,
/// When we sent the last message
@ -427,10 +428,7 @@ where
phantom: PhantomData<S>,
}
impl<S> TcpEventManager<(), S>
where
S: State,
{
impl<S> TcpEventManager<(), S> {
/// Create a builder for [`TcpEventManager`]
#[must_use]
pub fn builder() -> TcpEventManagerBuilder<(), S> {
@ -474,11 +472,7 @@ impl<S> TcpEventManagerBuilder<(), S> {
}
}
impl<EMH, S> TcpEventManagerBuilder<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata,
{
impl<EMH, S> TcpEventManagerBuilder<EMH, S> {
/// Set the throttle
#[must_use]
pub fn throttle(mut self, throttle: Duration) -> Self {
@ -546,11 +540,7 @@ where
}
}
impl<EMH, S> core::fmt::Debug for TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State,
{
impl<EMH, S> core::fmt::Debug for TcpEventManager<EMH, S> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut debug_struct = f.debug_struct("TcpEventManager");
let debug = debug_struct.field("tcp", &self.tcp);
@ -564,11 +554,7 @@ where
}
}
impl<EMH, S> Drop for TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State,
{
impl<EMH, S> Drop for TcpEventManager<EMH, S> {
/// TCP clients will have to wait until their pages are mapped by somebody.
fn drop(&mut self) {
self.await_restart_safe();
@ -577,11 +563,10 @@ where
impl<EMH, S> TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasExecutions + HasMetadata + HasImported + HasCorpus + Stoppable,
{
/// Write the client id for a client [`EventManager`] to env vars
/// Write the client id for a client `EventManager` to env vars
pub fn to_env(&self, env_name: &str) {
env::set_var(env_name, format!("{}", self.client_id.0));
}
@ -593,11 +578,11 @@ where
executor: &mut E,
state: &mut S,
client_id: ClientId,
event: Event<S::Input>,
event: Event<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error>
where
E: Executor<Self, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
E::Observers: Serialize + ObserversTuple<S::Input, S>,
E::Observers: Serialize + ObserversTuple<<S::Corpus as Corpus>::Input, S>,
for<'a> E::Observers: Deserialize<'a>,
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>,
@ -621,16 +606,8 @@ where
{
let observers: E::Observers =
postcard::from_bytes(observers_buf.as_ref().unwrap())?;
#[cfg(feature = "scalability_introspection")]
{
state.scalability_monitor_mut().testcase_with_observers += 1;
}
fuzzer.evaluate_execution(state, self, input, &observers, &exit_kind, false)?
} else {
#[cfg(feature = "scalability_introspection")]
{
state.scalability_monitor_mut().testcase_without_observers += 1;
}
fuzzer.evaluate_input_with_observers(state, executor, self, input, false)?
};
if let Some(item) = _res.1 {
@ -653,11 +630,7 @@ where
}
}
impl<EMH, S> TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State,
{
impl<EMH, S> TcpEventManager<EMH, S> {
/// Send information that this client is exiting.
/// The other side may free up all allocated memory.
/// We are no longer allowed to send anything afterwards.
@ -668,18 +641,11 @@ where
}
}
impl<EMH, S> UsesState for TcpEventManager<EMH, S>
impl<EMH, S> EventFirer<<S::Corpus as Corpus>::Input, S> for TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State,
{
type State = S;
}
impl<EMH, S> EventFirer for TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus,
<S::Corpus as Corpus>::Input: Serialize,
{
fn should_send(&self) -> bool {
if let Some(throttle) = self.throttle {
@ -691,8 +657,8 @@ where
fn fire(
&mut self,
_state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
_state: &mut S,
event: Event<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> {
let serialized = postcard::to_allocvec(&event)?;
@ -713,36 +679,27 @@ where
}
}
impl<EMH, S> EventRestarter for TcpEventManager<EMH, S>
impl<EMH, S> EventRestarter<S> for TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State,
S: HasCurrentStageId,
{
/// The TCP client needs to wait until a broker has mapped all pages before shutting down.
/// Otherwise, the OS may already have removed the shared maps.
fn await_restart_safe(&mut self) {
// wait until we can drop the message safely.
//self.tcp.await_safe_to_unmap_blocking();
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
std_on_restart(self, state)
}
}
impl<E, EMH, S, Z> EventProcessor<E, Z> for TcpEventManager<EMH, S>
impl<E, EMH, S, Z> EventProcessor<E, S, Z> for TcpEventManager<EMH, S>
where
E: HasObservers + Executor<Self, <S::Corpus as Corpus>::Input, S, Z>,
E::Observers: Serialize + ObserversTuple<S::Input, S>,
E::Observers: Serialize + ObserversTuple<<S::Corpus as Corpus>::Input, S>,
for<'a> E::Observers: Deserialize<'a>,
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasExecutions + HasMetadata + HasImported + HasCorpus + Stoppable,
<S::Corpus as Corpus>::Input: DeserializeOwned,
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>,
{
fn process(
&mut self,
fuzzer: &mut Z,
state: &mut Self::State,
executor: &mut E,
) -> Result<usize, Error> {
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
// TODO: Get around local event copy by moving handle_in_client
let self_id = self.client_id;
let mut len_buf = [0_u8; 4];
@ -801,31 +758,41 @@ where
}
}
impl<E, EMH, S, Z> EventManager<E, Z> for TcpEventManager<EMH, S>
where
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>,
S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
Z: ExecutionProcessor<Self, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, Self, <S::Corpus as Corpus>::Input, S>,
{
impl<EMH, S> ManagerExit for TcpEventManager<EMH, S> {
/// The TCP client needs to wait until a broker has mapped all pages before shutting down.
/// Otherwise, the OS may already have removed the shared maps.
fn await_restart_safe(&mut self) {
// wait until we can drop the message safely.
//self.tcp.await_safe_to_unmap_blocking();
}
fn send_exiting(&mut self) -> Result<(), Error> {
//TODO: Should not be needed since TCP does that for us
//self.tcp.sender.send_exiting()
Ok(())
}
}
impl<EMH, S> ProgressReporter for TcpEventManager<EMH, S>
impl<EMH, S> ProgressReporter<S> for TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasLastReportTime,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: Serialize,
S: HasExecutions + HasMetadata + HasLastReportTime + HasCorpus + MaybeHasClientPerfMonitor,
{
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
std_maybe_report_progress(self, state, monitor_timeout)
}
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
std_report_progress(self, state)
}
}
impl<EMH, S> HasEventManagerId for TcpEventManager<EMH, S>
where
EMH: EventManagerHooksTuple<S>,
S: State,
{
impl<EMH, S> HasEventManagerId for TcpEventManager<EMH, S> {
/// Gets the id assigned to this staterestorer.
fn mgr_id(&self) -> EventManagerId {
EventManagerId(self.client_id.0 as usize)
@ -836,10 +803,7 @@ where
#[derive(Debug)]
pub struct TcpRestartingEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider + 'static,
//CE: CustomEvent<I>,
SP: ShMemProvider,
{
/// The embedded TCP event manager
tcp_mgr: TcpEventManager<EMH, S>,
@ -849,29 +813,33 @@ where
save_state: bool,
}
impl<EMH, S, SP> UsesState for TcpRestartingEventManager<EMH, S, SP>
impl<EMH, S, SP> ProgressReporter<S> for TcpRestartingEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider + 'static,
{
type State = S;
}
impl<EMH, S, SP> ProgressReporter for TcpRestartingEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasLastReportTime,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasMetadata + HasExecutions + HasLastReportTime + HasCorpus + MaybeHasClientPerfMonitor,
<S::Corpus as Corpus>::Input: Serialize,
SP: ShMemProvider,
{
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
std_maybe_report_progress(self, state, monitor_timeout)
}
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
std_report_progress(self, state)
}
}
impl<EMH, S, SP> EventFirer for TcpRestartingEventManager<EMH, S, SP>
impl<EMH, S, SP> EventFirer<<S::Corpus as Corpus>::Input, S>
for TcpRestartingEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus,
<S::Corpus as Corpus>::Input: Serialize,
SP: ShMemProvider,
S: State,
//CE: CustomEvent<I>,
{
fn should_send(&self) -> bool {
self.tcp_mgr.should_send()
@ -879,8 +847,8 @@ where
fn fire(
&mut self,
state: &mut Self::State,
event: Event<<Self::State as UsesInput>::Input>,
state: &mut S,
event: Event<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> {
// Check if we are going to crash in the event, in which case we store our current state for the next runner
self.tcp_mgr.fire(state, event)
@ -891,12 +859,9 @@ where
}
}
impl<EMH, S, SP> EventRestarter for TcpRestartingEventManager<EMH, S, SP>
impl<EMH, S, SP> ManagerExit for TcpRestartingEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions,
SP: ShMemProvider,
//CE: CustomEvent<I>,
{
/// The tcp client needs to wait until a broker mapped all pages, before shutting down.
/// Otherwise, the OS may already have removed the shared maps,
@ -905,6 +870,20 @@ where
self.tcp_mgr.await_restart_safe();
}
fn send_exiting(&mut self) -> Result<(), Error> {
self.staterestorer.send_exiting();
// Also inform the broker that we are about to exit.
// This way, the broker can clean up the pages, and eventually exit.
self.tcp_mgr.send_exiting()
}
}
impl<EMH, S, SP> EventRestarter<S> for TcpRestartingEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus + HasExecutions + HasCurrentStageId + Serialize,
SP: ShMemProvider,
{
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
state.on_restart()?;
@ -920,24 +899,17 @@ where
self.await_restart_safe();
Ok(())
}
fn send_exiting(&mut self) -> Result<(), Error> {
self.staterestorer.send_exiting();
// Also inform the broker that we are about to exit.
// This way, the broker can clean up the pages, and eventually exit.
self.tcp_mgr.send_exiting()
}
}
impl<E, EMH, S, SP, Z> EventProcessor<E, Z> for TcpRestartingEventManager<EMH, S, SP>
impl<E, EMH, S, SP, Z> EventProcessor<E, S, Z> for TcpRestartingEventManager<EMH, S, SP>
where
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>,
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
SP: ShMemProvider + 'static,
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasExecutions + HasMetadata + HasImported + HasCorpus + Stoppable,
<S::Corpus as Corpus>::Input: DeserializeOwned,
SP: ShMemProvider,
Z: ExecutionProcessor<TcpEventManager<EMH, S>, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, TcpEventManager<EMH, S>, <S::Corpus as Corpus>::Input, S>,
{
@ -950,25 +922,9 @@ where
}
}
impl<E, EMH, S, SP, Z> EventManager<E, Z> for TcpRestartingEventManager<EMH, S, SP>
where
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>,
S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
SP: ShMemProvider + 'static,
Z: ExecutionProcessor<TcpEventManager<EMH, S>, <S::Corpus as Corpus>::Input, E::Observers, S>
+ EvaluatorObservers<E, TcpEventManager<EMH, S>, <S::Corpus as Corpus>::Input, S>,
{
}
impl<EMH, S, SP> HasEventManagerId for TcpRestartingEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider + 'static,
SP: ShMemProvider,
{
fn mgr_id(&self) -> EventManagerId {
self.tcp_mgr.mgr_id()
@ -983,9 +939,9 @@ const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
impl<EMH, S, SP> TcpRestartingEventManager<EMH, S, SP>
where
EMH: EventManagerHooksTuple<S>,
S: State,
SP: ShMemProvider + 'static,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus,
SP: ShMemProvider,
//CE: CustomEvent<I>,
{
/// Create a new runner, the executed child doing the actual fuzzing.
@ -1053,8 +1009,8 @@ pub fn setup_restarting_mgr_tcp<MT, S>(
>
where
MT: Monitor + Clone,
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
S: HasExecutions + HasMetadata + HasImported + HasCorpus + DeserializeOwned + Stoppable,
<S::Corpus as Corpus>::Input: Input,
{
TcpRestartingMgr::builder()
.shmem_provider(StdShMemProvider::new()?)
@ -1074,10 +1030,9 @@ where
#[derive(TypedBuilder, Debug)]
pub struct TcpRestartingMgr<EMH, MT, S, SP>
where
S: UsesInput + DeserializeOwned,
S: DeserializeOwned,
SP: ShMemProvider + 'static,
MT: Monitor,
//CE: CustomEvent<I>,
{
/// The shared memory provider to use for the broker or client spawned by the restarting
/// manager.
@ -1116,10 +1071,10 @@ where
#[expect(clippy::type_complexity, clippy::too_many_lines)]
impl<EMH, MT, S, SP> TcpRestartingMgr<EMH, MT, S, SP>
where
EMH: EventManagerHooksTuple<S> + Copy + Clone,
EMH: EventManagerHooksTuple<<S::Corpus as Corpus>::Input, S> + Copy + Clone,
SP: ShMemProvider,
S: State + HasExecutions + HasMetadata + HasImported + HasCorpus,
S::Corpus: Corpus<Input = S::Input>,
S: HasExecutions + HasMetadata + HasImported + HasCorpus + DeserializeOwned + Stoppable,
<S::Corpus as Corpus>::Input: Input,
MT: Monitor + Clone,
{
/// Launch the restarting manager
@ -1127,7 +1082,8 @@ where
// We start ourself as child process to actually fuzz
let (staterestorer, _new_shmem_provider, core_id) = if env::var(_ENV_FUZZER_SENDER).is_err()
{
let broker_things = |mut broker: TcpEventBroker<S::Input, MT>, _remote_broker_addr| {
let broker_things = |mut broker: TcpEventBroker<<S::Corpus as Corpus>::Input, MT>,
_remote_broker_addr| {
if let Some(exit_cleanly_after) = self.exit_cleanly_after {
broker.set_exit_cleanly_after(exit_cleanly_after);
}
@ -1141,10 +1097,11 @@ where
let connection = create_nonblocking_listener(("127.0.0.1", self.broker_port));
match connection {
Ok(listener) => {
let event_broker = TcpEventBroker::<S::Input, MT>::with_listener(
listener,
self.monitor.take().unwrap(),
);
let event_broker =
TcpEventBroker::<<S::Corpus as Corpus>::Input, MT>::with_listener(
listener,
self.monitor.take().unwrap(),
);
// Yep, broker. Just loop here.
log::info!(
@ -1172,7 +1129,7 @@ where
}
}
TcpManagerKind::Broker => {
let event_broker = TcpEventBroker::<S::Input, MT>::new(
let event_broker = TcpEventBroker::<<S::Corpus as Corpus>::Input, MT>::new(
format!("127.0.0.1:{}", self.broker_port),
self.monitor.take().unwrap(),
)?;

View File

@ -747,7 +747,7 @@ impl CommandExecutorBuilder {
/// # Example
/// ```
/// use std::{io::Write, process::{Stdio, Command, Child}, time::Duration};
/// use libafl::{Error, corpus::Corpus, inputs::{BytesInput, HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::{HasCorpus, UsesState, HasExecutions}};
/// use libafl::{Error, corpus::Corpus, inputs::{BytesInput, HasTargetBytes, Input}, executors::{Executor, command::CommandConfigurator}, state::{HasCorpus, HasExecutions}};
/// use libafl_bolts::AsSlice;
/// #[derive(Debug)]
/// struct MyExecutor;
@ -779,10 +779,8 @@ impl CommandExecutorBuilder {
///
/// 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>,
/// S::Corpus: Corpus<Input = BytesInput>
/// {
/// MyExecutor.into_executor(())
/// }
@ -877,7 +875,7 @@ mod tests {
#[test]
#[cfg_attr(miri, ignore)]
fn test_builder() {
let mut mgr: SimpleEventManager<_, NopState<NopInput>> =
let mut mgr: SimpleEventManager<NopInput, _, NopState<NopInput>> =
SimpleEventManager::new(SimpleMonitor::new(|status| {
log::info!("{status}");
}));

View File

@ -29,7 +29,6 @@ use crate::{
events::{EventFirer, EventRestarter},
executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers},
feedbacks::Feedback,
inputs::UsesInput,
state::{HasCorpus, HasExecutions, HasSolutions},
Error, HasObjective,
};
@ -222,9 +221,9 @@ impl<I, S> InProcessHooks<I, S> {
where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
Z: HasObjective<Objective = OF>,
I: Input + Clone,
S::Solutions: Corpus<Input = I>,
@ -266,10 +265,10 @@ impl<I, S> InProcessHooks<I, S> {
where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF>,
{
@ -329,9 +328,9 @@ impl<I, S> InProcessHooks<I, S> {
pub fn new<E, EM, OF, Z>(exec_tmout: Duration) -> Result<Self, Error>
where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCorpus + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF>,
{
#[cfg_attr(miri, allow(unused_variables))]
@ -469,7 +468,7 @@ pub(crate) static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExec
critical: null_mut(),
};
/// Get the inprocess [`crate::state::State`]
/// Get the inprocess State
///
/// # Safety
/// Only safe if not called twice and if the state is not accessed from another borrow while this one is alive.
@ -478,7 +477,7 @@ pub unsafe fn inprocess_get_state<'a, S>() -> Option<&'a mut S> {
unsafe { (GLOBAL_STATE.state_ptr as *mut S).as_mut() }
}
/// Get the [`crate::events::EventManager`]
/// Get the `EventManager`
///
/// # Safety
/// Only safe if not called twice and if the event manager is not accessed from another borrow while this one is alive.

View File

@ -19,7 +19,7 @@ pub mod unix_signal_handler {
},
feedbacks::Feedback,
fuzzer::HasObjective,
inputs::{Input, UsesInput},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
};
@ -81,9 +81,9 @@ pub mod unix_signal_handler {
where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF>,
I: Input + Clone,
@ -131,9 +131,9 @@ pub mod unix_signal_handler {
) where
E: Executor<EM, I, S, Z> + HasInProcessHooks<I, S> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus,
Z: HasObjective<Objective = OF>,
I: Input + Clone,
S::Solutions: Corpus<Input = I>,
@ -188,9 +188,9 @@ pub mod unix_signal_handler {
) where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
Z: HasObjective<Objective = OF>,
I: Input + Clone,
S::Solutions: Corpus<Input = I>,

View File

@ -17,7 +17,7 @@ pub mod windows_asan_handler {
},
feedbacks::Feedback,
fuzzer::HasObjective,
inputs::{Input, UsesInput},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
};
@ -28,10 +28,10 @@ pub mod windows_asan_handler {
where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF>,
{
@ -136,7 +136,7 @@ pub mod windows_exception_handler {
},
feedbacks::Feedback,
fuzzer::HasObjective,
inputs::{Input, UsesInput},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
};
@ -186,10 +186,10 @@ pub mod windows_exception_handler {
where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF>,
{
@ -249,10 +249,10 @@ pub mod windows_exception_handler {
) where
E: Executor<EM, I, S, Z> + HasInProcessHooks<I, S> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus,
Z: HasObjective<Objective = OF>,
S::Solutions: Corpus<Input = I>,
{
@ -319,10 +319,10 @@ pub mod windows_exception_handler {
) where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
Z: HasObjective<Objective = OF>,
S::Solutions: Corpus<Input = I>,
{

View File

@ -27,7 +27,7 @@ use crate::{
},
feedbacks::Feedback,
fuzzer::HasObjective,
inputs::{Input, UsesInput},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
Error,
@ -145,10 +145,10 @@ where
where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone,
OF: Feedback<EM, I, E::Observers, S>,
S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput<Input = I>,
S: HasCurrentTestcase + HasCorpus + HasSolutions,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF>,
{
@ -175,10 +175,10 @@ where
where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone,
OF: Feedback<EM, I, E::Observers, S>,
S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput<Input = I>,
S: HasCurrentTestcase + HasCorpus + HasSolutions,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF>,
{
@ -208,9 +208,9 @@ where
where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput<Input = I>,
S: HasCurrentTestcase + HasCorpus + HasSolutions,
Z: HasObjective<Objective = OF>,
S::Solutions: Corpus<Input = I>,
I: Input + Clone,

View File

@ -28,7 +28,7 @@ use crate::{
},
feedbacks::Feedback,
fuzzer::HasObjective,
inputs::{Input, UsesInput},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
Error, HasMetadata,
@ -124,7 +124,7 @@ impl<'a, H, I, OT, S> InProcessExecutor<'a, H, I, OT, S>
where
H: FnMut(&I) -> ExitKind + Sized,
OT: ObserversTuple<I, S>,
S: HasCorpus + HasCurrentTestcase + UsesInput<Input = I> + HasExecutions + HasSolutions,
S: HasCorpus + HasCurrentTestcase + HasExecutions + HasSolutions,
S::Solutions: Corpus<Input = I>,
I: Input,
{
@ -137,7 +137,7 @@ where
event_mgr: &mut EM,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -163,7 +163,7 @@ where
exec_tmout: Duration,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -200,7 +200,7 @@ where
timeout: Duration,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -227,7 +227,7 @@ where
HB: BorrowMut<H>,
HT: ExecutorHooksTuple<I, S>,
OT: ObserversTuple<I, S>,
S: HasCorpus + HasCurrentTestcase + UsesInput<Input = I> + HasExecutions + HasSolutions,
S: HasCorpus + HasCurrentTestcase + HasExecutions + HasSolutions,
S::Solutions: Corpus<Input = I>,
I: Input,
{
@ -241,7 +241,7 @@ where
event_mgr: &mut EM,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -268,7 +268,8 @@ where
exec_tmout: Duration,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -301,7 +302,7 @@ where
timeout: Duration,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -378,9 +379,9 @@ pub fn run_observers_and_save_state<E, EM, I, OF, S, Z>(
) where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
Z: HasObjective<Objective = OF>,
I: Input + Clone,
S::Solutions: Corpus<Input = I>,
@ -440,9 +441,9 @@ pub unsafe fn generic_inproc_crash_handler<E, EM, I, OF, S, Z>()
where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
I: Input + Clone,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF> + ExecutionProcessor<EM, I, E::Observers, S>,
@ -479,16 +480,12 @@ mod tests {
events::NopEventManager,
executors::{Executor, ExitKind, InProcessExecutor},
feedbacks::CrashFeedback,
inputs::{NopInput, UsesInput},
inputs::NopInput,
schedulers::RandScheduler,
state::{NopState, StdState},
StdFuzzer,
};
impl UsesInput for () {
type Input = NopInput;
}
#[test]
fn test_inmem_exec() {
let mut harness = |_buf: &NopInput| ExitKind::Ok;

View File

@ -20,7 +20,7 @@ use crate::{
},
feedbacks::Feedback,
fuzzer::HasObjective,
inputs::{Input, UsesInput},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
Error,
@ -124,7 +124,7 @@ impl<'a, H, I, OT, S, ES> StatefulInProcessExecutor<'a, H, I, OT, S, ES>
where
H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized,
OT: ObserversTuple<I, S>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
I: Clone + Input,
S::Solutions: Corpus<Input = I>,
{
@ -138,7 +138,7 @@ where
event_mgr: &mut EM,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -166,7 +166,7 @@ where
exec_tmout: Duration,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -205,7 +205,7 @@ where
timeout: Duration,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -246,12 +246,7 @@ where
HT: ExecutorHooksTuple<I, S>,
I: Input + Clone,
OT: ObserversTuple<I, S>,
S: HasCorpus
+ HasExecutions
+ HasSolutions
+ HasCorpus
+ HasCurrentTestcase
+ UsesInput<Input = I>,
S: HasCorpus + HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
S::Solutions: Corpus<Input = I>,
{
/// Create a new in mem executor with the default timeout (5 sec)
@ -265,7 +260,7 @@ where
event_mgr: &mut EM,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -295,7 +290,7 @@ where
exec_tmout: Duration,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{
@ -331,7 +326,7 @@ where
timeout: Duration,
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>,
{

View File

@ -382,7 +382,8 @@ mod tests {
let input = NopInput {};
let mut fuzzer = NopFuzzer::new();
let mut state = NopState::new();
let mut mgr: SimpleEventManager<_, NopState<NopInput>> = SimpleEventManager::printing();
let mut mgr: SimpleEventManager<NopInput, _, NopState<NopInput>> =
SimpleEventManager::printing();
in_process_fork_executor
.run_target(&mut fuzzer, &mut state, &mut mgr, &input)
.unwrap();

View File

@ -221,7 +221,7 @@ mod test {
let nonempty_input = BytesInput::new(vec![1u8]);
let mut executor = NopExecutor::new();
let mut fuzzer = NopFuzzer::new();
let mut mgr: NopEventManager<NopState<BytesInput>> = NopEventManager::new();
let mut mgr: NopEventManager = NopEventManager::new();
let mut state: NopState<BytesInput> = NopState::new();
executor

View File

@ -237,7 +237,7 @@ mod tests {
DiffFeedback::<_, _, _>::is_interesting(
&mut diff_feedback,
&mut nop_state,
&mut NopEventManager::<NopState<BytesInput>>::default(),
&mut NopEventManager::default(),
&BytesInput::new(vec![0]),
&observers,
&ExitKind::Ok

View File

@ -21,13 +21,13 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
#[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err;
use crate::{
corpus::Testcase,
corpus::{Corpus, Testcase},
events::{Event, EventFirer},
executors::ExitKind,
feedbacks::{Feedback, HasObserverHandle, StateInitializer},
inputs::UsesInput,
monitors::{AggregatorOps, UserStats, UserStatsValue},
observers::{CanTrack, MapObserver},
state::HasCorpus,
Error, HasMetadata, HasNamedMetadata,
};
@ -395,13 +395,13 @@ where
impl<C, EM, I, N, O, OT, R, S> Feedback<EM, I, OT, S> for MapFeedback<C, N, O, R>
where
C: CanTrack + AsRef<O>,
EM: EventFirer<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
N: IsNovel<O::Entry>,
O: MapObserver + for<'it> AsIter<'it, Item = O::Entry>,
O::Entry: 'static + Default + Debug + DeserializeOwned + Serialize,
OT: MatchName,
R: Reducer<O::Entry>,
S: HasNamedMetadata + UsesInput, // delete me
S: HasNamedMetadata + HasCorpus, // delete me
{
#[rustversion::nightly]
default fn is_interesting(
@ -538,10 +538,10 @@ where
impl<C, O, EM, I, OT, S> Feedback<EM, I, OT, S> for MapFeedback<C, DifferentIsNovel, O, MaxReducer>
where
C: CanTrack + AsRef<O>,
EM: EventFirer<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
O: MapObserver<Entry = u8> + for<'a> AsSlice<'a, Entry = u8> + for<'a> AsIter<'a, Item = u8>,
OT: MatchName,
S: HasNamedMetadata + UsesInput,
S: HasNamedMetadata + HasCorpus,
{
fn is_interesting(
&mut self,

View File

@ -14,10 +14,12 @@ use serde::Serialize;
use crate::monitors::PerfFeature;
use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase},
events::{Event, EventConfig, EventFirer, EventProcessor, ProgressReporter},
events::{
CanSerializeObserver, Event, EventConfig, EventFirer, EventProcessor, ProgressReporter,
},
executors::{Executor, ExitKind, HasObservers},
feedbacks::Feedback,
inputs::{Input, UsesInput},
inputs::Input,
mark_feature_time,
observers::ObserversTuple,
schedulers::Scheduler,
@ -25,7 +27,7 @@ use crate::{
start_timer,
state::{
HasCorpus, HasCurrentTestcase, HasExecutions, HasLastFoundTime, HasLastReportTime,
HasSolutions, MaybeHasClientPerfMonitor, State, UsesState,
HasSolutions, MaybeHasClientPerfMonitor, Stoppable,
},
Error, HasMetadata,
};
@ -307,13 +309,8 @@ impl<CS, EM, F, IF, OF, OT, S> ExecutionProcessor<EM, <S::Corpus as Corpus>::Inp
for StdFuzzer<CS, F, IF, OF>
where
CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
EM: EventFirer<State = S>,
S: HasCorpus
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
+ HasCurrentTestcase
+ HasSolutions
+ HasLastFoundTime,
EM: EventFirer<<S::Corpus as Corpus>::Input, S> + CanSerializeObserver<OT>,
S: HasCorpus + MaybeHasClientPerfMonitor + HasCurrentTestcase + HasSolutions + HasLastFoundTime,
F: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
OF: Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>,
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
@ -397,7 +394,7 @@ where
if manager.configuration() == EventConfig::AlwaysUnique {
None
} else {
manager.serialize_observers::<OT>(observers)?
manager.serialize_observers(observers)?
}
} else {
None
@ -515,14 +512,13 @@ where
CS: Scheduler<<S::Corpus as Corpus>::Input, 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>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S> + CanSerializeObserver<E::Observers>,
F: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
S: HasCorpus
+ HasSolutions
+ MaybeHasClientPerfMonitor
+ HasCurrentTestcase
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
+ HasExecutions
+ HasLastFoundTime,
<S::Corpus as Corpus>::Input: Input,
@ -593,7 +589,7 @@ where
CS: Scheduler<<S::Corpus as Corpus>::Input, 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>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S> + CanSerializeObserver<E::Observers>,
F: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
OF: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
S: HasCorpus
@ -601,8 +597,7 @@ where
+ MaybeHasClientPerfMonitor
+ HasCurrentTestcase
+ HasLastFoundTime
+ HasExecutions
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ HasExecutions,
<S::Corpus as Corpus>::Input: Input,
S::Solutions: Corpus<Input = <S::Corpus as Corpus>::Input>,
IF: InputFilter<<S::Corpus as Corpus>::Input>,
@ -725,7 +720,7 @@ where
let observers_buf = if manager.configuration() == EventConfig::AlwaysUnique {
None
} else {
manager.serialize_observers::<E::Observers>(&*observers)?
manager.serialize_observers(&*observers)?
};
manager.fire(
state,
@ -747,8 +742,8 @@ 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>,
EM: ProgressReporter + EventProcessor<E, Self, State = S>,
CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
EM: ProgressReporter<S> + EventProcessor<E, S, Self>,
S: HasExecutions
+ HasMetadata
+ HasCorpus
@ -756,7 +751,8 @@ where
+ HasTestcase
+ HasCurrentCorpusId
+ HasCurrentStageId
+ State,
+ Stoppable
+ MaybeHasClientPerfMonitor,
ST: StagesTuple<E, EM, S, Self>,
{
fn fuzz_one(
@ -924,11 +920,7 @@ where
CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
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>
+ HasExecutions
+ HasCorpus
+ MaybeHasClientPerfMonitor,
S: HasExecutions + HasCorpus + MaybeHasClientPerfMonitor,
{
/// Runs the input and triggers observers and feedback
fn execute_input(
@ -976,15 +968,15 @@ impl Default for NopFuzzer {
impl<E, EM, S, ST> Fuzzer<E, EM, S, ST> for NopFuzzer
where
EM: ProgressReporter<State = S> + EventProcessor<E, Self>,
EM: ProgressReporter<S> + EventProcessor<E, S, Self>,
ST: StagesTuple<E, EM, S, Self>,
S: HasMetadata + HasExecutions + HasLastReportTime + HasCurrentStageId + UsesInput,
S: HasMetadata + HasExecutions + HasLastReportTime + HasCurrentStageId,
{
fn fuzz_one(
&mut self,
_stages: &mut ST,
_executor: &mut E,
_state: &mut EM::State,
_state: &mut S,
_manager: &mut EM,
) -> Result<CorpusId, Error> {
unimplemented!("NopFuzzer cannot fuzz");

View File

@ -277,13 +277,6 @@ impl HasMutatorBytes for &mut Vec<u8> {
}
}
/// Defines the input type shared across traits of the type.
/// Needed for consistency across HasCorpus/HasSolutions and friends.
pub trait UsesInput {
/// Type which will be used throughout this state.
type Input: Input;
}
#[derive(Debug)]
/// Basic `InputConverter` with just one type that is not converting
pub struct NopInputConverter<I> {

View File

@ -914,26 +914,6 @@ pub struct ClientPerfMonitor {
timer_start: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
/// Count the imported testcase from other nodes that came with observers
pub struct ScalabilityMonitor {
/// Imported testcase received with observer
pub testcase_with_observers: usize,
/// Imported testcase received without observer
pub testcase_without_observers: usize,
}
impl ScalabilityMonitor {
/// Constructor
#[must_use]
pub fn new() -> Self {
Self {
testcase_with_observers: 0,
testcase_without_observers: 0,
}
}
}
/// Various features that are measured for performance
#[derive(Serialize, Deserialize, Debug, Clone)]
#[repr(u8)]

View File

@ -28,12 +28,12 @@ use crate::{observers::Observer, Error};
/// events::{EventFirer, NopEventManager},
/// executors::{CommandExecutor, ExitKind},
/// feedbacks::{Feedback, StateInitializer},
/// inputs::{BytesInput, UsesInput},
/// inputs::BytesInput,
/// mutators::{MutationResult, NopMutator},
/// observers::{ObserversTuple, StdErrObserver, StdOutObserver},
/// schedulers::QueueScheduler,
/// stages::StdMutationalStage,
/// state::{HasCorpus, State, StdState},
/// state::{HasCorpus, StdState},
/// Error, Fuzzer, StdFuzzer,
/// };
///
@ -58,7 +58,6 @@ use crate::{observers::Observer, Error};
///
/// impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ExportStdXObserver
/// where
/// S: State,
/// OT: MatchNameRef
/// {
/// fn is_interesting(

View File

@ -16,7 +16,7 @@ use crate::{
on_add_metadata_default, on_evaluation_metadata_default, on_next_metadata_default,
AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler,
},
state::{HasCorpus, State},
state::HasCorpus,
Error, HasMetadata,
};
@ -327,7 +327,7 @@ impl<C, O> HasQueueCycles for PowerQueueScheduler<C, O> {
impl<C, I, O, S> Scheduler<I, S> for PowerQueueScheduler<C, O>
where
S: HasCorpus + HasMetadata + HasTestcase + State,
S: HasCorpus + HasMetadata + HasTestcase,
O: MapObserver,
C: AsRef<O>,
{

View File

@ -26,7 +26,6 @@ use crate::{
corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata, Testcase},
events::{Event, EventFirer},
executors::HasObservers,
inputs::UsesInput,
monitors::{AggregatorOps, UserStats, UserStatsValue},
mutators::Tokens,
observers::MapObserver,
@ -240,7 +239,7 @@ pub struct AFLPlotData<'a> {
impl<C, E, EM, O, S, Z> Stage<E, EM, S, Z> for AflStatsStage<C, E, EM, O, S, Z>
where
E: HasObservers,
EM: EventFirer<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
Z: HasScheduler<<S::Corpus as Corpus>::Input, S>,
S: HasImported
+ HasCorpus
@ -249,8 +248,7 @@ where
+ HasExecutions
+ HasNamedMetadata
+ Stoppable
+ HasCurrentCorpusId
+ UsesInput,
+ HasCurrentCorpusId,
E::Observers: MatchNameRef,
O: MapObserver,
C: AsRef<O> + Named,
@ -446,7 +444,7 @@ where
impl<C, E, EM, O, S, Z> AflStatsStage<C, E, EM, O, S, Z>
where
E: HasObservers,
EM: EventFirer,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
S: HasImported + HasCorpus + HasMetadata + HasExecutions,
C: AsRef<O> + Named,
O: MapObserver,
@ -672,7 +670,7 @@ pub struct AflStatsStageBuilder<C, E, EM, O, S, Z> {
impl<C, E, EM, O, S, Z> AflStatsStageBuilder<C, E, EM, O, S, Z>
where
E: HasObservers,
EM: EventFirer,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
S: HasImported + HasCorpus + HasMetadata + HasExecutions,
C: AsRef<O> + Named,
O: MapObserver,

View File

@ -18,7 +18,7 @@ use crate::{
executors::{Executor, ExitKind, HasObservers},
feedbacks::{map::MapFeedbackMetadata, HasObserverHandle},
fuzzer::Evaluator,
inputs::{Input, UsesInput},
inputs::Input,
monitors::{AggregatorOps, UserStats, UserStatsValue},
observers::{MapObserver, ObserversTuple},
schedulers::powersched::SchedulerMetadata,
@ -92,7 +92,7 @@ pub struct CalibrationStage<C, E, O, OT, S> {
impl<C, E, EM, O, OT, S, Z> Stage<E, EM, S, Z> for CalibrationStage<C, E, O, OT, S>
where
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers<Observers = OT>,
EM: EventFirer<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
O: MapObserver,
C: AsRef<O>,
for<'de> <O as MapObserver>::Entry:
@ -103,8 +103,7 @@ where
+ HasNamedMetadata
+ HasExecutions
+ HasCurrentTestcase
+ HasCurrentCorpusId
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ HasCurrentCorpusId,
Z: Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: Input,
{

View File

@ -17,7 +17,7 @@ use crate::{
corpus::{Corpus, HasCurrentCorpusId},
events::EventFirer,
executors::{Executor, HasObservers},
inputs::{HasMutatorBytes, UsesInput},
inputs::HasMutatorBytes,
mutators::mutations::buffer_copy,
nonzero,
observers::{MapObserver, ObserversTuple},
@ -76,14 +76,9 @@ impl<C, E, EM, O, S, Z> Named for ColorizationStage<C, E, EM, O, S, Z> {
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>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
S: HasCorpus
+ HasMetadata
+ HasRand
+ HasNamedMetadata
+ HasCurrentCorpusId
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasCorpus + HasMetadata + HasRand + HasNamedMetadata + HasCurrentCorpusId,
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: HasMutatorBytes + Clone,
O: MapObserver,
@ -156,17 +151,12 @@ libafl_bolts::impl_serdeany!(TaintMetadata);
impl<C, E, EM, O, S, Z> ColorizationStage<C, E, EM, O, S, Z>
where
EM: EventFirer<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
O: MapObserver,
C: AsRef<O> + Named,
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus
+ HasMetadata
+ HasRand
+ HasCurrentCorpusId
+ HasCurrentTestcase
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasCorpus + HasMetadata + HasRand + HasCurrentCorpusId + HasCurrentTestcase,
<S::Corpus as Corpus>::Input: HasMutatorBytes + Clone,
{
#[inline]

View File

@ -17,10 +17,9 @@ use crate::monitors::PerfFeature;
use crate::{
corpus::{Corpus, HasCurrentCorpusId},
executors::{Executor, HasObservers},
inputs::UsesInput,
observers::{concolic::ConcolicObserver, ObserversTuple},
stages::{RetryCountRestartHelper, Stage, TracingStage},
state::{HasCorpus, HasCurrentTestcase, HasExecutions, MaybeHasClientPerfMonitor, UsesState},
state::{HasCorpus, HasCurrentTestcase, HasExecutions, MaybeHasClientPerfMonitor},
Error, HasMetadata, HasNamedMetadata,
};
#[cfg(feature = "concolic_mutation")]
@ -57,9 +56,7 @@ where
+ HasNamedMetadata
+ HasCurrentTestcase
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
EM: UsesState<State = S>,
+ MaybeHasClientPerfMonitor,
{
#[inline]
fn perform(
@ -387,8 +384,7 @@ where
+ HasNamedMetadata
+ HasCurrentTestcase
+ MaybeHasClientPerfMonitor
+ HasCurrentCorpusId
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ HasCurrentCorpusId,
{
#[inline]
fn perform(

View File

@ -17,13 +17,13 @@ use crate::{
corpus::{Corpus, HasCurrentCorpusId},
executors::{Executor, HasObservers},
feedbacks::map::MapNoveltiesMetadata,
inputs::{BytesInput, GeneralizedInputMetadata, GeneralizedItem, HasMutatorBytes, UsesInput},
inputs::{BytesInput, GeneralizedInputMetadata, GeneralizedItem, HasMutatorBytes},
mark_feature_time,
observers::{CanTrack, MapObserver, ObserversTuple},
require_novelties_tracking,
stages::{RetryCountRestartHelper, Stage},
start_timer,
state::{HasCorpus, HasExecutions, MaybeHasClientPerfMonitor, UsesState},
state::{HasCorpus, HasExecutions, MaybeHasClientPerfMonitor},
Error, HasMetadata, HasNamedMetadata,
};
@ -71,10 +71,8 @@ where
+ HasCorpus
+ HasNamedMetadata
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = BytesInput>,
+ MaybeHasClientPerfMonitor,
S::Corpus: Corpus<Input = BytesInput>,
EM: UsesState<State = S>,
{
#[inline]
#[expect(clippy::too_many_lines)]
@ -343,14 +341,9 @@ impl<C, EM, O, OT, S, Z> GeneralizationStage<C, EM, O, OT, S, Z>
where
O: MapObserver,
C: CanTrack + AsRef<O> + Named,
S: HasExecutions
+ HasMetadata
+ HasCorpus
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = BytesInput>,
S: HasExecutions + HasMetadata + HasCorpus + MaybeHasClientPerfMonitor,
S::Corpus: Corpus<Input = BytesInput>,
OT: ObserversTuple<BytesInput, S>,
EM: UsesState<State = S>,
{
/// Create a new [`GeneralizationStage`].
#[must_use]

View File

@ -9,7 +9,6 @@ use core::marker::PhantomData;
use crate::{
corpus::Corpus,
generators::Generator,
inputs::UsesInput,
stages::Stage,
state::{HasCorpus, HasRand},
Error, Evaluator,
@ -32,7 +31,7 @@ impl<G, S, Z> GenStage<G, S, Z> {
impl<E, EM, G, S, Z> Stage<E, EM, S, Z> for GenStage<G, S, Z>
where
Z: Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>,
S: HasCorpus + HasRand + UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasCorpus + HasRand,
G: Generator<<S::Corpus as Corpus>::Input, S>,
{
#[inline]

View File

@ -49,7 +49,7 @@ pub use verify_timeouts::{TimeoutsToVerify, VerifyTimeoutsStage};
use crate::{
corpus::{CorpusId, HasCurrentCorpusId},
events::EventProcessor,
state::{HasExecutions, State, Stoppable},
state::{HasExecutions, Stoppable},
Error, HasNamedMetadata,
};
@ -161,7 +161,7 @@ where
Head: Stage<E, EM, S, Z>,
Tail: StagesTuple<E, EM, S, Z> + HasConstLen,
S: HasCurrentStageId + Stoppable,
EM: EventProcessor<E, Z>,
EM: EventProcessor<E, S, Z>,
{
/// Performs all stages in the tuple,
/// Checks after every stage if state wants to stop
@ -248,8 +248,8 @@ impl<E, EM, S, Z> IntoVec<Box<dyn Stage<E, EM, S, Z>>> for Vec<Box<dyn Stage<E,
impl<E, EM, S, Z> StagesTuple<E, EM, S, Z> for Vec<Box<dyn Stage<E, EM, S, Z>>>
where
EM: EventProcessor<E, Z>,
S: HasCurrentStageId + State,
EM: EventProcessor<E, S, Z>,
S: HasCurrentStageId + Stoppable,
{
/// Performs all stages in the `Vec`
/// Checks after every stage if state wants to stop

View File

@ -14,7 +14,7 @@ use crate::monitors::PerfFeature;
use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId, Testcase},
fuzzer::Evaluator,
inputs::{Input, UsesInput},
inputs::Input,
mark_feature_time,
mutators::{MultiMutator, MutationResult, Mutator},
nonzero,
@ -156,11 +156,9 @@ where
+ HasExecutions
+ HasNamedMetadata
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor
+ UsesInput,
+ MaybeHasClientPerfMonitor,
I: MutatedTransform<<S::Corpus as Corpus>::Input, S> + Clone,
<S::Corpus as Corpus>::Input: Input,
S::Corpus: Corpus<Input = S::Input>,
{
#[inline]
fn perform(
@ -191,9 +189,8 @@ impl<E, EM, M, S, Z> StdMutationalStage<E, EM, <S::Corpus as Corpus>::Input, M,
where
M: Mutator<<S::Corpus as Corpus>::Input, S>,
Z: Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>,
S: HasCorpus + HasRand + HasCurrentCorpusId + UsesInput + MaybeHasClientPerfMonitor,
S: HasCorpus + HasRand + HasCurrentCorpusId + MaybeHasClientPerfMonitor,
<S::Corpus as Corpus>::Input: Input + Clone,
S::Corpus: Corpus<Input = S::Input>,
{
/// Creates a new default mutational stage
pub fn new(mutator: M) -> Self {
@ -212,10 +209,9 @@ impl<E, EM, I, M, S, Z> StdMutationalStage<E, EM, I, M, S, Z>
where
M: Mutator<I, S>,
Z: Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>,
S: HasCorpus + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor + UsesInput,
S: HasCorpus + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor,
I: MutatedTransform<<S::Corpus as Corpus>::Input, S> + Clone,
<S::Corpus as Corpus>::Input: Input,
S::Corpus: Corpus<Input = S::Input>,
{
/// Creates a new transforming mutational stage with the default max iterations
pub fn transforming(mutator: M) -> Self {
@ -313,10 +309,9 @@ impl<E, EM, I, M, S, Z> Stage<E, EM, S, Z> for MultiMutationalStage<E, EM, I, M,
where
M: MultiMutator<I, S>,
Z: Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>,
S: HasCorpus + HasRand + HasNamedMetadata + HasCurrentTestcase + HasCurrentCorpusId + UsesInput,
S: HasCorpus + HasRand + HasNamedMetadata + HasCurrentTestcase + HasCurrentCorpusId,
I: MutatedTransform<<S::Corpus as Corpus>::Input, S> + Clone,
<S::Corpus as Corpus>::Input: Input,
S::Corpus: Corpus<Input = S::Input>,
{
#[inline]
fn should_restart(&mut self, state: &mut S) -> Result<bool, Error> {

View File

@ -14,7 +14,7 @@ use crate::{
corpus::{Corpus, HasCurrentCorpusId},
executors::{Executor, HasObservers},
fuzzer::Evaluator,
inputs::{Input, UsesInput},
inputs::Input,
mark_feature_time,
mutators::{MutationResult, Mutator},
schedulers::{testcase_score::CorpusPowerTestcaseScore, TestcaseScore},
@ -23,9 +23,7 @@ use crate::{
MutationalStage, RetryCountRestartHelper, Stage,
},
start_timer,
state::{
HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor, UsesState,
},
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor},
Error, HasMetadata, HasNamedMetadata,
};
@ -80,7 +78,6 @@ 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, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
EM: UsesState<State = S>,
F: TestcaseScore<S>,
M: Mutator<I, S>,
S: HasCorpus
@ -90,8 +87,7 @@ where
+ HasNamedMetadata
+ HasCurrentTestcase
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ MaybeHasClientPerfMonitor,
Z: Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>,
I: MutatedTransform<<S::Corpus as Corpus>::Input, S> + Clone + Input,
<S::Corpus as Corpus>::Input: Input,
@ -122,16 +118,10 @@ where
impl<E, F, EM, I, M, S, Z> PowerMutationalStage<E, F, EM, I, M, S, Z>
where
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
EM: UsesState<State = S>,
F: TestcaseScore<S>,
I: Input,
M: Mutator<I, S>,
S: HasCorpus
+ HasMetadata
+ HasRand
+ HasCurrentTestcase
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasCorpus + HasMetadata + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor,
I: MutatedTransform<<S::Corpus as Corpus>::Input, S> + Clone + Input,
Z: Evaluator<E, EM, <S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: Input,

View File

@ -26,7 +26,6 @@ use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId},
events::{EventFirer, EventRestarter, HasEventManagerId, ProgressReporter},
executors::{Executor, ExitKind, HasObservers},
inputs::UsesInput,
observers::ObserversTuple,
schedulers::Scheduler,
stages::{RetryCountRestartHelper, Stage},
@ -38,11 +37,11 @@ use crate::{
/// Should be stored inside a `[Rc<RefCell<_>>`]
#[derive(Clone, Debug)]
pub struct PushStageSharedState<EM, I, OT, S, Z> {
/// The [`crate::state::State`]
/// The state
pub state: S,
/// The [`crate::fuzzer::Fuzzer`] instance
pub fuzzer: Z,
/// The [`crate::events::EventManager`]
/// The event manager
pub event_mgr: EM,
/// The [`crate::observers::ObserversTuple`]
pub observers: OT,
@ -254,10 +253,12 @@ where
+ HasLastReportTime
+ HasCurrentCorpusId
+ HasNamedMetadata
+ HasMetadata
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ HasMetadata,
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers<Observers = OT>,
EM: EventFirer<State = S> + EventRestarter + HasEventManagerId + ProgressReporter<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>
+ EventRestarter<S>
+ HasEventManagerId
+ ProgressReporter<S>,
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
PS: PushStage<EM, <S::Corpus as Corpus>::Input, OT, S, Z>,
Z: ExecutesInput<E, EM, <S::Corpus as Corpus>::Input, S>

View File

@ -18,7 +18,7 @@ use crate::{
events::{EventFirer, ProgressReporter},
executors::ExitKind,
fuzzer::STATS_TIMEOUT_DEFAULT,
inputs::{Input, UsesInput},
inputs::Input,
mark_feature_time,
mutators::Mutator,
nonzero,
@ -79,13 +79,10 @@ where
impl<EM, M, OT, S, Z> PushStage<EM, <S::Corpus as Corpus>::Input, OT, S, Z>
for StdMutationalPushStage<EM, M, OT, S, Z>
where
EM: EventFirer<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
Z: HasScheduler<<S::Corpus as Corpus>::Input, S>
+ ExecutionProcessor<EM, <S::Corpus as Corpus>::Input, OT, S>,
S: HasCorpus
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
+ HasRand
+ MaybeHasClientPerfMonitor,
S: HasCorpus + HasRand + MaybeHasClientPerfMonitor,
M: Mutator<<S::Corpus as Corpus>::Input, S>,
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
<S::Corpus as Corpus>::Input: Input + Clone,
@ -193,14 +190,13 @@ where
impl<EM, M, OT, S, Z> Iterator for StdMutationalPushStage<EM, M, OT, S, Z>
where
EM: ProgressReporter<State = S>,
EM: ProgressReporter<S> + EventFirer<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus
+ HasMetadata
+ HasExecutions
+ HasLastReportTime
+ HasRand
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ MaybeHasClientPerfMonitor,
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
M: Mutator<<S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: Clone + Debug + Input,
@ -216,14 +212,13 @@ where
impl<EM, M, OT, S, Z> StdMutationalPushStage<EM, M, OT, S, Z>
where
EM: ProgressReporter<State = S>,
EM: ProgressReporter<S> + EventFirer<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus
+ HasMetadata
+ HasExecutions
+ HasLastReportTime
+ HasRand
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ MaybeHasClientPerfMonitor,
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
M: Mutator<<S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: Clone + Debug + Input,

View File

@ -15,9 +15,9 @@ use crate::{
events::{llmp::LlmpEventConverter, Event, EventConfig, EventFirer},
executors::{Executor, ExitKind, HasObservers},
fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor},
inputs::{Input, InputConverter, UsesInput},
inputs::{Input, InputConverter},
stages::{RetryCountRestartHelper, Stage},
state::{HasCorpus, HasExecutions, HasRand, MaybeHasClientPerfMonitor, State, Stoppable},
state::{HasCorpus, HasExecutions, HasRand, MaybeHasClientPerfMonitor, Stoppable},
Error, HasMetadata, HasNamedMetadata,
};
@ -74,7 +74,6 @@ where
+ HasRand
+ HasMetadata
+ HasNamedMetadata
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor,
{
@ -221,27 +220,17 @@ impl SyncFromBrokerMetadata {
/// A stage that loads testcases from disk to sync with other fuzzers such as AFL++
#[derive(Debug)]
pub struct SyncFromBrokerStage<DI, IC, ICB, S, SP>
pub struct SyncFromBrokerStage<IC, ICB, S, SP>
where
SP: ShMemProvider + 'static,
S: UsesInput,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
SP: ShMemProvider,
{
client: LlmpEventConverter<DI, IC, ICB, S, SP>,
client: LlmpEventConverter<IC, ICB, S, SP>,
}
impl<E, EM, IC, ICB, DI, S, SP, Z> Stage<E, EM, S, Z> for SyncFromBrokerStage<DI, IC, ICB, S, SP>
impl<E, EM, IC, ICB, DI, S, SP, Z> Stage<E, EM, S, Z> for SyncFromBrokerStage<IC, ICB, S, SP>
where
EM: EventFirer<State = S>,
S: HasExecutions
+ HasCorpus
+ HasRand
+ HasMetadata
+ Stoppable
+ UsesInput<Input = <S::Corpus as Corpus>::Input>
+ State,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
S: HasExecutions + HasCorpus + HasRand + HasMetadata + Stoppable + MaybeHasClientPerfMonitor,
SP: ShMemProvider,
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
for<'a> E::Observers: Deserialize<'a>,
@ -323,17 +312,13 @@ where
}
}
impl<DI, IC, ICB, S, SP> SyncFromBrokerStage<DI, IC, ICB, S, SP>
impl<IC, ICB, S, SP> SyncFromBrokerStage<IC, ICB, S, SP>
where
SP: ShMemProvider + 'static,
S: UsesInput,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,
SP: ShMemProvider,
{
/// Creates a new [`SyncFromBrokerStage`]
#[must_use]
pub fn new(client: LlmpEventConverter<DI, IC, ICB, S, SP>) -> Self {
pub fn new(client: LlmpEventConverter<IC, ICB, S, SP>) -> Self {
Self { client }
}
}

View File

@ -22,7 +22,7 @@ use crate::{
events::EventFirer,
executors::{ExitKind, HasObservers},
feedbacks::{Feedback, FeedbackFactory, HasObserverHandle, StateInitializer},
inputs::{Input, UsesInput},
inputs::Input,
mark_feature_time,
mutators::{MutationResult, Mutator},
observers::{MapObserver, ObserversTuple},
@ -34,7 +34,7 @@ use crate::{
start_timer,
state::{
HasCorpus, HasCurrentTestcase, HasExecutions, HasMaxSize, HasSolutions,
MaybeHasClientPerfMonitor, State,
MaybeHasClientPerfMonitor,
},
Error, ExecutesInput, ExecutionProcessor, HasFeedback, HasMetadata, HasNamedMetadata,
HasScheduler,
@ -65,7 +65,7 @@ where
Z::Scheduler: RemovableScheduler<<S::Corpus as Corpus>::Input, S>,
E: HasObservers,
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
EM: EventFirer<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
FF: FeedbackFactory<F, E::Observers>,
F: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
S: HasMetadata
@ -75,8 +75,7 @@ where
+ HasMaxSize
+ HasNamedMetadata
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ MaybeHasClientPerfMonitor,
Z::Feedback: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
M: Mutator<<S::Corpus as Corpus>::Input, S>,
<<S as HasCorpus>::Corpus as Corpus>::Input: Input + Hash + HasLen,
@ -136,7 +135,7 @@ where
Z::Scheduler: RemovableScheduler<<S::Corpus as Corpus>::Input, S>,
E: HasObservers,
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S> + Serialize,
EM: EventFirer<State = S>,
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
FF: FeedbackFactory<F, E::Observers>,
F: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
S: HasMetadata
@ -147,8 +146,7 @@ where
+ HasNamedMetadata
+ HasCurrentTestcase
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ MaybeHasClientPerfMonitor,
Z::Feedback: Feedback<EM, <S::Corpus as Corpus>::Input, E::Observers, S>,
M: Mutator<<S::Corpus as Corpus>::Input, S>,
<S::Corpus as Corpus>::Input: Hash + HasLen + Input,
@ -364,7 +362,6 @@ impl<C, EM, I, M, OT, S> Feedback<EM, I, OT, S> for MapEqualityFeedback<C, M, S>
where
M: MapObserver,
C: AsRef<M>,
S: State,
OT: MatchName,
{
fn is_interesting(
@ -424,8 +421,8 @@ impl<C, M, OT, S> FeedbackFactory<MapEqualityFeedback<C, M, S>, OT> for MapEqual
where
M: MapObserver,
C: AsRef<M> + Handled,
OT: ObserversTuple<S::Input, S>,
S: UsesInput,
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus,
{
fn create_feedback(&self, observers: &OT) -> MapEqualityFeedback<C, M, S> {
let obs = observers

View File

@ -13,12 +13,12 @@ use crate::monitors::PerfFeature;
use crate::{
corpus::{Corpus, HasCurrentCorpusId},
executors::{Executor, HasObservers, ShadowExecutor},
inputs::{Input, UsesInput},
inputs::Input,
mark_feature_time,
observers::ObserversTuple,
stages::{RetryCountRestartHelper, Stage},
start_timer,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, MaybeHasClientPerfMonitor, UsesState},
state::{HasCorpus, HasCurrentTestcase, HasExecutions, MaybeHasClientPerfMonitor},
Error, HasNamedMetadata,
};
@ -38,9 +38,7 @@ where
+ HasCorpus
+ HasNamedMetadata
+ HasCurrentTestcase
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
EM: UsesState<State = S>, //delete me
+ MaybeHasClientPerfMonitor,
{
/// Perform tracing on the given `CorpusId`. Useful for if wrapping [`TracingStage`] with your
/// own stage and you need to manage [`super::NestedStageRetryCountRestartHelper`] differently
@ -82,9 +80,7 @@ where
+ HasCorpus
+ HasNamedMetadata
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
EM: UsesState<State = S>,
+ MaybeHasClientPerfMonitor,
<S::Corpus as Corpus>::Input: Input,
{
#[inline]
@ -176,9 +172,7 @@ where
+ Debug
+ HasCurrentTestcase
+ HasCurrentCorpusId
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
EM: UsesState<State = S>,
+ MaybeHasClientPerfMonitor,
{
#[inline]
fn perform(
@ -228,9 +222,8 @@ where
impl<E, EM, SOT, S, Z> ShadowTracingStage<E, EM, SOT, S, Z>
where
E: Executor<EM, <S::Corpus as Corpus>::Input, S, Z> + HasObservers,
S: HasExecutions + HasCorpus + UsesInput,
S: HasExecutions + HasCorpus,
SOT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
EM: UsesState<State = S>,
{
/// Creates a new default stage
pub fn new(_executor: &mut ShadowExecutor<E, S, SOT>) -> Self {

View File

@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
use crate::monitors::PerfFeature;
use crate::{
corpus::Corpus,
inputs::{Input, UsesInput},
inputs::Input,
mark_feature_time,
mutators::{MutationResult, Mutator},
nonzero,
@ -203,8 +203,7 @@ where
+ HasMetadata
+ HasExecutions
+ HasCurrentTestcase
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ MaybeHasClientPerfMonitor,
I: MutatedTransform<<S::Corpus as Corpus>::Input, S> + Clone,
<S::Corpus as Corpus>::Input: Input,
{
@ -243,8 +242,7 @@ where
+ HasExecutions
+ HasMetadata
+ HasCurrentTestcase
+ MaybeHasClientPerfMonitor
+ UsesInput<Input = <S::Corpus as Corpus>::Input>,
+ MaybeHasClientPerfMonitor,
I: MutatedTransform<<S::Corpus as Corpus>::Input, S> + Clone,
<S::Corpus as Corpus>::Input: Input,
{

View File

@ -12,10 +12,10 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{
corpus::Corpus,
executors::{Executor, HasObservers, HasTimeout},
inputs::{BytesInput, UsesInput},
inputs::BytesInput,
observers::ObserversTuple,
stages::Stage,
state::{HasCorpus, UsesState},
state::HasCorpus,
Evaluator, HasMetadata,
};
@ -85,9 +85,8 @@ 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, <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>,
S: HasCorpus + HasMetadata,
<S::Corpus as Corpus>::Input: Debug + Serialize + DeserializeOwned + Default + 'static + Clone,
{
fn perform(

View File

@ -28,15 +28,13 @@ pub use stack::StageStack;
#[cfg(feature = "introspection")]
use crate::monitors::ClientPerfMonitor;
#[cfg(feature = "scalability_introspection")]
use crate::monitors::ScalabilityMonitor;
use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, InMemoryCorpus, Testcase},
events::{Event, EventFirer, LogSeverity},
feedbacks::StateInitializer,
fuzzer::{Evaluator, ExecuteInputResult},
generators::Generator,
inputs::{Input, NopInput, UsesInput},
inputs::{Input, NopInput},
stages::{HasCurrentStageId, HasNestedStageStatus, StageId},
Error, HasMetadata, HasNamedMetadata,
};
@ -44,35 +42,6 @@ use crate::{
/// The maximum size of a testcase
pub const DEFAULT_MAX_SIZE: usize = 1_048_576;
/// The [`State`] of the fuzzer.
/// Contains all important information about the current run.
/// Will be used to restart the fuzzing process at any time.
pub trait State:
UsesInput
+ Serialize
+ DeserializeOwned
+ MaybeHasClientPerfMonitor
+ MaybeHasScalabilityMonitor
+ HasCurrentCorpusId
+ HasCurrentStageId
+ Stoppable
{
}
/// Structs which implement this trait are aware of the state. This is used for type enforcement.
pub trait UsesState: UsesInput<Input = <Self::State as UsesInput>::Input> {
/// The state known by this type.
type State: State;
}
// blanket impl which automatically defines UsesInput for anything that implements UsesState
impl<KS> UsesInput for KS
where
KS: UsesState,
{
type Input = <KS::State as UsesInput>::Input;
}
/// Trait for elements offering a corpus
pub trait HasCorpus {
/// The associated type implementing [`Corpus`].
@ -84,6 +53,32 @@ pub trait HasCorpus {
fn corpus_mut(&mut self) -> &mut Self::Corpus;
}
/// The trait that implements the very standard capability of a state.
/// This state contains important information about the current run
/// and can be used to restart the fuzzing process at any time.
///
/// This [`State`] is here for documentation purpose.
/// You should *NOT* implement this trait for any of your struct,
/// but when you implement your customized state, you can look at this trait to see what would be needed.
#[allow(dead_code)]
trait State:
Serialize
+ DeserializeOwned
+ MaybeHasClientPerfMonitor
+ HasCurrentCorpusId
+ HasCurrentStageId
+ Stoppable
{
}
impl<I, C, R, SC> State for StdState<I, C, R, SC>
where
C: Serialize + DeserializeOwned,
R: Rand,
SC: Serialize + DeserializeOwned,
{
}
// Reflexivity
impl<C> HasCorpus for C
where
@ -153,29 +148,6 @@ impl<T> MaybeHasClientPerfMonitor for T {}
#[cfg(feature = "introspection")]
impl<T> MaybeHasClientPerfMonitor for T where T: HasClientPerfMonitor {}
/// Intermediate trait for `HasScalabilityMonitor`
#[cfg(feature = "scalability_introspection")]
pub trait MaybeHasScalabilityMonitor: HasScalabilityMonitor {}
/// Intermediate trait for `HasScalabilityMonitor`
#[cfg(not(feature = "scalability_introspection"))]
pub trait MaybeHasScalabilityMonitor {}
#[cfg(not(feature = "scalability_introspection"))]
impl<T> MaybeHasScalabilityMonitor for T {}
#[cfg(feature = "scalability_introspection")]
impl<T> MaybeHasScalabilityMonitor for T where T: HasScalabilityMonitor {}
/// Trait for offering a [`ScalabilityMonitor`]
#[cfg(feature = "scalability_introspection")]
pub trait HasScalabilityMonitor {
/// Ref to [`ScalabilityMonitor`]
fn scalability_monitor(&self) -> &ScalabilityMonitor;
/// Mutable ref to [`ScalabilityMonitor`]
fn scalability_monitor_mut(&mut self) -> &mut ScalabilityMonitor;
}
/// Trait for the execution counter
pub trait HasExecutions {
/// The executions counter
@ -270,8 +242,6 @@ pub struct StdState<I, C, R, SC> {
/// Performance statistics for this fuzzer
#[cfg(feature = "introspection")]
introspection_monitor: ClientPerfMonitor,
#[cfg(feature = "scalability_introspection")]
scalability_monitor: ScalabilityMonitor,
#[cfg(feature = "std")]
/// Remaining initial inputs to load, if any
remaining_initial_files: Option<Vec<PathBuf>>,
@ -296,22 +266,6 @@ pub struct StdState<I, C, R, SC> {
phantom: PhantomData<I>,
}
impl<I, C, R, SC> UsesInput for StdState<I, C, R, SC>
where
I: Input,
{
type Input = I;
}
impl<I, C, R, SC> State for StdState<I, C, R, SC>
where
C: Corpus<Input = Self::Input> + Serialize + DeserializeOwned,
R: Rand,
SC: Corpus<Input = Self::Input> + Serialize + DeserializeOwned,
Self: UsesInput,
{
}
impl<I, C, R, SC> HasRand for StdState<I, C, R, SC>
where
R: Rand,
@ -368,7 +322,8 @@ where
impl<I, C, R, SC> HasSolutions for StdState<I, C, R, SC>
where
I: Input,
SC: Corpus<Input = <Self as UsesInput>::Input>,
C: Corpus,
SC: Corpus<Input = C::Input>,
{
type Solutions = SC;
@ -629,9 +584,9 @@ impl<I, C, R, SC> HasNestedStageStatus for StdState<I, C, R, SC> {
impl<C, I, R, SC> StdState<I, C, R, SC>
where
I: Input,
C: Corpus<Input = <Self as UsesInput>::Input>,
R: Rand,
SC: Corpus<Input = <Self as UsesInput>::Input>,
C: Corpus,
SC: Corpus<Input = C::Input>,
{
/// Decide if the state must load the inputs
pub fn must_load_initial_inputs(&self) -> bool {
@ -723,7 +678,7 @@ where
load_config: LoadConfig<I, Self, Z>,
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
if let Some(remaining) = self.remaining_initial_files.as_ref() {
@ -747,7 +702,7 @@ where
config: &mut LoadConfig<I, Self, Z>,
) -> Result<ExecuteInputResult, Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
log::info!("Loading file {path:?} ...");
@ -781,7 +736,7 @@ where
mut config: LoadConfig<I, Self, Z>,
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
loop {
@ -845,7 +800,7 @@ where
file_list: &[PathBuf],
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
self.load_initial_inputs_custom_by_filenames(
@ -872,7 +827,7 @@ where
in_dirs: &[PathBuf],
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
self.canonicalize_input_dirs(in_dirs)?;
@ -898,7 +853,7 @@ where
file_list: &[PathBuf],
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
self.load_initial_inputs_custom_by_filenames(
@ -923,7 +878,7 @@ where
in_dirs: &[PathBuf],
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
self.canonicalize_input_dirs(in_dirs)?;
@ -949,7 +904,7 @@ where
in_dirs: &[PathBuf],
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
self.canonicalize_input_dirs(in_dirs)?;
@ -990,7 +945,7 @@ where
cores: &Cores,
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
EM: EventFirer<I, Self>,
Z: Evaluator<E, EM, I, Self>,
{
if self.multicore_inputs_processed.unwrap_or(false) {
@ -1070,9 +1025,9 @@ where
impl<C, I, R, SC> StdState<I, C, R, SC>
where
I: Input,
C: Corpus<Input = <Self as UsesInput>::Input>,
C: Corpus<Input = I>,
R: Rand,
SC: Corpus<Input = <Self as UsesInput>::Input>,
SC: Corpus<Input = I>,
{
fn generate_initial_internal<G, E, EM, Z>(
&mut self,
@ -1084,8 +1039,8 @@ where
forced: bool,
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
G: Generator<<Self as UsesInput>::Input, Self>,
EM: EventFirer<I, Self>,
G: Generator<C::Input, Self>,
Z: Evaluator<E, EM, I, Self>,
{
let mut added = 0;
@ -1122,8 +1077,8 @@ where
num: usize,
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
G: Generator<<Self as UsesInput>::Input, Self>,
EM: EventFirer<I, Self>,
G: Generator<C::Input, Self>,
Z: Evaluator<E, EM, I, Self>,
{
self.generate_initial_internal(fuzzer, executor, generator, manager, num, true)
@ -1139,8 +1094,8 @@ where
num: usize,
) -> Result<(), Error>
where
EM: EventFirer<State = Self>,
G: Generator<<Self as UsesInput>::Input, Self>,
EM: EventFirer<I, Self>,
G: Generator<C::Input, Self>,
Z: Evaluator<E, EM, I, Self>,
{
self.generate_initial_internal(fuzzer, executor, generator, manager, num, false)
@ -1173,8 +1128,6 @@ where
stop_requested: false,
#[cfg(feature = "introspection")]
introspection_monitor: ClientPerfMonitor::new(),
#[cfg(feature = "scalability_introspection")]
scalability_monitor: ScalabilityMonitor::new(),
#[cfg(feature = "std")]
remaining_initial_files: None,
#[cfg(feature = "std")]
@ -1221,17 +1174,6 @@ impl<I, C, R, SC> HasClientPerfMonitor for StdState<I, C, R, SC> {
}
}
#[cfg(feature = "scalability_introspection")]
impl<I, C, R, SC> HasScalabilityMonitor for StdState<I, C, R, SC> {
fn scalability_monitor(&self) -> &ScalabilityMonitor {
&self.scalability_monitor
}
fn scalability_monitor_mut(&mut self) -> &mut ScalabilityMonitor {
&mut self.scalability_monitor
}
}
/// A very simple state without any bells or whistles, for testing.
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct NopState<I> {
@ -1280,13 +1222,6 @@ impl<I> HasCorpus for NopState<I> {
}
}
impl<I> UsesInput for NopState<I>
where
I: Input,
{
type Input = I;
}
impl<I> HasExecutions for NopState<I> {
fn executions(&self) -> &u64 {
&self.execution
@ -1353,8 +1288,6 @@ impl<I> HasRand for NopState<I> {
}
}
impl<I> State for NopState<I> where I: Input {}
impl<I> HasCurrentCorpusId for NopState<I> {
fn set_corpus_id(&mut self, _id: CorpusId) -> Result<(), Error> {
Ok(())
@ -1394,17 +1327,6 @@ impl<I> HasClientPerfMonitor for NopState<I> {
}
}
#[cfg(feature = "scalability_introspection")]
impl<I> HasScalabilityMonitor for NopState<I> {
fn scalability_monitor(&self) -> &ScalabilityMonitor {
unimplemented!();
}
fn scalability_monitor_mut(&mut self) -> &mut ScalabilityMonitor {
unimplemented!();
}
}
#[cfg(test)]
mod test {
use crate::{inputs::BytesInput, state::StdState};

View File

@ -13,11 +13,11 @@ use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity};
use frida_gum::interceptor::Interceptor;
use frida_gum::ModuleDetails;
use libafl::{
corpus::Testcase,
corpus::{Corpus, Testcase},
executors::ExitKind,
feedbacks::{Feedback, StateInitializer},
observers::Observer,
state::State,
state::HasCorpus,
Error, HasMetadata,
};
use libafl_bolts::{
@ -648,16 +648,16 @@ pub struct AsanErrorsFeedback<S> {
impl<S> StateInitializer<S> for AsanErrorsFeedback<S> {}
impl<EM, OT, S> Feedback<EM, S::Input, OT, S> for AsanErrorsFeedback<S>
impl<EM, OT, S> Feedback<EM, <S::Corpus as Corpus>::Input, OT, S> for AsanErrorsFeedback<S>
where
S: State + Debug,
S: HasCorpus + Debug,
OT: MatchNameRef,
{
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &<S::Corpus as Corpus>::Input,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error> {
@ -678,7 +678,7 @@ where
_state: &mut S,
_manager: &mut EM,
_observers: &OT,
testcase: &mut Testcase<S::Input>,
testcase: &mut Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> {
if let Some(errors) = &self.errors {
testcase.add_metadata(errors.clone());
@ -687,7 +687,11 @@ where
Ok(())
}
fn discard_metadata(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
fn discard_metadata(
&mut self,
_state: &mut S,
_input: &<S::Corpus as Corpus>::Input,
) -> Result<(), Error> {
self.errors = None;
Ok(())
}

View File

@ -16,9 +16,9 @@ use libafl::{
};
use libafl::{
executors::{Executor, ExitKind, HasObservers, InProcessExecutor},
inputs::{NopTargetBytesConverter, TargetBytesConverter, UsesInput},
inputs::{NopTargetBytesConverter, TargetBytesConverter},
observers::ObserversTuple,
state::{HasCorpus, HasExecutions, UsesState},
state::{HasCorpus, HasExecutions},
Error,
};
use libafl_bolts::{tuples::RefIndexable, AsSlice};
@ -59,9 +59,8 @@ where
impl<EM, H, I, OT, RT, S, TC, Z> Executor<EM, I, S, Z>
for FridaInProcessExecutor<'_, '_, '_, H, I, OT, RT, S, TC>
where
EM: UsesState<State = S>,
H: FnMut(&I) -> ExitKind,
S: HasCorpus + HasExecutions + UsesInput<Input = I>,
S: HasCorpus + HasExecutions,
TC: TargetBytesConverter<Input = I>,
OT: ObserversTuple<I, S>,
RT: FridaRuntimeTuple,
@ -226,7 +225,7 @@ impl<'a, 'b, 'c, H, I, OT, RT, S, TC> HasInProcessHooks<I, S>
for FridaInProcessExecutor<'a, 'b, 'c, H, I, OT, RT, S, TC>
where
H: FnMut(&I) -> ExitKind,
S: HasSolutions + HasCorpus + HasCurrentTestcase + HasExecutions + UsesInput<Input = I>,
S: HasSolutions + HasCorpus + HasCurrentTestcase + HasExecutions,
S::Solutions: Corpus<Input = I>,
I: Input,
TC: TargetBytesConverter<Input = I>,

View File

@ -161,7 +161,7 @@ fn main() -> Result<(), Box<dyn Error>> {
.arg(&archive_path)
.stdout(Stdio::piped())
.spawn()
.expect("llvm-nm works (are you using nightly?)");
.expect("llvm-nm does not work (are you using nightly? or did you install by rustup component add llvm-tools?)");
let mut redefinitions_file = BufWriter::new(File::create(&redefined_symbols).unwrap());

View File

@ -4,11 +4,11 @@ use std::borrow::Cow;
use libafl::{
alloc,
corpus::Testcase,
corpus::{Corpus, Testcase},
executors::ExitKind,
feedbacks::{Feedback, MinMapFeedback, StateInitializer},
inputs::{BytesInput, Input},
state::State,
state::HasCorpus,
Error, HasMetadata,
};
use libafl_bolts::{impl_serdeany, tuples::MatchNameRef, Named};
@ -43,15 +43,15 @@ impl Named for LibfuzzerKeepFeedback {
impl<S> StateInitializer<S> for LibfuzzerKeepFeedback {}
impl<EM, OT, S> Feedback<EM, S::Input, OT, S> for LibfuzzerKeepFeedback
impl<EM, OT, S> Feedback<EM, <S::Corpus as Corpus>::Input, OT, S> for LibfuzzerKeepFeedback
where
S: State,
S: HasCorpus,
{
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &<S::Corpus as Corpus>::Input,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error> {
@ -119,7 +119,6 @@ impl<S> StateInitializer<S> for LibfuzzerCrashCauseFeedback {}
impl<EM, OT, S> Feedback<EM, BytesInput, OT, S> for LibfuzzerCrashCauseFeedback
where
S: State<Input = BytesInput>,
OT: MatchNameRef,
{
fn is_interesting(

View File

@ -17,10 +17,9 @@ use libafl::{
SimpleRestartingEventManager,
},
executors::ExitKind,
inputs::UsesInput,
monitors::{tui::TuiMonitor, Monitor, MultiMonitor},
stages::{HasCurrentStageId, StagesTuple},
state::{HasExecutions, HasLastReportTime, HasSolutions, Stoppable, UsesState},
state::{HasExecutions, HasLastReportTime, HasSolutions, Stoppable},
Error, Fuzzer, HasMetadata,
};
use libafl_bolts::{
@ -65,12 +64,11 @@ where
F: Fuzzer<E, EM, S, ST>,
S: HasMetadata
+ HasExecutions
+ UsesInput
+ HasSolutions
+ HasLastReportTime
+ HasCurrentStageId
+ Stoppable,
EM: ProgressReporter<State = S> + EventProcessor<E, F>,
EM: ProgressReporter<S> + EventProcessor<E, S, F>,
ST: StagesTuple<E, EM, S, F>,
{
if let Some(solution) = state.solutions().last() {
@ -113,7 +111,7 @@ where
fuzz_with!(options, harness, do_fuzz, |fuzz_single| {
let (state, mgr): (
Option<StdState<_, _, _, _>>,
SimpleRestartingEventManager<_, StdState<_, _, _, _>, _>,
SimpleRestartingEventManager<_, _, StdState<_, _, _, _>, _>,
) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) {
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
Ok(res) => res,

View File

@ -9,7 +9,7 @@ use std::{
use libafl::{
corpus::Corpus,
events::{EventRestarter, SimpleRestartingEventManager},
events::{EventRestarter, ManagerExit, SimpleRestartingEventManager},
executors::{ExitKind, InProcessExecutor},
feedback_and_fast, feedback_or_fast,
feedbacks::{CrashFeedback, MinMapFeedback, TimeoutFeedback},
@ -69,7 +69,7 @@ pub fn merge(
let (state, mut mgr): (
Option<StdState<_, _, _, _>>,
SimpleRestartingEventManager<_, StdState<_, _, _, _>, _>,
SimpleRestartingEventManager<_, _, StdState<_, _, _, _>, _>,
) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) {
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
Ok(res) => res,

View File

@ -7,10 +7,10 @@ use std::{
use ahash::AHasher;
use libafl::{
corpus::Corpus,
executors::ExitKind,
inputs::UsesInput,
observers::{MapObserver, Observer, TimeObserver},
state::UsesState,
state::HasCorpus,
Error,
};
use libafl_bolts::{AsIter, HasLen, Named};
@ -158,13 +158,17 @@ where
}
}
impl<M, O, S> Observer<S::Input, S> for MappedEdgeMapObserver<M, O>
impl<M, O, S> Observer<<S::Corpus as Corpus>::Input, S> for MappedEdgeMapObserver<M, O>
where
M: Observer<S::Input, S> + Debug,
O: Observer<S::Input, S> + Debug,
S: UsesInput,
S: HasCorpus,
M: Observer<<S::Corpus as Corpus>::Input, S> + Debug,
O: Observer<<S::Corpus as Corpus>::Input, S> + Debug,
{
fn pre_exec(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error> {
fn pre_exec(
&mut self,
state: &mut S,
input: &<S::Corpus as Corpus>::Input,
) -> Result<(), Error> {
self.inner.pre_exec(state, input)?;
self.value_observer.pre_exec(state, input)
}
@ -172,7 +176,7 @@ where
fn post_exec(
&mut self,
state: &mut S,
input: &S::Input,
input: &<S::Corpus as Corpus>::Input,
exit_kind: &ExitKind,
) -> Result<(), Error> {
self.inner.post_exec(state, input, exit_kind)?;
@ -255,12 +259,16 @@ impl Named for SizeValueObserver {
}
}
impl<S> Observer<S::Input, S> for SizeValueObserver
impl<S> Observer<<S::Corpus as Corpus>::Input, S> for SizeValueObserver
where
S: UsesInput,
S::Input: HasLen,
S: HasCorpus,
<S::Corpus as Corpus>::Input: HasLen,
{
fn pre_exec(&mut self, _state: &mut S, input: &S::Input) -> Result<(), Error> {
fn pre_exec(
&mut self,
_state: &mut S,
input: &<S::Corpus as Corpus>::Input,
) -> Result<(), Error> {
self.size = input.len();
Ok(())
}
@ -299,18 +307,22 @@ impl Named for TimeValueObserver {
}
}
impl<S> Observer<S::Input, S> for TimeValueObserver
impl<S> Observer<<S::Corpus as Corpus>::Input, S> for TimeValueObserver
where
S: UsesInput,
S: HasCorpus,
{
fn pre_exec(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error> {
fn pre_exec(
&mut self,
state: &mut S,
input: &<S::Corpus as Corpus>::Input,
) -> Result<(), Error> {
self.time_obs.pre_exec(state, input)
}
fn post_exec(
&mut self,
state: &mut S,
input: &S::Input,
input: &<S::Corpus as Corpus>::Input,
exit_kind: &ExitKind,
) -> Result<(), Error> {
self.time_obs.post_exec(state, input, exit_kind)?;
@ -361,12 +373,16 @@ impl Named for SizeTimeValueObserver {
}
}
impl<S> Observer<S::Input, S> for SizeTimeValueObserver
impl<S> Observer<<S::Corpus as Corpus>::Input, S> for SizeTimeValueObserver
where
S: UsesInput,
S::Input: HasLen,
S: HasCorpus,
<S::Corpus as Corpus>::Input: HasLen,
{
fn pre_exec(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error> {
fn pre_exec(
&mut self,
state: &mut S,
input: &<S::Corpus as Corpus>::Input,
) -> Result<(), Error> {
self.size_obs.pre_exec(state, input)?;
self.time_obs.pre_exec(state, input)
}
@ -374,7 +390,7 @@ where
fn post_exec(
&mut self,
state: &mut S,
input: &S::Input,
input: &<S::Corpus as Corpus>::Input,
exit_kind: &ExitKind,
) -> Result<(), Error> {
self.time_obs.post_exec(state, input, exit_kind)?;

View File

@ -4,10 +4,9 @@ use libafl::{
events::{EventProcessor, ProgressReporter, SimpleEventManager},
executors::HasObservers,
feedbacks::MapFeedbackMetadata,
inputs::UsesInput,
monitors::SimpleMonitor,
stages::{HasCurrentStageId, StagesTuple},
state::{HasExecutions, HasLastReportTime, Stoppable, UsesState},
state::{HasExecutions, HasLastReportTime, Stoppable},
Error, Fuzzer, HasMetadata, HasNamedMetadata,
};
@ -27,12 +26,11 @@ where
S: HasMetadata
+ HasNamedMetadata
+ HasExecutions
+ UsesInput
+ HasLastReportTime
+ HasCurrentStageId
+ Stoppable,
E: HasObservers,
EM: ProgressReporter<State = S> + EventProcessor<E, F>,
EM: ProgressReporter<S> + EventProcessor<E, S, F>,
ST: StagesTuple<E, EM, S, F>,
{
let meta = state

View File

@ -6,7 +6,7 @@ use libafl::{
feedbacks::MapNoveltiesMetadata,
inputs::Input,
schedulers::{RemovableScheduler, Scheduler},
state::{HasCorpus, State},
state::HasCorpus,
Error, HasMetadata,
};
@ -20,7 +20,7 @@ pub struct MergeScheduler<I, S> {
impl<I, S> RemovableScheduler<I, S> for MergeScheduler<I, S>
where
I: Input,
S: State + HasCorpus,
S: HasCorpus,
{
fn on_remove(
&mut self,
@ -35,7 +35,7 @@ where
impl<I, S> Scheduler<I, S> for MergeScheduler<I, S>
where
S: State + HasCorpus,
S: HasCorpus,
{
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
self.all.insert(id);

View File

@ -7,9 +7,9 @@ use std::{
use libafl::{
corpus::Corpus,
executors::{Executor, ExitKind, HasObservers, HasTimeout},
inputs::{HasTargetBytes, UsesInput},
inputs::HasTargetBytes,
observers::{ObserversTuple, StdOutObserver},
state::{HasCorpus, HasExecutions, UsesState},
state::{HasCorpus, HasExecutions},
Error,
};
use libafl_bolts::{tuples::RefIndexable, AsSlice};
@ -41,8 +41,7 @@ impl NyxExecutor<(), ()> {
impl<EM, S, Z, OT> Executor<EM, <S::Corpus as Corpus>::Input, S, Z> for NyxExecutor<S, OT>
where
EM: UsesState<State = S>,
S: HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasCorpus + HasExecutions,
<S::Corpus as Corpus>::Input: HasTargetBytes,
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
{

View File

@ -1,9 +1,6 @@
use std::marker::PhantomData;
use libafl::{
inputs::HasTargetBytes,
state::{HasExecutions, State},
};
use libafl::{inputs::HasTargetBytes, state::HasExecutions};
use libafl_bolts::tuples::{tuple_list, Append, Prepend};
#[cfg(feature = "systemmode")]
@ -74,7 +71,7 @@ impl<C, I, S>
StdSnapshotManager,
>
where
S: State + HasExecutions + Unpin,
S: HasExecutions + Unpin,
I: HasTargetBytes,
{
#[must_use]
@ -104,7 +101,7 @@ impl<C, I, S>
StdSnapshotManager,
>
where
S: State + HasExecutions + Unpin,
S: HasExecutions + Unpin,
I: HasTargetBytes,
{
#[expect(clippy::should_implement_trait)]

View File

@ -7,10 +7,7 @@ use std::{cell::RefCell, ops::Add, pin::Pin};
use hashbrown::HashMap;
use libafl::{
executors::ExitKind,
inputs::HasTargetBytes,
observers::ObserversTuple,
state::{HasExecutions, State},
executors::ExitKind, inputs::HasTargetBytes, observers::ObserversTuple, state::HasExecutions,
};
use libafl_qemu_sys::{GuestAddr, GuestPhysAddr, GuestUsize, GuestVirtAddr};
@ -253,7 +250,7 @@ impl<C, I, S> Emulator<C, NopCommandManager, NopEmulatorDriver, (), I, S, NopSna
impl<C, I, S> Emulator<C, StdCommandManager<S>, StdEmulatorDriver, (), I, S, StdSnapshotManager>
where
S: State + HasExecutions + Unpin,
S: HasExecutions + Unpin,
I: HasTargetBytes,
{
#[must_use]

View File

@ -20,9 +20,9 @@ use libafl::{
},
feedbacks::Feedback,
fuzzer::HasObjective,
inputs::{Input, UsesInput},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions, State, UsesState},
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
Error, ExecutionProcessor, HasScheduler,
};
#[cfg(feature = "fork")]
@ -92,11 +92,11 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, I, OF, S, Z>(
) where
E: HasObservers + HasInProcessHooks<I, S> + Executor<EM, I, S, Z>,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
ET: EmulatorModuleTuple<I, S>,
I: Unpin,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCorpus + Unpin + HasCurrentTestcase + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCorpus + Unpin + HasCurrentTestcase,
I: Input,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF>,
@ -152,7 +152,7 @@ where
H: FnMut(&mut Emulator<C, CM, ED, ET, I, S, SM>, &mut S, &I) -> ExitKind,
I: Input + Unpin,
OT: ObserversTuple<I, S>,
S: HasCorpus + Unpin + HasExecutions + HasSolutions + State<Input = I>,
S: HasCorpus + Unpin + HasExecutions + HasSolutions + HasCurrentTestcase,
S::Solutions: Corpus<Input = I>,
{
pub fn new<EM, OF, Z>(
@ -168,7 +168,7 @@ where
C: Clone,
CM: CommandManager<C, ED, ET, I, S, SM, Commands = C>,
ED: EmulatorDriver<C, CM, ET, I, S, SM>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF> + HasScheduler<I, S> + ExecutionProcessor<EM, I, OT, S>,
<S as HasCorpus>::Corpus: Corpus<Input = I>,
@ -248,12 +248,11 @@ where
C: Clone,
CM: CommandManager<C, ED, ET, I, S, SM, Commands = C>,
ED: EmulatorDriver<C, CM, ET, I, S, SM>,
EM: UsesState<State = S>,
ET: EmulatorModuleTuple<I, S>,
H: FnMut(&mut Emulator<C, CM, ED, ET, I, S, SM>, &mut S, &I) -> ExitKind,
I: Unpin,
OT: ObserversTuple<I, S>,
S: State + HasExecutions + Unpin + HasCorpus,
S: HasExecutions + Unpin + HasCorpus,
{
fn run_target(
&mut self,
@ -290,7 +289,7 @@ where
ET: EmulatorModuleTuple<I, S>,
H: FnMut(&mut Emulator<C, CM, ED, ET, I, S, SM>, &mut S, &I) -> ExitKind,
OT: ObserversTuple<I, S>,
S: State + HasCorpus,
S: HasCorpus,
{
type Observers = OT;
#[inline]
@ -318,12 +317,11 @@ impl<C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> Debug
where
C: Debug,
CM: Debug,
EM: UsesState<State = S>,
ED: Debug,
ET: EmulatorModuleTuple<I, S> + Debug,
OT: ObserversTuple<I, S> + Debug,
I: Debug,
S: UsesInput<Input = I> + Debug,
S: Debug,
SM: Debug,
SP: ShMemProvider,
{
@ -339,10 +337,10 @@ where
impl<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z>
QemuForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z>
where
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
ET: EmulatorModuleTuple<I, S>,
OT: ObserversTuple<I, S>,
S: State + HasSolutions + HasCorpus,
S: HasSolutions + HasCorpus,
SP: ShMemProvider,
Z: HasObjective,
Z::Objective: Feedback<EM, I, OT, S>,
@ -404,13 +402,13 @@ where
C: Clone,
CM: CommandManager<C, ED, ET, I, S, SM, Commands = C>,
ED: EmulatorDriver<C, CM, ET, I, S, SM>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
ET: EmulatorModuleTuple<I, S>,
H: FnMut(&mut Emulator<C, CM, ED, ET, I, S, SM>, &I) -> ExitKind,
OF: Feedback<EM, I, OT, S>,
OT: ObserversTuple<I, S> + Debug,
I: Input + Unpin,
S: State + HasExecutions + Unpin + HasCorpus,
S: HasExecutions + Unpin + HasCorpus,
SP: ShMemProvider,
Z: HasObjective<Objective = OF>,
{
@ -438,26 +436,12 @@ where
}
}
#[cfg(feature = "fork")]
impl<C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> UsesState
for QemuForkExecutor<'_, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z>
where
ET: EmulatorModuleTuple<I, S>,
OT: ObserversTuple<I, S>,
S: State,
SP: ShMemProvider,
{
type State = S;
}
#[cfg(feature = "fork")]
impl<C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> HasObservers
for QemuForkExecutor<'_, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z>
where
EM: UsesState<State = S>,
ET: EmulatorModuleTuple<I, S>,
OT: ObserversTuple<I, S>,
S: State,
SP: ShMemProvider,
{
type Observers = OT;

View File

@ -4,10 +4,10 @@ use core::marker::PhantomData;
use libafl::{
corpus::{Corpus, HasCurrentCorpusId},
executors::{Executor, HasObservers},
inputs::{BytesInput, UsesInput},
inputs::BytesInput,
observers::ObserversTuple,
stages::{colorization::TaintMetadata, RetryCountRestartHelper, Stage},
state::{HasCorpus, HasCurrentTestcase, UsesState},
state::{HasCorpus, HasCurrentTestcase},
Error, HasMetadata, HasNamedMetadata,
};
use libafl_bolts::{
@ -36,15 +36,9 @@ 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, BytesInput, S, Z>,
TE::Observers: MatchNameRef + ObserversTuple<BytesInput, S>,
S: HasCorpus
+ HasCurrentTestcase
+ UsesInput<Input = BytesInput>
+ HasMetadata
+ HasNamedMetadata
+ HasCurrentCorpusId,
S: HasCorpus + HasCurrentTestcase + HasMetadata + HasNamedMetadata + HasCurrentCorpusId,
S::Corpus: Corpus<Input = BytesInput>,
{
#[inline]

View File

@ -11,7 +11,7 @@ use std::{
use libafl::{
corpus::Corpus,
inputs::{BytesInput, HasMutatorBytes, UsesInput},
inputs::{BytesInput, HasMutatorBytes},
mutators::{
ComposedByMutations, MutationId, MutationResult, Mutator, MutatorsTuple, ScheduledMutator,
},
@ -152,7 +152,7 @@ where
F: Fn(&mut dyn for<'b> FnMut(&'b mut S)) -> bool,
M: ScheduledMutator<BytesInput, S>,
M::Mutations: MutatorsTuple<BytesInput, S>,
S: HasMaxSize + UsesInput<Input = BytesInput>,
S: HasMaxSize,
{
fn mutate(&self, data: *mut u8, size: usize, max_size: usize) -> usize {
let mut new_size = 0; // if access fails, the new len is zero
@ -290,12 +290,12 @@ impl<S, SM> Named for LLVMCustomMutator<S, SM, false> {
impl<S, SM> Mutator<BytesInput, S> for LLVMCustomMutator<S, SM, false>
where
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + 'static,
S: HasRand + HasMaxSize + 'static,
SM: ScheduledMutator<BytesInput, S> + 'static,
SM::Mutations: MutatorsTuple<BytesInput, S>,
{
#[inline]
fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> {
fn mutate(&mut self, state: &mut S, input: &mut BytesInput) -> Result<MutationResult, Error> {
self.scheduled_mutate(state, input)
}
}
@ -303,15 +303,15 @@ where
impl<S, SM> ScheduledMutator<BytesInput, S> for LLVMCustomMutator<S, SM, false>
where
SM: ScheduledMutator<BytesInput, S> + 'static,
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + 'static,
S: HasRand + HasMaxSize + 'static,
SM::Mutations: MutatorsTuple<BytesInput, S>,
{
fn iterations(&self, state: &mut S, input: &S::Input) -> u64 {
fn iterations(&self, state: &mut S, input: &BytesInput) -> u64 {
let mutator = self.mutator.deref().borrow();
mutator.iterations(state, input)
}
fn schedule(&self, state: &mut S, input: &S::Input) -> MutationId {
fn schedule(&self, state: &mut S, input: &BytesInput) -> MutationId {
let mutator = self.mutator.deref().borrow();
mutator.schedule(state, input)
}
@ -319,7 +319,7 @@ where
fn scheduled_mutate(
&mut self,
state: &mut S,
input: &mut S::Input,
input: &mut BytesInput,
) -> Result<MutationResult, Error> {
let seed = state.rand_mut().next();
let len_orig = input.bytes().len();
@ -367,13 +367,13 @@ impl<S, SM> Named for LLVMCustomMutator<S, SM, true> {
impl<S, SM> Mutator<BytesInput, S> for LLVMCustomMutator<S, SM, true>
where
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + HasCorpus + 'static,
S: HasRand + HasMaxSize + HasCorpus + 'static,
SM: ScheduledMutator<BytesInput, S> + 'static,
S::Corpus: Corpus<Input = BytesInput>,
SM::Mutations: MutatorsTuple<BytesInput, S>,
{
#[inline]
fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> {
fn mutate(&mut self, state: &mut S, input: &mut BytesInput) -> Result<MutationResult, Error> {
self.scheduled_mutate(state, input)
}
}
@ -381,16 +381,16 @@ where
impl<S, SM> ScheduledMutator<BytesInput, S> for LLVMCustomMutator<S, SM, true>
where
SM: ScheduledMutator<BytesInput, S> + 'static,
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + HasCorpus + 'static,
S: HasRand + HasMaxSize + HasCorpus + 'static,
S::Corpus: Corpus<Input = BytesInput>,
SM::Mutations: MutatorsTuple<BytesInput, S>,
{
fn iterations(&self, state: &mut S, input: &S::Input) -> u64 {
fn iterations(&self, state: &mut S, input: &BytesInput) -> u64 {
let mutator = self.mutator.deref().borrow();
mutator.iterations(state, input)
}
fn schedule(&self, state: &mut S, input: &S::Input) -> MutationId {
fn schedule(&self, state: &mut S, input: &BytesInput) -> MutationId {
let mutator = self.mutator.deref().borrow();
mutator.schedule(state, input)
}
@ -398,7 +398,7 @@ where
fn scheduled_mutate(
&mut self,
state: &mut S,
input: &mut S::Input,
input: &mut BytesInput,
) -> Result<MutationResult, Error> {
let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
// We don't want to use the testcase we're already using for splicing

View File

@ -5,7 +5,7 @@ use libafl::{
events::{EventFirer, EventRestarter},
executors::{hooks::windows::windows_asan_handler::asan_death_handler, Executor, HasObservers},
feedbacks::Feedback,
inputs::{Input, UsesInput},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
HasObjective,
@ -34,9 +34,9 @@ pub unsafe fn setup_asan_callback<E, EM, I, OF, S, Z>(_executor: &E, _event_mgr:
where
E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput<Input = I>,
S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus,
S::Solutions: Corpus<Input = I>,
Z: HasObjective<Objective = OF>,
I: Input + Clone,

View File

@ -3,8 +3,8 @@ use core::{marker::PhantomData, ptr, time::Duration};
use libafl::{
corpus::Corpus,
executors::{Executor, ExitKind, HasObservers},
inputs::{HasTargetBytes, UsesInput},
state::{HasCorpus, HasExecutions, UsesState},
inputs::HasTargetBytes,
state::{HasCorpus, HasExecutions},
Error,
};
use libafl_bolts::{
@ -51,8 +51,7 @@ where
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: HasCorpus + HasExecutions + UsesInput<Input = <S::Corpus as Corpus>::Input>,
S: HasCorpus + HasExecutions,
<S::Corpus as Corpus>::Input: HasTargetBytes,
SP: ShMemProvider,
{