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:
parent
ba09cb0706
commit
435ca021cc
@ -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()?;`
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -10,7 +10,7 @@ use libafl::{
|
||||
corpus::{Corpus, InMemoryCorpus},
|
||||
events::{
|
||||
launcher::Launcher, ClientDescription, EventConfig, EventRestarter,
|
||||
LlmpRestartingEventManager,
|
||||
LlmpRestartingEventManager, ManagerExit,
|
||||
},
|
||||
executors::ExitKind,
|
||||
fuzzer::StdFuzzer,
|
||||
|
@ -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),
|
||||
|
@ -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)?;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -30,7 +30,6 @@ libafl = { path = "../../../libafl", features = [
|
||||
"prelude",
|
||||
"gzip",
|
||||
"regex",
|
||||
"scalability_introspection",
|
||||
] }
|
||||
libafl_bolts = { path = "../../../libafl_bolts", features = [
|
||||
"errors_backtrace",
|
||||
|
@ -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.
|
||||
|
@ -43,7 +43,6 @@ libafl = { path = "../../../libafl", default-features = false, features = [
|
||||
"prelude",
|
||||
"gzip",
|
||||
"regex",
|
||||
"scalability_introspection",
|
||||
"multi_machine",
|
||||
"errors_backtrace",
|
||||
] }
|
||||
|
@ -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"]
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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(());
|
||||
|
@ -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(),
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
)?;
|
||||
|
@ -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}");
|
||||
}));
|
||||
|
@ -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.
|
||||
|
@ -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>,
|
||||
|
@ -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>,
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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>,
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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> {
|
||||
|
@ -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)]
|
||||
|
@ -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(
|
||||
|
@ -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>,
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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]
|
||||
|
@ -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(
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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(
|
||||
|
@ -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};
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)?;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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>,
|
||||
{
|
||||
|
@ -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)]
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user