From 435ca021cc3561eaee0e43102b98b56263316b79 Mon Sep 17 00:00:00 2001 From: "Dongjia \"toka\" Zhang" Date: Wed, 15 Jan 2025 16:56:40 +0100 Subject: [PATCH] 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 --- MIGRATION.md | 4 + .../baby_fuzzer_custom_executor/src/main.rs | 7 +- fuzzers/binary_only/qemu_cmin/src/fuzzer.rs | 2 +- .../binary_only/qemu_coverage/src/fuzzer.rs | 2 +- .../forkserver/libafl-fuzz/src/executor.rs | 10 +- fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs | 8 +- fuzzers/forkserver/libafl-fuzz/src/hooks.rs | 9 +- .../qemu_linux_kernel/src/fuzzer.rs | 4 +- .../qemu_linux_process/src/fuzzer.rs | 4 +- .../libfuzzer_libpng_centralized/Cargo.toml | 1 - .../libfuzzer_libpng_cmin/src/lib.rs | 19 +- .../Cargo.toml | 1 - libafl/Cargo.toml | 3 - libafl/src/corpus/minimizer.rs | 6 +- libafl/src/events/broker_hooks/centralized.rs | 13 +- .../broker_hooks/centralized_multi_machine.rs | 27 +- libafl/src/events/broker_hooks/mod.rs | 7 +- libafl/src/events/centralized.rs | 289 ++++----- libafl/src/events/events_hooks/mod.rs | 40 +- libafl/src/events/launcher.rs | 49 +- libafl/src/events/llmp/mgr.rs | 287 +++------ libafl/src/events/llmp/mod.rs | 109 +--- libafl/src/events/llmp/restarting.rs | 189 +++--- libafl/src/events/mod.rs | 579 ++++++++---------- libafl/src/events/multi_machine.rs | 15 +- libafl/src/events/simple.rs | 279 +++++---- libafl/src/events/tcp.rs | 297 ++++----- libafl/src/executors/command.rs | 8 +- libafl/src/executors/hooks/inprocess.rs | 17 +- libafl/src/executors/hooks/unix.rs | 14 +- libafl/src/executors/hooks/windows.rs | 20 +- libafl/src/executors/inprocess/inner.rs | 14 +- libafl/src/executors/inprocess/mod.rs | 33 +- libafl/src/executors/inprocess/stateful.rs | 23 +- libafl/src/executors/inprocess_fork/mod.rs | 3 +- libafl/src/executors/mod.rs | 2 +- libafl/src/feedbacks/differential.rs | 2 +- libafl/src/feedbacks/map.rs | 12 +- libafl/src/fuzzer/mod.rs | 48 +- libafl/src/inputs/mod.rs | 7 - libafl/src/monitors/mod.rs | 20 - libafl/src/observers/stdio.rs | 5 +- libafl/src/schedulers/powersched.rs | 4 +- libafl/src/stages/afl_stats.rs | 10 +- libafl/src/stages/calibrate.rs | 7 +- libafl/src/stages/colorization.rs | 20 +- libafl/src/stages/concolic.rs | 10 +- libafl/src/stages/generalization.rs | 15 +- libafl/src/stages/generation.rs | 3 +- libafl/src/stages/mod.rs | 8 +- libafl/src/stages/mutational.rs | 15 +- libafl/src/stages/power.rs | 18 +- libafl/src/stages/push/mod.rs | 13 +- libafl/src/stages/push/mutational.rs | 19 +- libafl/src/stages/sync.rs | 37 +- libafl/src/stages/tmin.rs | 19 +- libafl/src/stages/tracing.rs | 19 +- libafl/src/stages/tuneable.rs | 8 +- libafl/src/stages/verify_timeouts.rs | 7 +- libafl/src/state/mod.rs | 174 ++---- libafl_frida/src/asan/errors.rs | 18 +- libafl_frida/src/executor.rs | 9 +- libafl_libfuzzer/build.rs | 2 +- libafl_libfuzzer/runtime/src/feedbacks.rs | 11 +- libafl_libfuzzer/runtime/src/fuzz.rs | 8 +- libafl_libfuzzer/runtime/src/merge.rs | 4 +- libafl_libfuzzer/runtime/src/observers.rs | 58 +- libafl_libfuzzer/runtime/src/report.rs | 6 +- libafl_libfuzzer/runtime/src/schedulers.rs | 6 +- libafl_nyx/src/executor.rs | 7 +- libafl_qemu/src/emu/builder.rs | 9 +- libafl_qemu/src/emu/mod.rs | 7 +- libafl_qemu/src/executor.rs | 42 +- .../src/cmps/stages/aflpptracing.rs | 12 +- libafl_targets/src/libfuzzer/mutators.rs | 28 +- libafl_targets/src/windows_asan.rs | 6 +- libafl_tinyinst/src/executor.rs | 7 +- 77 files changed, 1310 insertions(+), 1824 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 8897eb3d4c..1949016d1f 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -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` 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()?;` diff --git a/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs index 16002fb13f..a7b036f669 100644 --- a/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs @@ -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 CustomExecutor { impl Executor::Input, S, Z> for CustomExecutor where - EM: UsesState, - S: HasCorpus + HasExecutions + UsesInput::Input>, + S: HasCorpus + HasExecutions, ::Input: HasTargetBytes, { fn run_target( diff --git a/fuzzers/binary_only/qemu_cmin/src/fuzzer.rs b/fuzzers/binary_only/qemu_cmin/src/fuzzer.rs index b38b86ff2d..7b4790f7b5 100644 --- a/fuzzers/binary_only/qemu_cmin/src/fuzzer.rs +++ b/fuzzers/binary_only/qemu_cmin/src/fuzzer.rs @@ -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, diff --git a/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs b/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs index e1f4e5307b..5f8d5b666d 100644 --- a/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs +++ b/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs @@ -10,7 +10,7 @@ use libafl::{ corpus::{Corpus, InMemoryCorpus}, events::{ launcher::Launcher, ClientDescription, EventConfig, EventRestarter, - LlmpRestartingEventManager, + LlmpRestartingEventManager, ManagerExit, }, executors::ExitKind, fuzzer::StdFuzzer, diff --git a/fuzzers/forkserver/libafl-fuzz/src/executor.rs b/fuzzers/forkserver/libafl-fuzz/src/executor.rs index 3cf24c97ce..fbe1e2fea9 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/executor.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/executor.rs @@ -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 { impl Executor::Input, S, Z> for SupportedExecutors where - S: HasCorpus + UsesInput::Input>, + S: HasCorpus, EM: UsesState, NYX: Executor::Input, S, Z>, FSV: Executor::Input, S, Z>, @@ -340,8 +339,7 @@ pub enum SupportedExecutors { impl Executor::Input, S, Z> for SupportedExecutors where - S: HasCorpus + UsesInput::Input>, - EM: UsesState, + S: HasCorpus, FSV: Executor::Input, S, Z>, { fn run_target( @@ -349,7 +347,7 @@ where fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &S::Input, + input: &::Input, ) -> Result { match self { Self::Forkserver(fsrv, _) => fsrv.run_target(fuzzer, state, mgr, input), diff --git a/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs b/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs index 6f7895968d..7ee439740f 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs @@ -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 = SimpleEventManager, LibaflFuzzState>; +type LibaflFuzzManager = SimpleEventManager, 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( ) -> Result<(), Error> where Z: Fuzzer, - EM: ProgressReporter, + EM: ProgressReporter, ST: StagesTuple, - S: HasLastReportTime + HasExecutions + HasMetadata + UsesInput, + S: HasLastReportTime + HasExecutions + HasMetadata, { if opt.bench_just_one { fuzzer.fuzz_loop_for(stages, executor, state, mgr, 1)?; diff --git a/fuzzers/forkserver/libafl-fuzz/src/hooks.rs b/fuzzers/forkserver/libafl-fuzz/src/hooks.rs index 454d9e9ac3..7b50ead881 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/hooks.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/hooks.rs @@ -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 EventManagerHook for LibAflFuzzEventHook +impl EventManagerHook<::Input, S> for LibAflFuzzEventHook where - S: State + Stoppable, + S: HasCorpus + Stoppable, { fn pre_exec( &mut self, state: &mut S, _client_id: ClientId, - event: &Event, + event: &Event<::Input>, ) -> Result { if self.exit_on_solution && matches!(event, Event::Objective { .. }) { // TODO: dump state diff --git a/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs b/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs index 461f273fd1..44d43372f2 100644 --- a/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs +++ b/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs @@ -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( where ET: EmulatorModuleTuple, 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); diff --git a/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs b/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs index a8ef071c64..d88ebe3877 100644 --- a/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs +++ b/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs @@ -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( where ET: EmulatorModuleTuple, 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); diff --git a/fuzzers/inprocess/libfuzzer_libpng_centralized/Cargo.toml b/fuzzers/inprocess/libfuzzer_libpng_centralized/Cargo.toml index 319f0cdc5f..dc7d7e5cb3 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_centralized/Cargo.toml +++ b/fuzzers/inprocess/libfuzzer_libpng_centralized/Cargo.toml @@ -30,7 +30,6 @@ libafl = { path = "../../../libafl", features = [ "prelude", "gzip", "regex", - "scalability_introspection", ] } libafl_bolts = { path = "../../../libafl_bolts", features = [ "errors_backtrace", diff --git a/fuzzers/inprocess/libfuzzer_libpng_cmin/src/lib.rs b/fuzzers/inprocess/libfuzzer_libpng_cmin/src/lib.rs index 5a456892bc..fbfb76f6e6 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_cmin/src/lib.rs +++ b/fuzzers/inprocess/libfuzzer_libpng_cmin/src/lib.rs @@ -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)?; + as EventFirer>::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)?; + as EventFirer>::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. diff --git a/fuzzers/inprocess/sqlite_centralized_multi_machine/Cargo.toml b/fuzzers/inprocess/sqlite_centralized_multi_machine/Cargo.toml index 526258bc11..1dfbd79551 100644 --- a/fuzzers/inprocess/sqlite_centralized_multi_machine/Cargo.toml +++ b/fuzzers/inprocess/sqlite_centralized_multi_machine/Cargo.toml @@ -43,7 +43,6 @@ libafl = { path = "../../../libafl", default-features = false, features = [ "prelude", "gzip", "regex", - "scalability_introspection", "multi_machine", "errors_backtrace", ] } diff --git a/libafl/Cargo.toml b/libafl/Cargo.toml index 45f62ffa65..d5ed573eb1 100644 --- a/libafl/Cargo.toml +++ b/libafl/Cargo.toml @@ -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"] diff --git a/libafl/src/corpus/minimizer.rs b/libafl/src/corpus/minimizer.rs index 56767c6775..42fd357a0f 100644 --- a/libafl/src/corpus/minimizer.rs +++ b/libafl/src/corpus/minimizer.rs @@ -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 MapCorpusMinimizer where for<'a> O: MapObserver + AsIter<'a, Item = T>, C: AsRef, - S: HasMetadata + HasCorpus + HasExecutions + UsesInput::Input>, + S: HasMetadata + HasCorpus + HasExecutions, ::Input: Input, T: Copy + Hash + Eq, TS: TestcaseScore, @@ -75,7 +75,7 @@ where E::Observers: ObserversTuple<::Input, S>, CS: Scheduler<::Input, S> + RemovableScheduler<::Input, S>, - EM: EventFirer, + EM: EventFirer<::Input, S>, Z: HasScheduler<::Input, S, Scheduler = CS>, { // don't delete this else it won't work after restart diff --git a/libafl/src/events/broker_hooks/centralized.rs b/libafl/src/events/broker_hooks/centralized.rs index 831ae29fcb..5fbb437719 100644 --- a/libafl/src/events/broker_hooks/centralized.rs +++ b/libafl/src/events/broker_hooks/centralized.rs @@ -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 { @@ -25,7 +23,7 @@ pub struct CentralizedLlmpHook { impl LlmpHook for CentralizedLlmpHook where - I: Input, + I: DeserializeOwned, SP: ShMemProvider, { fn on_new_message( @@ -75,10 +73,7 @@ impl Debug for CentralizedLlmpHook { } } -impl CentralizedLlmpHook -where - I: Input, -{ +impl CentralizedLlmpHook { /// Create an event broker from a raw broker. pub fn new() -> Result { Ok(Self { diff --git a/libafl/src/events/broker_hooks/centralized_multi_machine.rs b/libafl/src/events/broker_hooks/centralized_multi_machine.rs index 0630f13572..e522c62831 100644 --- a/libafl/src/events/broker_hooks/centralized_multi_machine.rs +++ b/libafl/src/events/broker_hooks/centralized_multi_machine.rs @@ -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 NullLock { /// It is responsible for receiving messages from other neighbours. /// Please check [`crate::events::multi_machine`] for more information. #[derive(Debug)] -pub struct TcpMultiMachineLlmpSenderHook -where - I: Input, -{ +pub struct TcpMultiMachineLlmpSenderHook { /// the actual state of the broker hook shared_state: Arc>>, /// 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 -where - I: Input, -{ +pub struct TcpMultiMachineLlmpReceiverHook { /// the actual state of the broker hook shared_state: Arc>>, /// the tokio runtime used to interact with other machines. Keep it outside to avoid locking it. @@ -96,11 +91,7 @@ where phantom: PhantomData, } -impl TcpMultiMachineLlmpSenderHook -where - A: Clone + Display + ToSocketAddrs + Send + Sync + 'static, - I: Input + Send + Sync + 'static, -{ +impl TcpMultiMachineLlmpSenderHook { /// Should not be created alone. Use [`TcpMultiMachineHooksBuilder`] instead. pub(crate) fn new( shared_state: Arc>>, @@ -117,7 +108,7 @@ where impl TcpMultiMachineLlmpReceiverHook 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 LlmpHook for TcpMultiMachineLlmpSenderHook 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 LlmpHook for TcpMultiMachineLlmpReceiverHook 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( diff --git a/libafl/src/events/broker_hooks/mod.rs b/libafl/src/events/broker_hooks/mod.rs index ee58aa4d36..baac20f950 100644 --- a/libafl/src/events/broker_hooks/mod.rs +++ b/libafl/src/events/broker_hooks/mod.rs @@ -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 { impl LlmpHook for StdLlmpEventHook where - I: Input, - MT: Monitor, + I: DeserializeOwned, SP: ShMemProvider, + MT: Monitor, { fn on_new_message( &mut self, @@ -90,7 +90,6 @@ where impl StdLlmpEventHook where - I: Input, MT: Monitor, { /// Create an event broker from a raw broker. diff --git a/libafl/src/events/centralized.rs b/libafl/src/events/centralized.rs index 409c574bba..f2c4c3656b 100644 --- a/libafl/src/events/centralized.rs +++ b/libafl/src/events/centralized.rs @@ -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 where - EM: UsesState, - EMH: EventManagerHooksTuple, - S: State, SP: ShMemProvider, { inner: EM, @@ -64,14 +64,7 @@ where phantom: PhantomData, } -impl - CentralizedEventManager< - NopEventManager>, - (), - NopState, - NopShMemProvider, - > -{ +impl CentralizedEventManager, NopShMemProvider> { /// Creates a builder for [`CentralizedEventManager`] #[must_use] pub fn builder() -> CentralizedEventManagerBuilder { @@ -113,9 +106,6 @@ impl CentralizedEventManagerBuilder { time_obs: Option>, ) -> Result, Error> where - EM: UsesState, - EMH: EventManagerHooksTuple, - S: State, SP: ShMemProvider, { Ok(CentralizedEventManager { @@ -143,22 +133,10 @@ impl CentralizedEventManagerBuilder { time_obs: Option>, ) -> Result, Error> where - EM: UsesState, - EMH: EventManagerHooksTuple, - 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>, ) -> Result, Error> where - EM: UsesState, - EMH: EventManagerHooksTuple, - 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>, ) -> Result, Error> where - EM: UsesState, - EMH: EventManagerHooksTuple, - 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 UsesState for CentralizedEventManager -where - EM: UsesState, - EMH: EventManagerHooksTuple, - S: State, - SP: ShMemProvider, -{ - type State = EM::State; -} impl AdaptiveSerializer for CentralizedEventManager where - EM: AdaptiveSerializer + UsesState, - EMH: EventManagerHooksTuple, - S: State, + EM: AdaptiveSerializer, SP: ShMemProvider, { fn serialization_time(&self) -> Duration { @@ -264,13 +209,14 @@ where } } -impl EventFirer for CentralizedEventManager +impl EventFirer<::Input, S> + for CentralizedEventManager where - EM: AdaptiveSerializer + EventFirer + HasEventManagerId, - EMH: EventManagerHooksTuple, - S: State + HasCorpus, - S::Corpus: Corpus, + EM: HasEventManagerId + EventFirer<::Input, S>, + EMH: EventManagerHooksTuple<<::Corpus as Corpus>::Input, S>, SP: ShMemProvider, + S: HasCorpus + Stoppable, + <::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<::Input>, + state: &mut S, + mut event: Event<::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(&mut self, observers: &OT) -> Result>, Error> - where - OT: ObserversTuple + 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 EventRestarter for CentralizedEventManager +impl EventRestarter for CentralizedEventManager where - EM: EventRestarter, - EMH: EventManagerHooksTuple, - S: State, SP: ShMemProvider, + EM: EventRestarter, { #[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 CanSerializeObserver for CentralizedEventManager +where + EM: AdaptiveSerializer, + SP: ShMemProvider, + OT: Serialize + MatchNameRef, +{ + fn serialize_observers(&mut self, observers: &OT) -> Result>, Error> { + serialize_observers_adaptive::( + &mut self.inner, + observers, + 4, // twice as much as the normal llmp em's value cuz it does this job twice. + 80, + ) + } +} + +impl ManagerExit for CentralizedEventManager +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 EventProcessor for CentralizedEventManager +impl EventProcessor for CentralizedEventManager where - EM: AdaptiveSerializer + EventProcessor + EventFirer + HasEventManagerId, - EMH: EventManagerHooksTuple, - E: HasObservers + Executor::Input, S, Z>, - E::Observers: - ObserversTuple<::Input, ::State> + Serialize, - for<'a> E::Observers: Deserialize<'a>, - S: State + HasCorpus, - S::Corpus: Corpus, - Self::State: HasExecutions + HasMetadata, + E: HasObservers, + E::Observers: DeserializeOwned, + EM: EventProcessor + HasEventManagerId + EventFirer<::Input, S>, + EMH: EventManagerHooksTuple<::Input, S>, + S: HasCorpus + Stoppable, + ::Input: Input, SP: ShMemProvider, - Z: EvaluatorObservers::Input, S> - + ExecutionProcessor::Input, E::Observers, S>, + Z: ExecutionProcessor::Input, E::Observers, S> + + EvaluatorObservers::Input, S>, { - fn process( - &mut self, - fuzzer: &mut Z, - state: &mut Self::State, - executor: &mut E, - ) -> Result { + fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { if self.is_main { // main node self.receive_from_secondary(fuzzer, state, executor) @@ -400,40 +345,35 @@ where } } -impl EventManager for CentralizedEventManager +impl ProgressReporter for CentralizedEventManager where - E: HasObservers + Executor::Input, S, Z>, - E::Observers: - ObserversTuple<::Input, ::State> + Serialize, - for<'a> E::Observers: Deserialize<'a>, - EM: AdaptiveSerializer + EventManager, - EM::State: HasExecutions + HasMetadata + HasLastReportTime, - EMH: EventManagerHooksTuple, - S: State + HasCorpus, - S::Corpus: Corpus, + EM: EventFirer<::Input, S> + HasEventManagerId, + EMH: EventManagerHooksTuple<<::Corpus as Corpus>::Input, S>, + S: HasExecutions + + HasMetadata + + HasLastReportTime + + Stoppable + + HasCorpus + + MaybeHasClientPerfMonitor, + ::Input: Input, SP: ShMemProvider, - Z: EvaluatorObservers::Input, S> - + ExecutionProcessor::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 ProgressReporter for CentralizedEventManager -where - EM: AdaptiveSerializer + ProgressReporter + HasEventManagerId, - EM::State: HasMetadata + HasExecutions + HasLastReportTime, - EMH: EventManagerHooksTuple, - S: State + HasCorpus, - S::Corpus: Corpus, - SP: ShMemProvider, -{ + fn report_progress(&mut self, state: &mut S) -> Result<(), Error> { + std_report_progress(self, state) + } } impl HasEventManagerId for CentralizedEventManager where - EM: HasEventManagerId + UsesState, - EMH: EventManagerHooksTuple, - S: State + HasCorpus, - S::Corpus: Corpus, + EM: HasEventManagerId, SP: ShMemProvider, { fn mgr_id(&self) -> EventManagerId { @@ -443,10 +383,6 @@ where impl CentralizedEventManager where - EM: UsesState, - EMH: EventManagerHooksTuple, - S: State + HasCorpus, - S::Corpus: Corpus, 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 CentralizedEventManager where - EM: UsesState + EventFirer + AdaptiveSerializer + HasEventManagerId, - EMH: EventManagerHooksTuple, - S: State + Stoppable + HasCorpus, - S::Corpus: Corpus, + EM: HasEventManagerId + EventFirer<::Input, S>, + EMH: EventManagerHooksTuple<::Input, S>, + S: HasCorpus + Stoppable, + ::Input: Input, SP: ShMemProvider, { #[cfg(feature = "llmp_compression")] @@ -510,17 +446,14 @@ where fn receive_from_secondary( &mut self, fuzzer: &mut Z, - state: &mut ::State, + state: &mut S, executor: &mut E, ) -> Result where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: - ObserversTuple<::Input, ::State> + Serialize, - ::State: UsesInput + HasExecutions + HasMetadata, - for<'a> E::Observers: Deserialize<'a>, - Z: EvaluatorObservers::Input, S> - + ExecutionProcessor::Input, E::Observers, S>, + E: HasObservers, + E::Observers: DeserializeOwned, + Z: ExecutionProcessor::Input, E::Observers, S> + + EvaluatorObservers::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<<::State as UsesInput>::Input> = - postcard::from_bytes(event_bytes)?; + let event: Event<::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 ::State, + state: &mut S, client_id: ClientId, - event: Event<<::State as UsesInput>::Input>, + event: Event<::Input>, ) -> Result<(), Error> where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: - ObserversTuple<::Input, ::State> + Serialize, - ::State: UsesInput + HasExecutions + HasMetadata, - for<'a> E::Observers: Deserialize<'a> + Serialize, - Z: EvaluatorObservers::Input, S> - + ExecutionProcessor::Input, E::Observers, S>, + E: HasObservers, + E::Observers: DeserializeOwned, + Z: ExecutionProcessor::Input, E::Observers, S> + + EvaluatorObservers::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(), diff --git a/libafl/src/events/events_hooks/mod.rs b/libafl/src/events/events_hooks/mod.rs index b34b1810f6..e7736212e5 100644 --- a/libafl/src/events/events_hooks/mod.rs +++ b/libafl/src/events/events_hooks/mod.rs @@ -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 -where - S: State, -{ +pub trait EventManagerHook { /// 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, + event: &Event, ) -> Result; /// 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, + _event: &Event, ) -> Result<(), Error> { Ok(()) } @@ -38,16 +35,13 @@ where } /// The tuples contains `broker_hooks` to be executed for `handle_in_client` -pub trait EventManagerHooksTuple -where - S: State, -{ +pub trait EventManagerHooksTuple { /// The hook that runs before `handle_in_client` fn pre_exec_all( &mut self, state: &mut S, client_id: ClientId, - event: &Event, + event: &Event, ) -> Result; /// 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, + event: &Event, ) -> Result<(), Error>; /// The hook that runs after `handle_in_client` fn post_exec_all(&mut self, state: &mut S, client_id: ClientId) -> Result; } -impl EventManagerHooksTuple for () -where - S: State, -{ +impl EventManagerHooksTuple for () { /// The hook that runs before `handle_in_client` fn pre_exec_all( &mut self, _state: &mut S, _client_id: ClientId, - _event: &Event, + _event: &Event, ) -> Result { Ok(true) } @@ -80,7 +71,7 @@ where &mut self, _state: &mut S, _client_id: ClientId, - _event: &Event, + _event: &Event, ) -> Result<(), Error> { Ok(()) } @@ -91,18 +82,17 @@ where } } -impl EventManagerHooksTuple for (Head, Tail) +impl EventManagerHooksTuple for (Head, Tail) where - Head: EventManagerHook, - Tail: EventManagerHooksTuple, - S: State, + Head: EventManagerHook, + Tail: EventManagerHooksTuple, { /// The hook that runs before `handle_in_client` fn pre_exec_all( &mut self, state: &mut S, client_id: ClientId, - event: &Event, + event: &Event, ) -> Result { 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, + event: &Event, ) -> Result<(), Error> { self.0.on_fire(state, client_id, event)?; self.1.on_fire_all(state, client_id, event) diff --git a/libafl/src/events/launcher.rs b/libafl/src/events/launcher.rs index 7dcba580fb..ea66e4aeff 100644 --- a/libafl/src/events/launcher.rs +++ b/libafl/src/events/launcher.rs @@ -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(&mut self) -> Result<(), Error> where - S: State + HasExecutions, + S: DeserializeOwned + HasCorpus + Serialize, + ::Input: DeserializeOwned, CF: FnOnce( Option, LlmpRestartingEventManager<(), S, SP>, @@ -236,8 +237,9 @@ where #[cfg(all(unix, feature = "fork"))] pub fn launch_with_hooks(&mut self, hooks: EMH) -> Result<(), Error> where - S: State + HasExecutions, - EMH: EventManagerHooksTuple + Clone + Copy, + S: DeserializeOwned + HasCorpus + Serialize, + ::Input: DeserializeOwned, + EMH: EventManagerHooksTuple<::Input, S> + Clone + Copy, CF: FnOnce( Option, LlmpRestartingEventManager, @@ -383,8 +385,9 @@ where #[expect(clippy::too_many_lines, clippy::match_wild_err_arm)] pub fn launch_with_hooks(&mut self, hooks: EMH) -> Result<(), Error> where - S: State + HasExecutions, - EMH: EventManagerHooksTuple + Clone + Copy, + S: DeserializeOwned + HasCorpus + Serialize, + ::Input: DeserializeOwned, + EMH: EventManagerHooksTuple<::Input, S> + Clone + Copy, CF: FnOnce( Option, LlmpRestartingEventManager, @@ -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, @@ -633,8 +633,8 @@ where /// Launch a standard Centralized-based fuzzer pub fn launch(&mut self) -> Result<(), Error> where - S: State, - S::Input: Send + Sync + 'static, + S: DeserializeOwned + HasCorpus + Serialize, + ::Input: DeserializeOwned + Input + Send + Sync + 'static, CF: FnOnce( Option, CentralizedEventManager, (), 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, + ::Input: Input + Send + Sync + 'static, CF: FnOnce( Option, CentralizedEventManager, ClientDescription, ) -> Result<(), Error>, - EM: UsesState, EMB: FnOnce(&Self, ClientDescription) -> Result<(Option, EM), Error>, MF: FnOnce( Option, CentralizedEventManager, // No broker_hooks for centralized EM ClientDescription, ) -> Result<(), Error>, - <::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::<<::State as UsesInput>::Input>()? + .build::<::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::::new()?, + CentralizedLlmpHook::<::Input>::new()?, multi_machine_receiver_hook, ); #[cfg(not(feature = "multi_machine"))] - let centralized_hooks = tuple_list!(CentralizedLlmpHook::::new()?); + let centralized_hooks = + tuple_list!(CentralizedLlmpHook::<::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::::new(self.monitor.clone())?); + let llmp_hook = tuple_list!(StdLlmpEventHook::<::Input, MT>::new( + self.monitor.clone() + )?); #[cfg(feature = "multi_machine")] let llmp_hook = tuple_list!( - StdLlmpEventHook::::new(self.monitor.clone())?, + StdLlmpEventHook::<::Input, MT>::new(self.monitor.clone())?, multi_machine_sender_hook, ); diff --git a/libafl/src/events/llmp/mgr.rs b/libafl/src/events/llmp/mgr.rs index d6a6b806cb..b1cad00989 100644 --- a/libafl/src/events/llmp/mgr.rs +++ b/libafl/src/events/llmp/mgr.rs @@ -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 where - S: State, SP: ShMemProvider, { /// We only send 1 testcase for every `throttle` second pub(crate) throttle: Option, - /// 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, NopShMemProvider> { pub struct LlmpEventManagerBuilder { throttle: Option, 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 LlmpEventManagerBuilder { ) -> Result, 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 LlmpEventManagerBuilder { ) -> Result, 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 LlmpEventManagerBuilder { ) -> Result, 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 LlmpEventManagerBuilder { ) -> Result, 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 CanSerializeObserver for LlmpEventManager +where + SP: ShMemProvider, + OT: Serialize + MatchNameRef, +{ + fn serialize_observers(&mut self, observers: &OT) -> Result>, Error> { + serialize_observers_adaptive::(self, observers, 2, 80) } } impl AdaptiveSerializer for LlmpEventManager where SP: ShMemProvider, - S: State, { fn serialization_time(&self) -> Duration { self.serialization_time @@ -309,7 +259,6 @@ where impl core::fmt::Debug for LlmpEventManager 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 Drop for LlmpEventManager 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 LlmpEventManager 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 LlmpEventManager where - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, - S::Corpus: Corpus, SP: ShMemProvider, { // Handle arriving events in the client @@ -400,15 +344,16 @@ where executor: &mut E, state: &mut S, client_id: ClientId, - event: Event, + event: Event<::Input>, ) -> Result<(), Error> where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple + Serialize, - for<'a> E::Observers: Deserialize<'a>, + S: HasCorpus + HasImported + Stoppable, + EMH: EventManagerHooksTuple<::Input, S>, + ::Input: Input, + E: HasObservers, + E::Observers: DeserializeOwned, Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S> - + Evaluator::Input, S>, + + EvaluatorObservers::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 LlmpEventManager { +impl LlmpEventManager { /// 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 LlmpEventManager { } } -impl UsesState for LlmpEventManager +impl EventFirer for LlmpEventManager where - S: State, - SP: ShMemProvider, -{ - type State = S; -} - -impl EventFirer for LlmpEventManager -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<::Input>, - ) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S, event: Event) -> 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(&mut self, observers: &OT) -> Result>, Error> - where - OT: ObserversTuple + 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 EventRestarter for LlmpEventManager +impl EventRestarter for LlmpEventManager +where + SP: ShMemProvider, + S: HasCurrentStageId, +{ + fn on_restart(&mut self, state: &mut S) -> Result<(), Error> { + std_on_restart(self, state) + } +} + +impl ManagerExit for LlmpEventManager 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 EventProcessor for LlmpEventManager +impl EventProcessor for LlmpEventManager where - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, - S::Corpus: Corpus, + E: HasObservers, + E::Observers: DeserializeOwned, + S: HasCorpus + HasImported + Stoppable, + EMH: EventManagerHooksTuple<::Input, S>, + ::Input: DeserializeOwned + Input, SP: ShMemProvider, - E: HasObservers + Executor::Input, S, Z>, - E::Observers: ObserversTuple + Serialize, - for<'a> E::Observers: Deserialize<'a>, Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S> - + Evaluator::Input, S>, + + EvaluatorObservers::Input, S>, { - fn process( - &mut self, - fuzzer: &mut Z, - state: &mut Self::State, - executor: &mut E, - ) -> Result { + fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { // 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 = postcard::from_bytes(event_bytes)?; + let event: Event<::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 EventManager for LlmpEventManager +impl ProgressReporter for LlmpEventManager where - E: HasObservers + Executor::Input, S, Z>, - E::Observers: ObserversTuple + Serialize, - for<'a> E::Observers: Deserialize<'a>, - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported + HasCorpus, - S::Corpus: Corpus, + S: HasExecutions + HasLastReportTime + HasMetadata + HasCorpus + MaybeHasClientPerfMonitor, SP: ShMemProvider, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S> - + Evaluator::Input, S>, + ::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 ProgressReporter for LlmpEventManager -where - S: State + HasExecutions + HasMetadata + HasLastReportTime, - SP: ShMemProvider, -{ + fn report_progress(&mut self, state: &mut S) -> Result<(), Error> { + std_report_progress(self, state) + } } impl HasEventManagerId for LlmpEventManager where - S: State, SP: ShMemProvider, { /// Gets the id assigned to this staterestorer. diff --git a/libafl/src/events/llmp/mod.rs b/libafl/src/events/llmp/mod.rs index c45542101f..07be48a666 100644 --- a/libafl/src/events/llmp/mod.rs +++ b/libafl/src/events/llmp/mod.rs @@ -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 +pub struct LlmpEventConverter where - S: UsesInput, SP: ShMemProvider, - IC: InputConverter, - ICB: InputConverter, - DI: Input, { throttle: Option, llmp: LlmpClient, @@ -104,7 +99,6 @@ where impl LlmpEventConverter< - NopInput, NopInputConverter, NopInputConverter, NopState, @@ -140,18 +134,14 @@ impl LlmpEventConverterBuilder { } /// Create a event converter from a raw llmp client - pub fn build_from_client( + pub fn build_from_client( self, llmp: LlmpClient, converter: Option, converter_back: Option, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, - S: UsesInput, - IC: InputConverter, - ICB: InputConverter, - 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( + pub fn build_on_port( self, shmem_provider: SP, port: u16, converter: Option, converter_back: Option, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, - S: UsesInput, - IC: InputConverter, - ICB: InputConverter, - 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( + pub fn build_existing_client_from_env( self, shmem_provider: SP, env_name: &str, converter: Option, converter_back: Option, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, - S: UsesInput, - IC: InputConverter, - ICB: InputConverter, - DI: Input, { let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?; Ok(LlmpEventConverter { @@ -224,13 +206,11 @@ impl LlmpEventConverterBuilder { } } -impl core::fmt::Debug for LlmpEventConverter +impl Debug for LlmpEventConverter where SP: ShMemProvider, - S: UsesInput, - IC: InputConverter, - ICB: InputConverter, - 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 LlmpEventConverter +impl LlmpEventConverter where - S: UsesInput + HasExecutions + HasMetadata + Stoppable + HasCorpus, + S: HasCorpus, SP: ShMemProvider, - IC: InputConverter, - ICB: InputConverter, - DI: Input, { // TODO other new_* routines @@ -278,7 +255,7 @@ where } // Handle arriving events in the client - fn handle_in_client( + fn handle_in_client( &mut self, fuzzer: &mut Z, executor: &mut E, @@ -288,12 +265,8 @@ where event: Event, ) -> Result<(), Error> where - E: Executor::Input, S, Z> + HasObservers, - EM: UsesState + EventFirer, - S::Corpus: Corpus, - for<'a> E::Observers: Deserialize<'a>, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + ICB: InputConverter::Input, From = DI>, + Z: EvaluatorObservers::Input, S>, { match event { Event::NewTestcase { @@ -327,7 +300,7 @@ where } /// Handle arriving events in the client - pub fn process( + pub fn process( &mut self, fuzzer: &mut Z, state: &mut S, @@ -335,12 +308,9 @@ where manager: &mut EM, ) -> Result where - E: Executor::Input, S, Z> + HasObservers, - EM: UsesState + EventFirer, - S::Corpus: Corpus, - for<'a> E::Observers: Deserialize<'a>, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + ICB: InputConverter::Input, From = DI>, + DI: DeserializeOwned + Input, + Z: EvaluatorObservers::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 UsesState for LlmpEventConverter +impl EventFirer<::Input, S> + for LlmpEventConverter where - S: State, + IC: InputConverter::Input>, + S: HasCorpus, SP: ShMemProvider, - IC: InputConverter, - ICB: InputConverter, - DI: Input, -{ - type State = S; -} - -impl EventFirer for LlmpEventConverter -where - S: State, - SP: ShMemProvider, - IC: InputConverter, - ICB: InputConverter, - 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<::Input>, + _state: &mut S, + event: Event<::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<::Input>, + _state: &mut S, + event: Event<::Input>, ) -> Result<(), Error> { if self.converter.is_none() { return Ok(()); diff --git a/libafl/src/events/llmp/restarting.rs b/libafl/src/events/llmp/restarting.rs index 5a4c0a33e0..1bc1fcd8cb 100644 --- a/libafl/src/events/llmp/restarting.rs +++ b/libafl/src/events/llmp/restarting.rs @@ -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 where - S: State, SP: ShMemProvider, - //CE: CustomEvent, { /// The embedded LLMP event manager llmp_mgr: LlmpEventManager, @@ -67,7 +71,6 @@ where impl AdaptiveSerializer for LlmpRestartingEventManager where SP: ShMemProvider, - S: State, { fn serialization_time(&self) -> Duration { self.llmp_mgr.serialization_time() @@ -100,67 +103,68 @@ where } } -impl UsesState for LlmpRestartingEventManager +impl ProgressReporter for LlmpRestartingEventManager where - S: State, + S: HasExecutions + + HasLastReportTime + + HasMetadata + + HasCorpus + + Serialize + + MaybeHasClientPerfMonitor, SP: ShMemProvider, + ::Input: Serialize, { - type State = S; -} - -impl ProgressReporter for LlmpRestartingEventManager -where - S: State + HasExecutions + HasMetadata + HasLastReportTime, - SP: ShMemProvider, -{ -} - -impl EventFirer for LlmpRestartingEventManager -where - SP: ShMemProvider, - S: State, - //CE: CustomEvent, -{ - 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<::Input>, - ) -> Result<(), Error> { + fn report_progress(&mut self, state: &mut S) -> Result<(), Error> { + std_report_progress(self, state) + } +} + +impl EventFirer for LlmpRestartingEventManager +where + I: Serialize, + S: HasCorpus + Serialize, + SP: ShMemProvider, +{ + fn should_send(&self) -> bool { + as EventFirer>::should_send(&self.llmp_mgr) + } + + fn fire(&mut self, state: &mut S, event: Event) -> 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(&mut self, observers: &OT) -> Result>, Error> - where - OT: ObserversTuple + Serialize, - { - self.llmp_mgr.serialize_observers(observers) - } - fn configuration(&self) -> EventConfig { - self.llmp_mgr.configuration() + as EventFirer>::configuration(&self.llmp_mgr) } } -impl EventRestarter for LlmpRestartingEventManager +#[cfg(feature = "std")] +impl CanSerializeObserver for LlmpRestartingEventManager where - S: State + HasExecutions, SP: ShMemProvider, - //CE: CustomEvent, + 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>, Error> { + serialize_observers_adaptive::(self, observers, 2, 80) } +} +impl EventRestarter for LlmpRestartingEventManager +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 ManagerExit for LlmpRestartingEventManager +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 EventProcessor for LlmpRestartingEventManager +impl EventProcessor for LlmpRestartingEventManager where - E: HasObservers + Executor, ::Input, S, Z>, - E::Observers: ObserversTuple + Serialize, - for<'a> E::Observers: Deserialize<'a>, - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, - S::Corpus: Corpus, + EMH: EventManagerHooksTuple<::Input, S>, + E: HasObservers, + E::Observers: DeserializeOwned, + S: HasCorpus + HasImported + Stoppable + Serialize, + ::Input: DeserializeOwned + Input, + S::Corpus: Serialize, SP: ShMemProvider, Z: ExecutionProcessor< LlmpEventManager, ::Input, E::Observers, S, - > + EvaluatorObservers, ::Input, S> - + Evaluator, ::Input, S>, + > + EvaluatorObservers, ::Input, S>, { fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { let res = self.llmp_mgr.process(fuzzer, state, executor)?; @@ -217,28 +232,8 @@ where } } -impl EventManager for LlmpRestartingEventManager -where - E: HasObservers + Executor, ::Input, S, Z>, - E::Observers: ObserversTuple + Serialize, - for<'a> E::Observers: Deserialize<'a>, - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported + HasCorpus, - S::Corpus: Corpus, - SP: ShMemProvider, - Z: ExecutionProcessor< - LlmpEventManager, - ::Input, - E::Observers, - S, - > + EvaluatorObservers, ::Input, S> - + Evaluator, ::Input, S>, -{ -} - impl HasEventManagerId for LlmpRestartingEventManager 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 LlmpRestartingEventManager where - S: State, SP: ShMemProvider, - //CE: CustomEvent, + S: Serialize, { /// Create a new runner, the executed child doing the actual fuzzing. pub fn new(llmp_mgr: LlmpEventManager, staterestorer: StateRestorer) -> Self { @@ -334,7 +328,8 @@ pub fn setup_restarting_mgr_std( > where MT: Monitor + Clone, - S: State, + S: HasCorpus + Serialize + DeserializeOwned, + ::Input: DeserializeOwned, { RestartingMgr::builder() .shmem_provider(StdShMemProvider::new()?) @@ -366,7 +361,8 @@ pub fn setup_restarting_mgr_std_adaptive( > where MT: Monitor + Clone, - S: State, + S: HasCorpus + Serialize + DeserializeOwned, + ::Input: DeserializeOwned, { RestartingMgr::builder() .shmem_provider(StdShMemProvider::new()?) @@ -389,9 +385,6 @@ pub struct RestartingMgr { /// 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 { #[expect(clippy::type_complexity, clippy::too_many_lines)] impl RestartingMgr where - EMH: EventManagerHooksTuple + Copy + Clone, + EMH: EventManagerHooksTuple<::Input, S> + Copy + Clone, SP: ShMemProvider, - S: State, + S: HasCorpus + Serialize + DeserializeOwned, + ::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::::new( - self.monitor.take().unwrap(), - )?; + let llmp_hook = + StdLlmpEventHook::<::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 = 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(), diff --git a/libafl/src/events/mod.rs b/libafl/src/events/mod.rs index 55cf440461..f7cbca659c 100644 --- a/libafl/src/events/mod.rs +++ b/libafl/src/events/mod.rs @@ -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 -where - I: Input, -{ +pub enum Event { // 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 Event -where - I: Input, -{ +impl Event { /// 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 { /// 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<::Input>, - ) -> Result<(), Error>; + fn fire(&mut self, state: &mut S, event: Event) -> 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(&mut self, observers: &OT) -> Result>, Error> - where - OT: ObserversTuple<::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( + manager: &mut EM, + observers: &OT, + time_factor: u32, + percentage_threshold: usize, +) -> Result>, 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( + reporter: &mut PR, + state: &mut S, + monitor_timeout: Duration, +) -> Result<(), Error> +where + PR: ProgressReporter, + 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(reporter: &mut EM, state: &mut S) -> Result<(), Error> +where + EM: EventFirer<::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 { + /// 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 { + /// 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( + restarter: &mut (impl EventRestarter + 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 { + /// Do serialize the observer + fn serialize_observers(&mut self, observers: &OT) -> Result>, 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 { + /// 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; + + /// 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 EventFirer for NopEventManager { + fn should_send(&self) -> bool { + true + } + + fn fire(&mut self, _state: &mut S, _event: Event) -> 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 EventRestarter 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: 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; - - /// 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: - EventFirer + EventProcessor + 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 { - phantom: PhantomData, -} - -impl NopEventManager { - /// Creates a new [`NopEventManager`] - #[must_use] - pub fn new() -> Self { - NopEventManager { - phantom: PhantomData, - } - } -} - -impl Default for NopEventManager { - fn default() -> Self { - Self::new() - } -} - -impl UsesState for NopEventManager -where - S: State, -{ - type State = S; -} - -impl EventFirer for NopEventManager -where - S: State, -{ - fn should_send(&self) -> bool { - true - } - - fn fire( - &mut self, - _state: &mut Self::State, - _event: Event<::Input>, - ) -> Result<(), Error> { - Ok(()) - } -} - -impl EventRestarter for NopEventManager where S: State {} - -impl EventProcessor for NopEventManager -where - S: State + HasExecutions, -{ +impl EventProcessor for NopEventManager { fn process( &mut self, _fuzzer: &mut Z, - _state: &mut Self::State, + _state: &mut S, _executor: &mut E, ) -> Result { Ok(0) @@ -648,23 +663,36 @@ where } } -impl EventManager for NopEventManager where - S: State + HasExecutions + HasLastReportTime + HasMetadata +impl CanSerializeObserver for NopEventManager +where + OT: Serialize, { + fn serialize_observers(&mut self, observers: &OT) -> Result>, Error> { + Ok(Some(postcard::to_allocvec(observers)?)) + } } -impl ProgressReporter for NopEventManager where - S: State + HasExecutions + HasLastReportTime + HasMetadata -{ +impl ProgressReporter 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 HasEventManagerId for NopEventManager { +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 { @@ -673,7 +701,7 @@ pub struct MonitorTypedEventManager { } impl MonitorTypedEventManager { - /// 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 MonitorTypedEventManager { } } -impl UsesState for MonitorTypedEventManager +impl CanSerializeObserver for MonitorTypedEventManager where - EM: UsesState, + OT: Serialize, { - type State = EM::State; + fn serialize_observers(&mut self, observers: &OT) -> Result>, Error> { + Ok(Some(postcard::to_allocvec(observers)?)) + } } -impl EventFirer for MonitorTypedEventManager +impl EventFirer for MonitorTypedEventManager where - EM: EventFirer, + EM: EventFirer, { fn should_send(&self) -> bool { true } #[inline] - fn fire( - &mut self, - state: &mut Self::State, - event: Event<::Input>, - ) -> Result<(), Error> { + fn fire(&mut self, state: &mut S, event: Event) -> 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(&mut self, observers: &OT) -> Result>, Error> - where - OT: ObserversTuple<::Input, Self::State> + Serialize, - { - self.inner.serialize_observers(observers) - } - #[inline] fn configuration(&self) -> EventConfig { self.inner.configuration() } } -impl EventRestarter for MonitorTypedEventManager +impl EventRestarter for MonitorTypedEventManager where - EM: EventRestarter, + EM: EventRestarter, { #[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 ManagerExit for MonitorTypedEventManager +where + EM: ManagerExit, +{ #[inline] fn send_exiting(&mut self) -> Result<(), Error> { self.inner.send_exiting() @@ -751,17 +774,12 @@ where } } -impl EventProcessor for MonitorTypedEventManager +impl EventProcessor for MonitorTypedEventManager where - EM: EventProcessor, + EM: EventProcessor, { #[inline] - fn process( - &mut self, - fuzzer: &mut Z, - state: &mut Self::State, - executor: &mut E, - ) -> Result { + fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { self.inner.process(fuzzer, state, executor) } @@ -770,30 +788,21 @@ where } } -impl EventManager for MonitorTypedEventManager +impl ProgressReporter for MonitorTypedEventManager where - EM: EventManager, - Self::State: HasLastReportTime + HasExecutions + HasMetadata, -{ -} - -impl ProgressReporter for MonitorTypedEventManager -where - Self: UsesState, - EM: ProgressReporter, - Self::State: HasLastReportTime + HasExecutions + HasMetadata, + EM: ProgressReporter, { #[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>; - - /// 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( - &mut self, - observers: &OT, - time_factor: u32, - percentage_threshold: usize, - ) -> Result>, Error> - where - OT: ObserversTuple + 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)] diff --git a/libafl/src/events/multi_machine.rs b/libafl/src/events/multi_machine.rs index 51f8d7a145..314bea15cb 100644 --- a/libafl/src/events/multi_machine.rs +++ b/libafl/src/events/multi_machine.rs @@ -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 Send for MultiMachineMsg<'_, I> {} unsafe impl 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 { /// 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 -where - I: Input, -{ +pub struct TcpMultiMachineHooks { /// The sender hooks pub sender: TcpMultiMachineLlmpSenderHook, /// The hooks diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index 8a95b5f89e..44ad11ccd7 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -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 -where - S: UsesInput + Stoppable, -{ +pub struct SimpleEventManager { /// The monitor monitor: MT, /// The events that happened since the last `handle_in_broker` - events: Vec>, + events: Vec>, phantom: PhantomData, } -impl Debug for SimpleEventManager +impl Debug for SimpleEventManager 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 UsesState for SimpleEventManager -where - S: State, -{ - type State = S; -} - -impl EventFirer for SimpleEventManager +impl EventFirer for SimpleEventManager 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<::Input>, - ) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S, event: Event) -> 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 EventRestarter for SimpleEventManager -where - MT: Monitor, - S: State, -{ +impl ManagerExit for SimpleEventManager { + fn send_exiting(&mut self) -> Result<(), Error> { + Ok(()) + } + + fn await_restart_safe(&mut self) {} } -impl EventProcessor for SimpleEventManager +impl EventRestarter for SimpleEventManager where + S: HasCurrentStageId, +{ + fn on_restart(&mut self, state: &mut S) -> Result<(), Error> { + std_on_restart(self, state) + } +} + +impl EventProcessor for SimpleEventManager +where + I: Debug, MT: Monitor, - S: State, + S: Stoppable, { fn process( &mut self, @@ -130,34 +128,51 @@ where } } -impl EventManager for SimpleEventManager +impl CanSerializeObserver for SimpleEventManager where - MT: Monitor, - S: State + HasExecutions + HasLastReportTime + HasMetadata, + OT: Serialize, { + fn serialize_observers(&mut self, observers: &OT) -> Result>, Error> { + Ok(Some(postcard::to_allocvec(observers)?)) + } } -impl ProgressReporter for SimpleEventManager +impl ProgressReporter for SimpleEventManager where + I: Debug, MT: Monitor, - S: State + HasExecutions + HasMetadata + HasLastReportTime, + S: HasMetadata + + HasExecutions + + HasLastReportTime + + Stoppable + + HasCorpus + + MaybeHasClientPerfMonitor, + S::Corpus: Corpus, { + 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 HasEventManagerId for SimpleEventManager -where - MT: Monitor, - S: UsesInput + Stoppable, -{ +impl HasEventManagerId for SimpleEventManager { fn mgr_id(&self) -> EventManagerId { EventManagerId(0) } } #[cfg(feature = "std")] -impl SimpleEventManager +impl SimpleEventManager where - S: UsesInput + Stoppable, + I: Debug, + S: Stoppable, { /// Creates a [`SimpleEventManager`] that just prints to `stdout`. #[must_use] @@ -166,10 +181,11 @@ where } } -impl SimpleEventManager +impl SimpleEventManager 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, - ) -> Result { + fn handle_in_broker(monitor: &mut MT, event: &Event) -> Result { 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) -> Result<(), Error> { + fn handle_in_client(&mut self, state: &mut S, event: &Event) -> 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 +pub struct SimpleRestartingEventManager where - S: UsesInput + Stoppable, - SP: ShMemProvider, //CE: CustomEvent, + SP: ShMemProvider, { /// The actual simple event mgr - simple_event_mgr: SimpleEventManager, + inner: SimpleEventManager, /// [`StateRestorer`] for restarts staterestorer: StateRestorer, } #[cfg(feature = "std")] -impl UsesState for SimpleRestartingEventManager -where - S: State, - SP: ShMemProvider, -{ - type State = S; -} - -#[cfg(feature = "std")] -impl EventFirer for SimpleRestartingEventManager +impl EventFirer for SimpleRestartingEventManager 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<::Input>, - ) -> Result<(), Error> { - self.simple_event_mgr.fire(_state, event) + fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { + self.inner.fire(_state, event) } } #[cfg(feature = "std")] -impl EventRestarter for SimpleRestartingEventManager +impl EventRestarter for SimpleRestartingEventManager 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 EventProcessor for SimpleRestartingEventManager +impl CanSerializeObserver for SimpleRestartingEventManager +where + SP: ShMemProvider, + OT: Serialize, +{ + fn serialize_observers(&mut self, observers: &OT) -> Result>, Error> { + Ok(Some(postcard::to_allocvec(observers)?)) + } +} + +#[cfg(feature = "std")] +impl ManagerExit for SimpleRestartingEventManager where - MT: Monitor, - S: State + HasExecutions, SP: ShMemProvider, { - fn process( - &mut self, - fuzzer: &mut Z, - state: &mut Self::State, - executor: &mut E, - ) -> Result { - 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 EventProcessor for SimpleRestartingEventManager +where + I: Debug, + MT: Monitor, + SP: ShMemProvider, + S: Stoppable, +{ + fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { + self.inner.process(fuzzer, state, executor) + } + fn on_shutdown(&mut self) -> Result<(), Error> { self.send_exiting() } } #[cfg(feature = "std")] -impl EventManager for SimpleRestartingEventManager +impl ProgressReporter for SimpleRestartingEventManager where + I: Debug, MT: Monitor, - S: State + HasExecutions + HasMetadata + HasLastReportTime + Serialize, SP: ShMemProvider, + S: HasExecutions + + HasMetadata + + HasLastReportTime + + Stoppable + + HasCorpus + + MaybeHasClientPerfMonitor, + S::Corpus: Corpus, { -} + 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 ProgressReporter for SimpleRestartingEventManager -where - MT: Monitor, - S: State + HasExecutions + HasMetadata + HasLastReportTime, - SP: ShMemProvider, -{ -} - -#[cfg(feature = "std")] -impl HasEventManagerId for SimpleRestartingEventManager -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 SimpleRestartingEventManager +impl HasEventManagerId for SimpleRestartingEventManager where - S: UsesInput + Stoppable, SP: ShMemProvider, - MT: Monitor, //TODO CE: CustomEvent, +{ + fn mgr_id(&self) -> EventManagerId { + self.inner.mgr_id() + } +} + +#[cfg(feature = "std")] +impl SimpleRestartingEventManager +where + I: Debug, + MT: Monitor, + S: Stoppable, + SP: ShMemProvider, { /// Creates a new [`SimpleEventManager`]. fn launched(monitor: MT, staterestorer: StateRestorer) -> 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, Self), Error> where diff --git a/libafl/src/events/tcp.rs b/libafl/src/events/tcp.rs index a553b3a390..69e16ccc72 100644 --- a/libafl/src/events/tcp.rs +++ b/libafl/src/events/tcp.rs @@ -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 -where - EMH: EventManagerHooksTuple, - S: State, -{ +/// An `EventManager` that forwards all events to other attached via tcp. +pub struct TcpEventManager { /// We send message every `throttle` second throttle: Option, /// When we sent the last message @@ -427,10 +428,7 @@ where phantom: PhantomData, } -impl TcpEventManager<(), S> -where - S: State, -{ +impl TcpEventManager<(), S> { /// Create a builder for [`TcpEventManager`] #[must_use] pub fn builder() -> TcpEventManagerBuilder<(), S> { @@ -474,11 +472,7 @@ impl TcpEventManagerBuilder<(), S> { } } -impl TcpEventManagerBuilder -where - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata, -{ +impl TcpEventManagerBuilder { /// Set the throttle #[must_use] pub fn throttle(mut self, throttle: Duration) -> Self { @@ -546,11 +540,7 @@ where } } -impl core::fmt::Debug for TcpEventManager -where - EMH: EventManagerHooksTuple, - S: State, -{ +impl core::fmt::Debug for TcpEventManager { 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 Drop for TcpEventManager -where - EMH: EventManagerHooksTuple, - S: State, -{ +impl Drop for TcpEventManager { /// 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 TcpEventManager where - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, - S::Corpus: Corpus, + EMH: EventManagerHooksTuple<::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, + event: Event<::Input>, ) -> Result<(), Error> where E: Executor::Input, S, Z> + HasObservers, - E::Observers: Serialize + ObserversTuple, + E::Observers: Serialize + ObserversTuple<::Input, S>, for<'a> E::Observers: Deserialize<'a>, Z: ExecutionProcessor::Input, E::Observers, S> + EvaluatorObservers::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 TcpEventManager -where - EMH: EventManagerHooksTuple, - S: State, -{ +impl TcpEventManager { /// 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 UsesState for TcpEventManager +impl EventFirer<::Input, S> for TcpEventManager where - EMH: EventManagerHooksTuple, - S: State, -{ - type State = S; -} - -impl EventFirer for TcpEventManager -where - EMH: EventManagerHooksTuple, - S: State, + EMH: EventManagerHooksTuple<::Input, S>, + S: HasCorpus, + ::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<::Input>, + _state: &mut S, + event: Event<::Input>, ) -> Result<(), Error> { let serialized = postcard::to_allocvec(&event)?; @@ -713,36 +679,27 @@ where } } -impl EventRestarter for TcpEventManager +impl EventRestarter for TcpEventManager where - EMH: EventManagerHooksTuple, - 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 EventProcessor for TcpEventManager +impl EventProcessor for TcpEventManager where E: HasObservers + Executor::Input, S, Z>, - E::Observers: Serialize + ObserversTuple, + E::Observers: Serialize + ObserversTuple<::Input, S>, for<'a> E::Observers: Deserialize<'a>, - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, - S::Corpus: Corpus, + EMH: EventManagerHooksTuple<::Input, S>, + S: HasExecutions + HasMetadata + HasImported + HasCorpus + Stoppable, + ::Input: DeserializeOwned, Z: ExecutionProcessor::Input, E::Observers, S> + EvaluatorObservers::Input, S>, { - fn process( - &mut self, - fuzzer: &mut Z, - state: &mut Self::State, - executor: &mut E, - ) -> Result { + fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { // 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 EventManager for TcpEventManager -where - E: HasObservers + Executor::Input, S, Z>, - E::Observers: Serialize + ObserversTuple, - for<'a> E::Observers: Deserialize<'a>, - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported + HasCorpus, - S::Corpus: Corpus, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, -{ +impl ManagerExit for TcpEventManager { + /// 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 ProgressReporter for TcpEventManager +impl ProgressReporter for TcpEventManager where - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasLastReportTime, + EMH: EventManagerHooksTuple<::Input, S>, + ::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 HasEventManagerId for TcpEventManager -where - EMH: EventManagerHooksTuple, - S: State, -{ +impl HasEventManagerId for TcpEventManager { /// 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 where - EMH: EventManagerHooksTuple, - S: State, - SP: ShMemProvider + 'static, - //CE: CustomEvent, + SP: ShMemProvider, { /// The embedded TCP event manager tcp_mgr: TcpEventManager, @@ -849,29 +813,33 @@ where save_state: bool, } -impl UsesState for TcpRestartingEventManager +impl ProgressReporter for TcpRestartingEventManager where - EMH: EventManagerHooksTuple, - S: State, - SP: ShMemProvider + 'static, -{ - type State = S; -} - -impl ProgressReporter for TcpRestartingEventManager -where - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasLastReportTime, + EMH: EventManagerHooksTuple<::Input, S>, + S: HasMetadata + HasExecutions + HasLastReportTime + HasCorpus + MaybeHasClientPerfMonitor, + ::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 EventFirer for TcpRestartingEventManager +impl EventFirer<::Input, S> + for TcpRestartingEventManager where - EMH: EventManagerHooksTuple, + EMH: EventManagerHooksTuple<::Input, S>, + S: HasCorpus, + ::Input: Serialize, SP: ShMemProvider, - S: State, - //CE: CustomEvent, { 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<::Input>, + state: &mut S, + event: Event<::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 EventRestarter for TcpRestartingEventManager +impl ManagerExit for TcpRestartingEventManager where - EMH: EventManagerHooksTuple, - S: State + HasExecutions, SP: ShMemProvider, - //CE: CustomEvent, { /// 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 EventRestarter for TcpRestartingEventManager +where + EMH: EventManagerHooksTuple<::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 EventProcessor for TcpRestartingEventManager +impl EventProcessor for TcpRestartingEventManager where E: HasObservers + Executor, ::Input, S, Z>, for<'a> E::Observers: Deserialize<'a>, - E::Observers: ObserversTuple + Serialize, - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, - S::Corpus: Corpus, - SP: ShMemProvider + 'static, + E::Observers: ObserversTuple<::Input, S> + Serialize, + EMH: EventManagerHooksTuple<::Input, S>, + S: HasExecutions + HasMetadata + HasImported + HasCorpus + Stoppable, + ::Input: DeserializeOwned, + SP: ShMemProvider, Z: ExecutionProcessor, ::Input, E::Observers, S> + EvaluatorObservers, ::Input, S>, { @@ -950,25 +922,9 @@ where } } -impl EventManager for TcpRestartingEventManager -where - E: HasObservers + Executor, ::Input, S, Z>, - E::Observers: ObserversTuple + Serialize, - for<'a> E::Observers: Deserialize<'a>, - EMH: EventManagerHooksTuple, - S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported + HasCorpus, - S::Corpus: Corpus, - SP: ShMemProvider + 'static, - Z: ExecutionProcessor, ::Input, E::Observers, S> - + EvaluatorObservers, ::Input, S>, -{ -} - impl HasEventManagerId for TcpRestartingEventManager where - EMH: EventManagerHooksTuple, - 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 TcpRestartingEventManager where - EMH: EventManagerHooksTuple, - S: State, - SP: ShMemProvider + 'static, + EMH: EventManagerHooksTuple<::Input, S>, + S: HasCorpus, + SP: ShMemProvider, //CE: CustomEvent, { /// Create a new runner, the executed child doing the actual fuzzing. @@ -1053,8 +1009,8 @@ pub fn setup_restarting_mgr_tcp( > where MT: Monitor + Clone, - S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, - S::Corpus: Corpus, + S: HasExecutions + HasMetadata + HasImported + HasCorpus + DeserializeOwned + Stoppable, + ::Input: Input, { TcpRestartingMgr::builder() .shmem_provider(StdShMemProvider::new()?) @@ -1074,10 +1030,9 @@ where #[derive(TypedBuilder, Debug)] pub struct TcpRestartingMgr where - S: UsesInput + DeserializeOwned, + S: DeserializeOwned, SP: ShMemProvider + 'static, MT: Monitor, - //CE: CustomEvent, { /// 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 TcpRestartingMgr where - EMH: EventManagerHooksTuple + Copy + Clone, + EMH: EventManagerHooksTuple<::Input, S> + Copy + Clone, SP: ShMemProvider, - S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, - S::Corpus: Corpus, + S: HasExecutions + HasMetadata + HasImported + HasCorpus + DeserializeOwned + Stoppable, + ::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, _remote_broker_addr| { + let broker_things = |mut broker: TcpEventBroker<::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::::with_listener( - listener, - self.monitor.take().unwrap(), - ); + let event_broker = + TcpEventBroker::<::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::::new( + let event_broker = TcpEventBroker::<::Input, MT>::new( format!("127.0.0.1:{}", self.broker_port), self.monitor.take().unwrap(), )?; diff --git a/libafl/src/executors/command.rs b/libafl/src/executors/command.rs index 968b717926..e1bc56808d 100644 --- a/libafl/src/executors/command.rs +++ b/libafl/src/executors/command.rs @@ -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() -> impl Executor /// where -/// EM: UsesState, -/// EM::State: UsesInput + HasExecutions, /// S: HasCorpus + HasExecutions, -/// S::Corpus: Corpus, +/// S::Corpus: Corpus /// { /// MyExecutor.into_executor(()) /// } @@ -877,7 +875,7 @@ mod tests { #[test] #[cfg_attr(miri, ignore)] fn test_builder() { - let mut mgr: SimpleEventManager<_, NopState> = + let mut mgr: SimpleEventManager> = SimpleEventManager::new(SimpleMonitor::new(|status| { log::info!("{status}"); })); diff --git a/libafl/src/executors/hooks/inprocess.rs b/libafl/src/executors/hooks/inprocess.rs index 18d9da8735..06cbf45aae 100644 --- a/libafl/src/executors/hooks/inprocess.rs +++ b/libafl/src/executors/hooks/inprocess.rs @@ -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 InProcessHooks { where E: Executor + HasObservers + HasInProcessHooks, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, S::Solutions: Corpus, @@ -266,10 +265,10 @@ impl InProcessHooks { where E: Executor + HasObservers + HasInProcessHooks, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, S::Solutions: Corpus, Z: HasObjective, { @@ -329,9 +328,9 @@ impl InProcessHooks { pub fn new(exec_tmout: Duration) -> Result where E: Executor + HasObservers + HasInProcessHooks, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus, Z: HasObjective, { #[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. diff --git a/libafl/src/executors/hooks/unix.rs b/libafl/src/executors/hooks/unix.rs index feb15caa0d..06dc3ad986 100644 --- a/libafl/src/executors/hooks/unix.rs +++ b/libafl/src/executors/hooks/unix.rs @@ -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 + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, S::Solutions: Corpus, Z: HasObjective, I: Input + Clone, @@ -131,9 +131,9 @@ pub mod unix_signal_handler { ) where E: Executor + HasInProcessHooks + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, Z: HasObjective, I: Input + Clone, S::Solutions: Corpus, @@ -188,9 +188,9 @@ pub mod unix_signal_handler { ) where E: Executor + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, S::Solutions: Corpus, diff --git a/libafl/src/executors/hooks/windows.rs b/libafl/src/executors/hooks/windows.rs index 1e6bbc4fe1..c5d8c60275 100644 --- a/libafl/src/executors/hooks/windows.rs +++ b/libafl/src/executors/hooks/windows.rs @@ -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 + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, S::Solutions: Corpus, Z: HasObjective, { @@ -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 + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, S::Solutions: Corpus, Z: HasObjective, { @@ -249,10 +249,10 @@ pub mod windows_exception_handler { ) where E: Executor + HasInProcessHooks + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, Z: HasObjective, S::Solutions: Corpus, { @@ -319,10 +319,10 @@ pub mod windows_exception_handler { ) where E: Executor + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, Z: HasObjective, S::Solutions: Corpus, { diff --git a/libafl/src/executors/inprocess/inner.rs b/libafl/src/executors/inprocess/inner.rs index 6656f5d44f..deee22d49a 100644 --- a/libafl/src/executors/inprocess/inner.rs +++ b/libafl/src/executors/inprocess/inner.rs @@ -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 + HasObservers + HasInProcessHooks, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput, + S: HasCurrentTestcase + HasCorpus + HasSolutions, S::Solutions: Corpus, Z: HasObjective, { @@ -175,10 +175,10 @@ where where E: Executor + HasObservers + HasInProcessHooks, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput, + S: HasCurrentTestcase + HasCorpus + HasSolutions, S::Solutions: Corpus, Z: HasObjective, { @@ -208,9 +208,9 @@ where where E: Executor + HasObservers + HasInProcessHooks, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput, + S: HasCurrentTestcase + HasCorpus + HasSolutions, Z: HasObjective, S::Solutions: Corpus, I: Input + Clone, diff --git a/libafl/src/executors/inprocess/mod.rs b/libafl/src/executors/inprocess/mod.rs index 70136fd16c..57ecbe1f26 100644 --- a/libafl/src/executors/inprocess/mod.rs +++ b/libafl/src/executors/inprocess/mod.rs @@ -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, - S: HasCorpus + HasCurrentTestcase + UsesInput + HasExecutions + HasSolutions, + S: HasCorpus + HasCurrentTestcase + HasExecutions + HasSolutions, S::Solutions: Corpus, I: Input, { @@ -137,7 +137,7 @@ where event_mgr: &mut EM, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -163,7 +163,7 @@ where exec_tmout: Duration, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -200,7 +200,7 @@ where timeout: Duration, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -227,7 +227,7 @@ where HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, - S: HasCorpus + HasCurrentTestcase + UsesInput + HasExecutions + HasSolutions, + S: HasCorpus + HasCurrentTestcase + HasExecutions + HasSolutions, S::Solutions: Corpus, I: Input, { @@ -241,7 +241,7 @@ where event_mgr: &mut EM, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -268,7 +268,8 @@ where exec_tmout: Duration, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, + OF: Feedback, Z: HasObjective, { @@ -301,7 +302,7 @@ where timeout: Duration, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -378,9 +379,9 @@ pub fn run_observers_and_save_state( ) where E: Executor + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, S::Solutions: Corpus, @@ -440,9 +441,9 @@ pub unsafe fn generic_inproc_crash_handler() where E: Executor + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, I: Input + Clone, S::Solutions: Corpus, Z: HasObjective + ExecutionProcessor, @@ -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; diff --git a/libafl/src/executors/inprocess/stateful.rs b/libafl/src/executors/inprocess/stateful.rs index a4c88334fd..11faf97390 100644 --- a/libafl/src/executors/inprocess/stateful.rs +++ b/libafl/src/executors/inprocess/stateful.rs @@ -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, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, I: Clone + Input, S::Solutions: Corpus, { @@ -138,7 +138,7 @@ where event_mgr: &mut EM, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -166,7 +166,7 @@ where exec_tmout: Duration, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -205,7 +205,7 @@ where timeout: Duration, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -246,12 +246,7 @@ where HT: ExecutorHooksTuple, I: Input + Clone, OT: ObserversTuple, - S: HasCorpus - + HasExecutions - + HasSolutions - + HasCorpus - + HasCurrentTestcase - + UsesInput, + S: HasCorpus + HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, S::Solutions: Corpus, { /// Create a new in mem executor with the default timeout (5 sec) @@ -265,7 +260,7 @@ where event_mgr: &mut EM, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -295,7 +290,7 @@ where exec_tmout: Duration, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { @@ -331,7 +326,7 @@ where timeout: Duration, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective, { diff --git a/libafl/src/executors/inprocess_fork/mod.rs b/libafl/src/executors/inprocess_fork/mod.rs index bd02ac8455..d826b2d9fd 100644 --- a/libafl/src/executors/inprocess_fork/mod.rs +++ b/libafl/src/executors/inprocess_fork/mod.rs @@ -382,7 +382,8 @@ mod tests { let input = NopInput {}; let mut fuzzer = NopFuzzer::new(); let mut state = NopState::new(); - let mut mgr: SimpleEventManager<_, NopState> = SimpleEventManager::printing(); + let mut mgr: SimpleEventManager> = + SimpleEventManager::printing(); in_process_fork_executor .run_target(&mut fuzzer, &mut state, &mut mgr, &input) .unwrap(); diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index 4a77191b93..993857df9e 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -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> = NopEventManager::new(); + let mut mgr: NopEventManager = NopEventManager::new(); let mut state: NopState = NopState::new(); executor diff --git a/libafl/src/feedbacks/differential.rs b/libafl/src/feedbacks/differential.rs index c5d537a5b3..e274fa1f92 100644 --- a/libafl/src/feedbacks/differential.rs +++ b/libafl/src/feedbacks/differential.rs @@ -237,7 +237,7 @@ mod tests { DiffFeedback::<_, _, _>::is_interesting( &mut diff_feedback, &mut nop_state, - &mut NopEventManager::>::default(), + &mut NopEventManager::default(), &BytesInput::new(vec![0]), &observers, &ExitKind::Ok diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs index 7e8cb9700a..988f0a16dd 100644 --- a/libafl/src/feedbacks/map.rs +++ b/libafl/src/feedbacks/map.rs @@ -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 Feedback for MapFeedback where C: CanTrack + AsRef, - EM: EventFirer, + EM: EventFirer<::Input, S>, N: IsNovel, O: MapObserver + for<'it> AsIter<'it, Item = O::Entry>, O::Entry: 'static + Default + Debug + DeserializeOwned + Serialize, OT: MatchName, R: Reducer, - S: HasNamedMetadata + UsesInput, // delete me + S: HasNamedMetadata + HasCorpus, // delete me { #[rustversion::nightly] default fn is_interesting( @@ -538,10 +538,10 @@ where impl Feedback for MapFeedback where C: CanTrack + AsRef, - EM: EventFirer, + EM: EventFirer<::Input, S>, O: MapObserver + 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, diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index f60086d229..bbc1361442 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -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 ExecutionProcessor::Inp for StdFuzzer where CS: Scheduler<::Input, S>, - EM: EventFirer, - S: HasCorpus - + MaybeHasClientPerfMonitor - + UsesInput::Input> - + HasCurrentTestcase - + HasSolutions - + HasLastFoundTime, + EM: EventFirer<::Input, S> + CanSerializeObserver, + S: HasCorpus + MaybeHasClientPerfMonitor + HasCurrentTestcase + HasSolutions + HasLastFoundTime, F: Feedback::Input, OT, S>, OF: Feedback::Input, OT, S>, OT: ObserversTuple<::Input, S> + Serialize, @@ -397,7 +394,7 @@ where if manager.configuration() == EventConfig::AlwaysUnique { None } else { - manager.serialize_observers::(observers)? + manager.serialize_observers(observers)? } } else { None @@ -515,14 +512,13 @@ where CS: Scheduler<::Input, S>, E: HasObservers + Executor::Input, S, Self>, E::Observers: MatchName + ObserversTuple<::Input, S> + Serialize, - EM: EventFirer, + EM: EventFirer<::Input, S> + CanSerializeObserver, F: Feedback::Input, E::Observers, S>, OF: Feedback::Input, E::Observers, S>, S: HasCorpus + HasSolutions + MaybeHasClientPerfMonitor + HasCurrentTestcase - + UsesInput::Input> + HasExecutions + HasLastFoundTime, ::Input: Input, @@ -593,7 +589,7 @@ where CS: Scheduler<::Input, S>, E: HasObservers + Executor::Input, S, Self>, E::Observers: MatchName + ObserversTuple<::Input, S> + Serialize, - EM: EventFirer, + EM: EventFirer<::Input, S> + CanSerializeObserver, F: Feedback::Input, E::Observers, S>, OF: Feedback::Input, E::Observers, S>, S: HasCorpus @@ -601,8 +597,7 @@ where + MaybeHasClientPerfMonitor + HasCurrentTestcase + HasLastFoundTime - + HasExecutions - + UsesInput::Input>, + + HasExecutions, ::Input: Input, S::Solutions: Corpus::Input>, IF: InputFilter<::Input>, @@ -725,7 +720,7 @@ where let observers_buf = if manager.configuration() == EventConfig::AlwaysUnique { None } else { - manager.serialize_observers::(&*observers)? + manager.serialize_observers(&*observers)? }; manager.fire( state, @@ -747,8 +742,8 @@ where impl Fuzzer for StdFuzzer where - CS: Scheduler, - EM: ProgressReporter + EventProcessor, + CS: Scheduler<::Input, S>, + EM: ProgressReporter + EventProcessor, S: HasExecutions + HasMetadata + HasCorpus @@ -756,7 +751,8 @@ where + HasTestcase + HasCurrentCorpusId + HasCurrentStageId - + State, + + Stoppable + + MaybeHasClientPerfMonitor, ST: StagesTuple, { fn fuzz_one( @@ -924,11 +920,7 @@ where CS: Scheduler<::Input, S>, E: Executor::Input, S, Self> + HasObservers, E::Observers: ObserversTuple<::Input, S>, - EM: UsesState, - S: UsesInput::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 Fuzzer for NopFuzzer where - EM: ProgressReporter + EventProcessor, + EM: ProgressReporter + EventProcessor, ST: StagesTuple, - 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 { unimplemented!("NopFuzzer cannot fuzz"); diff --git a/libafl/src/inputs/mod.rs b/libafl/src/inputs/mod.rs index 91aac35652..432cdef35a 100644 --- a/libafl/src/inputs/mod.rs +++ b/libafl/src/inputs/mod.rs @@ -277,13 +277,6 @@ impl HasMutatorBytes for &mut Vec { } } -/// 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 { diff --git a/libafl/src/monitors/mod.rs b/libafl/src/monitors/mod.rs index bfc55084bc..5a0d31a821 100644 --- a/libafl/src/monitors/mod.rs +++ b/libafl/src/monitors/mod.rs @@ -914,26 +914,6 @@ pub struct ClientPerfMonitor { timer_start: Option, } -#[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)] diff --git a/libafl/src/observers/stdio.rs b/libafl/src/observers/stdio.rs index 266cb68110..5c4547d520 100644 --- a/libafl/src/observers/stdio.rs +++ b/libafl/src/observers/stdio.rs @@ -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 Feedback for ExportStdXObserver /// where -/// S: State, /// OT: MatchNameRef /// { /// fn is_interesting( diff --git a/libafl/src/schedulers/powersched.rs b/libafl/src/schedulers/powersched.rs index df9cf8194f..91280b6b91 100644 --- a/libafl/src/schedulers/powersched.rs +++ b/libafl/src/schedulers/powersched.rs @@ -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 HasQueueCycles for PowerQueueScheduler { impl Scheduler for PowerQueueScheduler where - S: HasCorpus + HasMetadata + HasTestcase + State, + S: HasCorpus + HasMetadata + HasTestcase, O: MapObserver, C: AsRef, { diff --git a/libafl/src/stages/afl_stats.rs b/libafl/src/stages/afl_stats.rs index c45e0cff35..b68005f71a 100644 --- a/libafl/src/stages/afl_stats.rs +++ b/libafl/src/stages/afl_stats.rs @@ -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 Stage for AflStatsStage where E: HasObservers, - EM: EventFirer, + EM: EventFirer<::Input, S>, Z: HasScheduler<::Input, S>, S: HasImported + HasCorpus @@ -249,8 +248,7 @@ where + HasExecutions + HasNamedMetadata + Stoppable - + HasCurrentCorpusId - + UsesInput, + + HasCurrentCorpusId, E::Observers: MatchNameRef, O: MapObserver, C: AsRef + Named, @@ -446,7 +444,7 @@ where impl AflStatsStage where E: HasObservers, - EM: EventFirer, + EM: EventFirer<::Input, S>, S: HasImported + HasCorpus + HasMetadata + HasExecutions, C: AsRef + Named, O: MapObserver, @@ -672,7 +670,7 @@ pub struct AflStatsStageBuilder { impl AflStatsStageBuilder where E: HasObservers, - EM: EventFirer, + EM: EventFirer<::Input, S>, S: HasImported + HasCorpus + HasMetadata + HasExecutions, C: AsRef + Named, O: MapObserver, diff --git a/libafl/src/stages/calibrate.rs b/libafl/src/stages/calibrate.rs index 9bcb7e932b..35f8aec8fc 100644 --- a/libafl/src/stages/calibrate.rs +++ b/libafl/src/stages/calibrate.rs @@ -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 { impl Stage for CalibrationStage where E: Executor::Input, S, Z> + HasObservers, - EM: EventFirer, + EM: EventFirer<::Input, S>, O: MapObserver, C: AsRef, for<'de> ::Entry: @@ -103,8 +103,7 @@ where + HasNamedMetadata + HasExecutions + HasCurrentTestcase - + HasCurrentCorpusId - + UsesInput::Input>, + + HasCurrentCorpusId, Z: Evaluator::Input, S>, ::Input: Input, { diff --git a/libafl/src/stages/colorization.rs b/libafl/src/stages/colorization.rs index a47b96f827..87109a3820 100644 --- a/libafl/src/stages/colorization.rs +++ b/libafl/src/stages/colorization.rs @@ -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 Named for ColorizationStage { impl Stage for ColorizationStage where - EM: EventFirer, + EM: EventFirer<::Input, S>, E: HasObservers + Executor::Input, S, Z>, - S: HasCorpus - + HasMetadata - + HasRand - + HasNamedMetadata - + HasCurrentCorpusId - + UsesInput::Input>, + S: HasCorpus + HasMetadata + HasRand + HasNamedMetadata + HasCurrentCorpusId, E::Observers: ObserversTuple<::Input, S>, ::Input: HasMutatorBytes + Clone, O: MapObserver, @@ -156,17 +151,12 @@ libafl_bolts::impl_serdeany!(TaintMetadata); impl ColorizationStage where - EM: EventFirer, + EM: EventFirer<::Input, S>, O: MapObserver, C: AsRef + Named, E: HasObservers + Executor::Input, S, Z>, E::Observers: ObserversTuple<::Input, S>, - S: HasCorpus - + HasMetadata - + HasRand - + HasCurrentCorpusId - + HasCurrentTestcase - + UsesInput::Input>, + S: HasCorpus + HasMetadata + HasRand + HasCurrentCorpusId + HasCurrentTestcase, ::Input: HasMutatorBytes + Clone, { #[inline] diff --git a/libafl/src/stages/concolic.rs b/libafl/src/stages/concolic.rs index 904bc524be..ba820ab7bd 100644 --- a/libafl/src/stages/concolic.rs +++ b/libafl/src/stages/concolic.rs @@ -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>, - EM: UsesState, + + MaybeHasClientPerfMonitor, { #[inline] fn perform( @@ -387,8 +384,7 @@ where + HasNamedMetadata + HasCurrentTestcase + MaybeHasClientPerfMonitor - + HasCurrentCorpusId - + UsesInput::Input>, + + HasCurrentCorpusId, { #[inline] fn perform( diff --git a/libafl/src/stages/generalization.rs b/libafl/src/stages/generalization.rs index 496a1bb49e..432514f09b 100644 --- a/libafl/src/stages/generalization.rs +++ b/libafl/src/stages/generalization.rs @@ -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, + + MaybeHasClientPerfMonitor, S::Corpus: Corpus, - EM: UsesState, { #[inline] #[expect(clippy::too_many_lines)] @@ -343,14 +341,9 @@ impl GeneralizationStage where O: MapObserver, C: CanTrack + AsRef + Named, - S: HasExecutions - + HasMetadata - + HasCorpus - + MaybeHasClientPerfMonitor - + UsesInput, + S: HasExecutions + HasMetadata + HasCorpus + MaybeHasClientPerfMonitor, S::Corpus: Corpus, OT: ObserversTuple, - EM: UsesState, { /// Create a new [`GeneralizationStage`]. #[must_use] diff --git a/libafl/src/stages/generation.rs b/libafl/src/stages/generation.rs index ccf1b94f9d..336b0aff54 100644 --- a/libafl/src/stages/generation.rs +++ b/libafl/src/stages/generation.rs @@ -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 GenStage { impl Stage for GenStage where Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + UsesInput::Input>, + S: HasCorpus + HasRand, G: Generator<::Input, S>, { #[inline] diff --git a/libafl/src/stages/mod.rs b/libafl/src/stages/mod.rs index d0626abe8c..8bf7cd4fb3 100644 --- a/libafl/src/stages/mod.rs +++ b/libafl/src/stages/mod.rs @@ -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, Tail: StagesTuple + HasConstLen, S: HasCurrentStageId + Stoppable, - EM: EventProcessor, + EM: EventProcessor, { /// Performs all stages in the tuple, /// Checks after every stage if state wants to stop @@ -248,8 +248,8 @@ impl IntoVec>> for Vec StagesTuple for Vec>> where - EM: EventProcessor, - S: HasCurrentStageId + State, + EM: EventProcessor, + S: HasCurrentStageId + Stoppable, { /// Performs all stages in the `Vec` /// Checks after every stage if state wants to stop diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 9b3ffdbb9f..43bc885ddf 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -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<::Input, S> + Clone, ::Input: Input, - S::Corpus: Corpus, { #[inline] fn perform( @@ -191,9 +189,8 @@ impl StdMutationalStage::Input, M, where M: Mutator<::Input, S>, Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + HasCurrentCorpusId + UsesInput + MaybeHasClientPerfMonitor, + S: HasCorpus + HasRand + HasCurrentCorpusId + MaybeHasClientPerfMonitor, ::Input: Input + Clone, - S::Corpus: Corpus, { /// Creates a new default mutational stage pub fn new(mutator: M) -> Self { @@ -212,10 +209,9 @@ impl StdMutationalStage where M: Mutator, Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor + UsesInput, + S: HasCorpus + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor, I: MutatedTransform<::Input, S> + Clone, ::Input: Input, - S::Corpus: Corpus, { /// Creates a new transforming mutational stage with the default max iterations pub fn transforming(mutator: M) -> Self { @@ -313,10 +309,9 @@ impl Stage for MultiMutationalStage, Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + HasNamedMetadata + HasCurrentTestcase + HasCurrentCorpusId + UsesInput, + S: HasCorpus + HasRand + HasNamedMetadata + HasCurrentTestcase + HasCurrentCorpusId, I: MutatedTransform<::Input, S> + Clone, ::Input: Input, - S::Corpus: Corpus, { #[inline] fn should_restart(&mut self, state: &mut S) -> Result { diff --git a/libafl/src/stages/power.rs b/libafl/src/stages/power.rs index ba81b38b5e..9fb2ab8e9a 100644 --- a/libafl/src/stages/power.rs +++ b/libafl/src/stages/power.rs @@ -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 Stage for PowerMutationalStage where E: Executor::Input, S, Z> + HasObservers, - EM: UsesState, F: TestcaseScore, M: Mutator, S: HasCorpus @@ -90,8 +87,7 @@ where + HasNamedMetadata + HasCurrentTestcase + HasCurrentCorpusId - + MaybeHasClientPerfMonitor - + UsesInput::Input>, + + MaybeHasClientPerfMonitor, Z: Evaluator::Input, S>, I: MutatedTransform<::Input, S> + Clone + Input, ::Input: Input, @@ -122,16 +118,10 @@ where impl PowerMutationalStage where E: Executor::Input, S, Z> + HasObservers, - EM: UsesState, F: TestcaseScore, I: Input, M: Mutator, - S: HasCorpus - + HasMetadata - + HasRand - + HasCurrentTestcase - + MaybeHasClientPerfMonitor - + UsesInput::Input>, + S: HasCorpus + HasMetadata + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor, I: MutatedTransform<::Input, S> + Clone + Input, Z: Evaluator::Input, S>, ::Input: Input, diff --git a/libafl/src/stages/push/mod.rs b/libafl/src/stages/push/mod.rs index 76a2389d94..9837bad736 100644 --- a/libafl/src/stages/push/mod.rs +++ b/libafl/src/stages/push/mod.rs @@ -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>`] #[derive(Clone, Debug)] pub struct PushStageSharedState { - /// 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>, + + HasMetadata, E: Executor::Input, S, Z> + HasObservers, - EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + EM: EventFirer<::Input, S> + + EventRestarter + + HasEventManagerId + + ProgressReporter, OT: ObserversTuple<::Input, S>, PS: PushStage::Input, OT, S, Z>, Z: ExecutesInput::Input, S> diff --git a/libafl/src/stages/push/mutational.rs b/libafl/src/stages/push/mutational.rs index fd0dd57be3..a9aa086bd0 100644 --- a/libafl/src/stages/push/mutational.rs +++ b/libafl/src/stages/push/mutational.rs @@ -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 PushStage::Input, OT, S, Z> for StdMutationalPushStage where - EM: EventFirer, + EM: EventFirer<::Input, S>, Z: HasScheduler<::Input, S> + ExecutionProcessor::Input, OT, S>, - S: HasCorpus - + UsesInput::Input> - + HasRand - + MaybeHasClientPerfMonitor, + S: HasCorpus + HasRand + MaybeHasClientPerfMonitor, M: Mutator<::Input, S>, OT: ObserversTuple<::Input, S> + Serialize, ::Input: Input + Clone, @@ -193,14 +190,13 @@ where impl Iterator for StdMutationalPushStage where - EM: ProgressReporter, + EM: ProgressReporter + EventFirer<::Input, S>, S: HasCorpus + HasMetadata + HasExecutions + HasLastReportTime + HasRand - + MaybeHasClientPerfMonitor - + UsesInput::Input>, + + MaybeHasClientPerfMonitor, OT: ObserversTuple<::Input, S> + Serialize, M: Mutator<::Input, S>, ::Input: Clone + Debug + Input, @@ -216,14 +212,13 @@ where impl StdMutationalPushStage where - EM: ProgressReporter, + EM: ProgressReporter + EventFirer<::Input, S>, S: HasCorpus + HasMetadata + HasExecutions + HasLastReportTime + HasRand - + MaybeHasClientPerfMonitor - + UsesInput::Input>, + + MaybeHasClientPerfMonitor, OT: ObserversTuple<::Input, S> + Serialize, M: Mutator<::Input, S>, ::Input: Clone + Debug + Input, diff --git a/libafl/src/stages/sync.rs b/libafl/src/stages/sync.rs index 57aee77461..ed62544377 100644 --- a/libafl/src/stages/sync.rs +++ b/libafl/src/stages/sync.rs @@ -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> + 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 +pub struct SyncFromBrokerStage where - SP: ShMemProvider + 'static, - S: UsesInput, - IC: InputConverter, - ICB: InputConverter, - DI: Input, + SP: ShMemProvider, { - client: LlmpEventConverter, + client: LlmpEventConverter, } -impl Stage for SyncFromBrokerStage +impl Stage for SyncFromBrokerStage where - EM: EventFirer, - S: HasExecutions - + HasCorpus - + HasRand - + HasMetadata - + Stoppable - + UsesInput::Input> - + State, + EM: EventFirer<::Input, S>, + S: HasExecutions + HasCorpus + HasRand + HasMetadata + Stoppable + MaybeHasClientPerfMonitor, SP: ShMemProvider, E: HasObservers + Executor::Input, S, Z>, for<'a> E::Observers: Deserialize<'a>, @@ -323,17 +312,13 @@ where } } -impl SyncFromBrokerStage +impl SyncFromBrokerStage where - SP: ShMemProvider + 'static, - S: UsesInput, - IC: InputConverter, - ICB: InputConverter, - DI: Input, + SP: ShMemProvider, { /// Creates a new [`SyncFromBrokerStage`] #[must_use] - pub fn new(client: LlmpEventConverter) -> Self { + pub fn new(client: LlmpEventConverter) -> Self { Self { client } } } diff --git a/libafl/src/stages/tmin.rs b/libafl/src/stages/tmin.rs index 01f2e3837a..0303f37a25 100644 --- a/libafl/src/stages/tmin.rs +++ b/libafl/src/stages/tmin.rs @@ -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<::Input, S>, E: HasObservers, E::Observers: ObserversTuple<::Input, S> + Serialize, - EM: EventFirer, + EM: EventFirer<::Input, S>, FF: FeedbackFactory, F: Feedback::Input, E::Observers, S>, S: HasMetadata @@ -75,8 +75,7 @@ where + HasMaxSize + HasNamedMetadata + HasCurrentCorpusId - + MaybeHasClientPerfMonitor - + UsesInput::Input>, + + MaybeHasClientPerfMonitor, Z::Feedback: Feedback::Input, E::Observers, S>, M: Mutator<::Input, S>, <::Corpus as Corpus>::Input: Input + Hash + HasLen, @@ -136,7 +135,7 @@ where Z::Scheduler: RemovableScheduler<::Input, S>, E: HasObservers, E::Observers: ObserversTuple<::Input, S> + Serialize, - EM: EventFirer, + EM: EventFirer<::Input, S>, FF: FeedbackFactory, F: Feedback::Input, E::Observers, S>, S: HasMetadata @@ -147,8 +146,7 @@ where + HasNamedMetadata + HasCurrentTestcase + HasCurrentCorpusId - + MaybeHasClientPerfMonitor - + UsesInput::Input>, + + MaybeHasClientPerfMonitor, Z::Feedback: Feedback::Input, E::Observers, S>, M: Mutator<::Input, S>, ::Input: Hash + HasLen + Input, @@ -364,7 +362,6 @@ impl Feedback for MapEqualityFeedback where M: MapObserver, C: AsRef, - S: State, OT: MatchName, { fn is_interesting( @@ -424,8 +421,8 @@ impl FeedbackFactory, OT> for MapEqual where M: MapObserver, C: AsRef + Handled, - OT: ObserversTuple, - S: UsesInput, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, { fn create_feedback(&self, observers: &OT) -> MapEqualityFeedback { let obs = observers diff --git a/libafl/src/stages/tracing.rs b/libafl/src/stages/tracing.rs index 13dfdec1c0..149c96845d 100644 --- a/libafl/src/stages/tracing.rs +++ b/libafl/src/stages/tracing.rs @@ -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>, - EM: UsesState, //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>, - EM: UsesState, + + MaybeHasClientPerfMonitor, ::Input: Input, { #[inline] @@ -176,9 +172,7 @@ where + Debug + HasCurrentTestcase + HasCurrentCorpusId - + MaybeHasClientPerfMonitor - + UsesInput::Input>, - EM: UsesState, + + MaybeHasClientPerfMonitor, { #[inline] fn perform( @@ -228,9 +222,8 @@ where impl ShadowTracingStage where E: Executor::Input, S, Z> + HasObservers, - S: HasExecutions + HasCorpus + UsesInput, + S: HasExecutions + HasCorpus, SOT: ObserversTuple<::Input, S>, - EM: UsesState, { /// Creates a new default stage pub fn new(_executor: &mut ShadowExecutor) -> Self { diff --git a/libafl/src/stages/tuneable.rs b/libafl/src/stages/tuneable.rs index 2764291281..61677bd407 100644 --- a/libafl/src/stages/tuneable.rs +++ b/libafl/src/stages/tuneable.rs @@ -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>, + + MaybeHasClientPerfMonitor, I: MutatedTransform<::Input, S> + Clone, ::Input: Input, { @@ -243,8 +242,7 @@ where + HasExecutions + HasMetadata + HasCurrentTestcase - + MaybeHasClientPerfMonitor - + UsesInput::Input>, + + MaybeHasClientPerfMonitor, I: MutatedTransform<::Input, S> + Clone, ::Input: Input, { diff --git a/libafl/src/stages/verify_timeouts.rs b/libafl/src/stages/verify_timeouts.rs index 560f014340..ec2939cd59 100644 --- a/libafl/src/stages/verify_timeouts.rs +++ b/libafl/src/stages/verify_timeouts.rs @@ -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 Stage for VerifyTimeoutsStage where E::Observers: ObserversTuple<::Input, S>, E: Executor::Input, S, Z> + HasObservers + HasTimeout, - EM: UsesState, Z: Evaluator::Input, S>, - S: HasCorpus + HasMetadata + UsesInput::Input>, + S: HasCorpus + HasMetadata, ::Input: Debug + Serialize + DeserializeOwned + Default + 'static + Clone, { fn perform( diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index 0f2aba2ea9..e9f9cbce39 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -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> { - /// The state known by this type. - type State: State; -} - -// blanket impl which automatically defines UsesInput for anything that implements UsesState -impl UsesInput for KS -where - KS: UsesState, -{ - type Input = ::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 State for StdState +where + C: Serialize + DeserializeOwned, + R: Rand, + SC: Serialize + DeserializeOwned, +{ +} + // Reflexivity impl HasCorpus for C where @@ -153,29 +148,6 @@ impl MaybeHasClientPerfMonitor for T {} #[cfg(feature = "introspection")] impl 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 MaybeHasScalabilityMonitor for T {} - -#[cfg(feature = "scalability_introspection")] -impl 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 { /// 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>, @@ -296,22 +266,6 @@ pub struct StdState { phantom: PhantomData, } -impl UsesInput for StdState -where - I: Input, -{ - type Input = I; -} - -impl State for StdState -where - C: Corpus + Serialize + DeserializeOwned, - R: Rand, - SC: Corpus + Serialize + DeserializeOwned, - Self: UsesInput, -{ -} - impl HasRand for StdState where R: Rand, @@ -368,7 +322,8 @@ where impl HasSolutions for StdState where I: Input, - SC: Corpus::Input>, + C: Corpus, + SC: Corpus, { type Solutions = SC; @@ -629,9 +584,9 @@ impl HasNestedStageStatus for StdState { impl StdState where I: Input, - C: Corpus::Input>, R: Rand, - SC: Corpus::Input>, + C: Corpus, + SC: Corpus, { /// Decide if the state must load the inputs pub fn must_load_initial_inputs(&self) -> bool { @@ -723,7 +678,7 @@ where load_config: LoadConfig, ) -> Result<(), Error> where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { if let Some(remaining) = self.remaining_initial_files.as_ref() { @@ -747,7 +702,7 @@ where config: &mut LoadConfig, ) -> Result where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { log::info!("Loading file {path:?} ..."); @@ -781,7 +736,7 @@ where mut config: LoadConfig, ) -> Result<(), Error> where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { loop { @@ -845,7 +800,7 @@ where file_list: &[PathBuf], ) -> Result<(), Error> where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { self.load_initial_inputs_custom_by_filenames( @@ -872,7 +827,7 @@ where in_dirs: &[PathBuf], ) -> Result<(), Error> where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { self.canonicalize_input_dirs(in_dirs)?; @@ -898,7 +853,7 @@ where file_list: &[PathBuf], ) -> Result<(), Error> where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { self.load_initial_inputs_custom_by_filenames( @@ -923,7 +878,7 @@ where in_dirs: &[PathBuf], ) -> Result<(), Error> where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { self.canonicalize_input_dirs(in_dirs)?; @@ -949,7 +904,7 @@ where in_dirs: &[PathBuf], ) -> Result<(), Error> where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { self.canonicalize_input_dirs(in_dirs)?; @@ -990,7 +945,7 @@ where cores: &Cores, ) -> Result<(), Error> where - EM: EventFirer, + EM: EventFirer, Z: Evaluator, { if self.multicore_inputs_processed.unwrap_or(false) { @@ -1070,9 +1025,9 @@ where impl StdState where I: Input, - C: Corpus::Input>, + C: Corpus, R: Rand, - SC: Corpus::Input>, + SC: Corpus, { fn generate_initial_internal( &mut self, @@ -1084,8 +1039,8 @@ where forced: bool, ) -> Result<(), Error> where - EM: EventFirer, - G: Generator<::Input, Self>, + EM: EventFirer, + G: Generator, Z: Evaluator, { let mut added = 0; @@ -1122,8 +1077,8 @@ where num: usize, ) -> Result<(), Error> where - EM: EventFirer, - G: Generator<::Input, Self>, + EM: EventFirer, + G: Generator, Z: Evaluator, { self.generate_initial_internal(fuzzer, executor, generator, manager, num, true) @@ -1139,8 +1094,8 @@ where num: usize, ) -> Result<(), Error> where - EM: EventFirer, - G: Generator<::Input, Self>, + EM: EventFirer, + G: Generator, Z: Evaluator, { 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 HasClientPerfMonitor for StdState { } } -#[cfg(feature = "scalability_introspection")] -impl HasScalabilityMonitor for StdState { - 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 { @@ -1280,13 +1222,6 @@ impl HasCorpus for NopState { } } -impl UsesInput for NopState -where - I: Input, -{ - type Input = I; -} - impl HasExecutions for NopState { fn executions(&self) -> &u64 { &self.execution @@ -1353,8 +1288,6 @@ impl HasRand for NopState { } } -impl State for NopState where I: Input {} - impl HasCurrentCorpusId for NopState { fn set_corpus_id(&mut self, _id: CorpusId) -> Result<(), Error> { Ok(()) @@ -1394,17 +1327,6 @@ impl HasClientPerfMonitor for NopState { } } -#[cfg(feature = "scalability_introspection")] -impl HasScalabilityMonitor for NopState { - 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}; diff --git a/libafl_frida/src/asan/errors.rs b/libafl_frida/src/asan/errors.rs index bdd062d262..8fbc9fd969 100644 --- a/libafl_frida/src/asan/errors.rs +++ b/libafl_frida/src/asan/errors.rs @@ -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 { impl StateInitializer for AsanErrorsFeedback {} -impl Feedback for AsanErrorsFeedback +impl Feedback::Input, OT, S> for AsanErrorsFeedback where - S: State + Debug, + S: HasCorpus + Debug, OT: MatchNameRef, { fn is_interesting( &mut self, _state: &mut S, _manager: &mut EM, - _input: &S::Input, + _input: &::Input, observers: &OT, _exit_kind: &ExitKind, ) -> Result { @@ -678,7 +678,7 @@ where _state: &mut S, _manager: &mut EM, _observers: &OT, - testcase: &mut Testcase, + testcase: &mut Testcase<::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: &::Input, + ) -> Result<(), Error> { self.errors = None; Ok(()) } diff --git a/libafl_frida/src/executor.rs b/libafl_frida/src/executor.rs index d16a71446b..f3a1cffee9 100644 --- a/libafl_frida/src/executor.rs +++ b/libafl_frida/src/executor.rs @@ -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 Executor for FridaInProcessExecutor<'_, '_, '_, H, I, OT, RT, S, TC> where - EM: UsesState, H: FnMut(&I) -> ExitKind, - S: HasCorpus + HasExecutions + UsesInput, + S: HasCorpus + HasExecutions, TC: TargetBytesConverter, OT: ObserversTuple, RT: FridaRuntimeTuple, @@ -226,7 +225,7 @@ impl<'a, 'b, 'c, H, I, OT, RT, S, TC> HasInProcessHooks for FridaInProcessExecutor<'a, 'b, 'c, H, I, OT, RT, S, TC> where H: FnMut(&I) -> ExitKind, - S: HasSolutions + HasCorpus + HasCurrentTestcase + HasExecutions + UsesInput, + S: HasSolutions + HasCorpus + HasCurrentTestcase + HasExecutions, S::Solutions: Corpus, I: Input, TC: TargetBytesConverter, diff --git a/libafl_libfuzzer/build.rs b/libafl_libfuzzer/build.rs index 46342c7405..6c293b4f0e 100644 --- a/libafl_libfuzzer/build.rs +++ b/libafl_libfuzzer/build.rs @@ -161,7 +161,7 @@ fn main() -> Result<(), Box> { .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()); diff --git a/libafl_libfuzzer/runtime/src/feedbacks.rs b/libafl_libfuzzer/runtime/src/feedbacks.rs index e67b5f8a72..12ed1eb195 100644 --- a/libafl_libfuzzer/runtime/src/feedbacks.rs +++ b/libafl_libfuzzer/runtime/src/feedbacks.rs @@ -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 StateInitializer for LibfuzzerKeepFeedback {} -impl Feedback for LibfuzzerKeepFeedback +impl Feedback::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: &::Input, _observers: &OT, _exit_kind: &ExitKind, ) -> Result { @@ -119,7 +119,6 @@ impl StateInitializer for LibfuzzerCrashCauseFeedback {} impl Feedback for LibfuzzerCrashCauseFeedback where - S: State, OT: MatchNameRef, { fn is_interesting( diff --git a/libafl_libfuzzer/runtime/src/fuzz.rs b/libafl_libfuzzer/runtime/src/fuzz.rs index fddcf0bb59..86c773a30e 100644 --- a/libafl_libfuzzer/runtime/src/fuzz.rs +++ b/libafl_libfuzzer/runtime/src/fuzz.rs @@ -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, S: HasMetadata + HasExecutions - + UsesInput + HasSolutions + HasLastReportTime + HasCurrentStageId + Stoppable, - EM: ProgressReporter + EventProcessor, + EM: ProgressReporter + EventProcessor, ST: StagesTuple, { if let Some(solution) = state.solutions().last() { @@ -113,7 +111,7 @@ where fuzz_with!(options, harness, do_fuzz, |fuzz_single| { let (state, mgr): ( Option>, - 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, diff --git a/libafl_libfuzzer/runtime/src/merge.rs b/libafl_libfuzzer/runtime/src/merge.rs index c5400a6a27..5af3fb4824 100644 --- a/libafl_libfuzzer/runtime/src/merge.rs +++ b/libafl_libfuzzer/runtime/src/merge.rs @@ -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>, - 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, diff --git a/libafl_libfuzzer/runtime/src/observers.rs b/libafl_libfuzzer/runtime/src/observers.rs index c92a8ecf16..bd054330e2 100644 --- a/libafl_libfuzzer/runtime/src/observers.rs +++ b/libafl_libfuzzer/runtime/src/observers.rs @@ -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 Observer for MappedEdgeMapObserver +impl Observer<::Input, S> for MappedEdgeMapObserver where - M: Observer + Debug, - O: Observer + Debug, - S: UsesInput, + S: HasCorpus, + M: Observer<::Input, S> + Debug, + O: Observer<::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: &::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: &::Input, exit_kind: &ExitKind, ) -> Result<(), Error> { self.inner.post_exec(state, input, exit_kind)?; @@ -255,12 +259,16 @@ impl Named for SizeValueObserver { } } -impl Observer for SizeValueObserver +impl Observer<::Input, S> for SizeValueObserver where - S: UsesInput, - S::Input: HasLen, + S: HasCorpus, + ::Input: HasLen, { - fn pre_exec(&mut self, _state: &mut S, input: &S::Input) -> Result<(), Error> { + fn pre_exec( + &mut self, + _state: &mut S, + input: &::Input, + ) -> Result<(), Error> { self.size = input.len(); Ok(()) } @@ -299,18 +307,22 @@ impl Named for TimeValueObserver { } } -impl Observer for TimeValueObserver +impl Observer<::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: &::Input, + ) -> Result<(), Error> { self.time_obs.pre_exec(state, input) } fn post_exec( &mut self, state: &mut S, - input: &S::Input, + input: &::Input, exit_kind: &ExitKind, ) -> Result<(), Error> { self.time_obs.post_exec(state, input, exit_kind)?; @@ -361,12 +373,16 @@ impl Named for SizeTimeValueObserver { } } -impl Observer for SizeTimeValueObserver +impl Observer<::Input, S> for SizeTimeValueObserver where - S: UsesInput, - S::Input: HasLen, + S: HasCorpus, + ::Input: HasLen, { - fn pre_exec(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error> { + fn pre_exec( + &mut self, + state: &mut S, + input: &::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: &::Input, exit_kind: &ExitKind, ) -> Result<(), Error> { self.time_obs.post_exec(state, input, exit_kind)?; diff --git a/libafl_libfuzzer/runtime/src/report.rs b/libafl_libfuzzer/runtime/src/report.rs index 642ad0cb09..0afc49ef89 100644 --- a/libafl_libfuzzer/runtime/src/report.rs +++ b/libafl_libfuzzer/runtime/src/report.rs @@ -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 + EventProcessor, + EM: ProgressReporter + EventProcessor, ST: StagesTuple, { let meta = state diff --git a/libafl_libfuzzer/runtime/src/schedulers.rs b/libafl_libfuzzer/runtime/src/schedulers.rs index 82ea6298a9..d14d8c0c77 100644 --- a/libafl_libfuzzer/runtime/src/schedulers.rs +++ b/libafl_libfuzzer/runtime/src/schedulers.rs @@ -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 { impl RemovableScheduler for MergeScheduler where I: Input, - S: State + HasCorpus, + S: HasCorpus, { fn on_remove( &mut self, @@ -35,7 +35,7 @@ where impl Scheduler for MergeScheduler where - S: State + HasCorpus, + S: HasCorpus, { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { self.all.insert(id); diff --git a/libafl_nyx/src/executor.rs b/libafl_nyx/src/executor.rs index 8fcc555137..36029e2d27 100644 --- a/libafl_nyx/src/executor.rs +++ b/libafl_nyx/src/executor.rs @@ -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 Executor::Input, S, Z> for NyxExecutor where - EM: UsesState, - S: HasCorpus + HasExecutions + UsesInput::Input>, + S: HasCorpus + HasExecutions, ::Input: HasTargetBytes, OT: ObserversTuple<::Input, S>, { diff --git a/libafl_qemu/src/emu/builder.rs b/libafl_qemu/src/emu/builder.rs index dec5e32bfe..43541b6904 100644 --- a/libafl_qemu/src/emu/builder.rs +++ b/libafl_qemu/src/emu/builder.rs @@ -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 StdSnapshotManager, > where - S: State + HasExecutions + Unpin, + S: HasExecutions + Unpin, I: HasTargetBytes, { #[must_use] @@ -104,7 +101,7 @@ impl StdSnapshotManager, > where - S: State + HasExecutions + Unpin, + S: HasExecutions + Unpin, I: HasTargetBytes, { #[expect(clippy::should_implement_trait)] diff --git a/libafl_qemu/src/emu/mod.rs b/libafl_qemu/src/emu/mod.rs index 7ee0f0edae..afe846cd20 100644 --- a/libafl_qemu/src/emu/mod.rs +++ b/libafl_qemu/src/emu/mod.rs @@ -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 Emulator Emulator, StdEmulatorDriver, (), I, S, StdSnapshotManager> where - S: State + HasExecutions + Unpin, + S: HasExecutions + Unpin, I: HasTargetBytes, { #[must_use] diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index 170d1a5559..faf4abd164 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -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( ) where E: HasObservers + HasInProcessHooks + Executor, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, ET: EmulatorModuleTuple, I: Unpin, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + Unpin + HasCurrentTestcase + UsesInput, + S: HasExecutions + HasSolutions + HasCorpus + Unpin + HasCurrentTestcase, I: Input, S::Solutions: Corpus, Z: HasObjective, @@ -152,7 +152,7 @@ where H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, I: Input + Unpin, OT: ObserversTuple, - S: HasCorpus + Unpin + HasExecutions + HasSolutions + State, + S: HasCorpus + Unpin + HasExecutions + HasSolutions + HasCurrentTestcase, S::Solutions: Corpus, { pub fn new( @@ -168,7 +168,7 @@ where C: Clone, CM: CommandManager, ED: EmulatorDriver, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective + HasScheduler + ExecutionProcessor, ::Corpus: Corpus, @@ -248,12 +248,11 @@ where C: Clone, CM: CommandManager, ED: EmulatorDriver, - EM: UsesState, ET: EmulatorModuleTuple, H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, I: Unpin, OT: ObserversTuple, - S: State + HasExecutions + Unpin + HasCorpus, + S: HasExecutions + Unpin + HasCorpus, { fn run_target( &mut self, @@ -290,7 +289,7 @@ where ET: EmulatorModuleTuple, H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, OT: ObserversTuple, - S: State + HasCorpus, + S: HasCorpus, { type Observers = OT; #[inline] @@ -318,12 +317,11 @@ impl Debug where C: Debug, CM: Debug, - EM: UsesState, ED: Debug, ET: EmulatorModuleTuple + Debug, OT: ObserversTuple + Debug, I: Debug, - S: UsesInput + 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 + EventRestarter, + EM: EventFirer + EventRestarter, ET: EmulatorModuleTuple, OT: ObserversTuple, - S: State + HasSolutions + HasCorpus, + S: HasSolutions + HasCorpus, SP: ShMemProvider, Z: HasObjective, Z::Objective: Feedback, @@ -404,13 +402,13 @@ where C: Clone, CM: CommandManager, ED: EmulatorDriver, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, ET: EmulatorModuleTuple, H: FnMut(&mut Emulator, &I) -> ExitKind, OF: Feedback, OT: ObserversTuple + Debug, I: Input + Unpin, - S: State + HasExecutions + Unpin + HasCorpus, + S: HasExecutions + Unpin + HasCorpus, SP: ShMemProvider, Z: HasObjective, { @@ -438,26 +436,12 @@ where } } -#[cfg(feature = "fork")] -impl UsesState - for QemuForkExecutor<'_, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> -where - ET: EmulatorModuleTuple, - OT: ObserversTuple, - S: State, - SP: ShMemProvider, -{ - type State = S; -} - #[cfg(feature = "fork")] impl HasObservers for QemuForkExecutor<'_, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> where - EM: UsesState, ET: EmulatorModuleTuple, OT: ObserversTuple, - S: State, SP: ShMemProvider, { type Observers = OT; diff --git a/libafl_targets/src/cmps/stages/aflpptracing.rs b/libafl_targets/src/cmps/stages/aflpptracing.rs index 308978c0f4..b3edfd81bd 100644 --- a/libafl_targets/src/cmps/stages/aflpptracing.rs +++ b/libafl_targets/src/cmps/stages/aflpptracing.rs @@ -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 Named for AFLppCmplogTracingStage<'_, EM, TE, S, Z> { impl Stage for AFLppCmplogTracingStage<'_, EM, TE, S, Z> where - EM: UsesState, TE: HasObservers + Executor, TE::Observers: MatchNameRef + ObserversTuple, - S: HasCorpus - + HasCurrentTestcase - + UsesInput - + HasMetadata - + HasNamedMetadata - + HasCurrentCorpusId, + S: HasCorpus + HasCurrentTestcase + HasMetadata + HasNamedMetadata + HasCurrentCorpusId, S::Corpus: Corpus, { #[inline] diff --git a/libafl_targets/src/libfuzzer/mutators.rs b/libafl_targets/src/libfuzzer/mutators.rs index 434fbed7ca..34abfb72a3 100644 --- a/libafl_targets/src/libfuzzer/mutators.rs +++ b/libafl_targets/src/libfuzzer/mutators.rs @@ -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, M::Mutations: MutatorsTuple, - S: HasMaxSize + UsesInput, + 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 Named for LLVMCustomMutator { impl Mutator for LLVMCustomMutator where - S: UsesInput + HasRand + HasMaxSize + 'static, + S: HasRand + HasMaxSize + 'static, SM: ScheduledMutator + 'static, SM::Mutations: MutatorsTuple, { #[inline] - fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result { + fn mutate(&mut self, state: &mut S, input: &mut BytesInput) -> Result { self.scheduled_mutate(state, input) } } @@ -303,15 +303,15 @@ where impl ScheduledMutator for LLVMCustomMutator where SM: ScheduledMutator + 'static, - S: UsesInput + HasRand + HasMaxSize + 'static, + S: HasRand + HasMaxSize + 'static, SM::Mutations: MutatorsTuple, { - 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 { let seed = state.rand_mut().next(); let len_orig = input.bytes().len(); @@ -367,13 +367,13 @@ impl Named for LLVMCustomMutator { impl Mutator for LLVMCustomMutator where - S: UsesInput + HasRand + HasMaxSize + HasCorpus + 'static, + S: HasRand + HasMaxSize + HasCorpus + 'static, SM: ScheduledMutator + 'static, S::Corpus: Corpus, SM::Mutations: MutatorsTuple, { #[inline] - fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result { + fn mutate(&mut self, state: &mut S, input: &mut BytesInput) -> Result { self.scheduled_mutate(state, input) } } @@ -381,16 +381,16 @@ where impl ScheduledMutator for LLVMCustomMutator where SM: ScheduledMutator + 'static, - S: UsesInput + HasRand + HasMaxSize + HasCorpus + 'static, + S: HasRand + HasMaxSize + HasCorpus + 'static, S::Corpus: Corpus, SM::Mutations: MutatorsTuple, { - 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 { 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 diff --git a/libafl_targets/src/windows_asan.rs b/libafl_targets/src/windows_asan.rs index edabcdc9f1..40d3d4bf1b 100644 --- a/libafl_targets/src/windows_asan.rs +++ b/libafl_targets/src/windows_asan.rs @@ -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(_executor: &E, _event_mgr: where E: Executor + HasObservers, E::Observers: ObserversTuple, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, S::Solutions: Corpus, Z: HasObjective, I: Input + Clone, diff --git a/libafl_tinyinst/src/executor.rs b/libafl_tinyinst/src/executor.rs index 7a6c8cd693..19296148c8 100644 --- a/libafl_tinyinst/src/executor.rs +++ b/libafl_tinyinst/src/executor.rs @@ -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 Executor::Input, S, Z> for TinyInstExecutor where - EM: UsesState, - S: HasCorpus + HasExecutions + UsesInput::Input>, + S: HasCorpus + HasExecutions, ::Input: HasTargetBytes, SP: ShMemProvider, {