diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index d53c6cfece..2d37cd3d17 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -290,7 +290,7 @@ jobs: - ./fuzzers/structure_aware/forkserver_simple_nautilus # In-process - # - ./fuzzers/fuzz_anything/cargo_fuzz # Revive after they fix rustc + - ./fuzzers/fuzz_anything/cargo_fuzz # - ./fuzzers/inprocess/dynamic_analysis - ./fuzzers/inprocess/fuzzbench - ./fuzzers/inprocess/fuzzbench_text diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 352e5bd302..f4510882dc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ Before making your pull requests, try to see if your code follows these rules. - `PhantomData` should have the smallest set of types needed. Try not adding `PhantomData` to your struct unless it is really necessary. Also even when you really need `PhantomData`, try to keep the types `T` used in `PhantomData` as smallest as possible - Wherever possible, trait implementations with lifetime specifiers should use '_ lifetime elision. - Complex constructors should be replaced with `typed_builder`, or write code in the builder pattern for yourself. -- Remove generic restrictions at the definitions (e.g., we do not need to specify that types impl `Serialize`, `Deserialize`, or `Debug` anymore at the struct definitions). Therefore, try avoiding code like this unless the contraint is really necessary. +- Remove generic restrictions at the definitions (e.g., we do not need to specify that types impl `Serialize`, `Deserialize`, or `Debug` anymore at the struct definitions). Therefore, try avoiding code like this unless the constraint is really necessary. ```rust pub struct X where @@ -35,9 +35,8 @@ pub struct X { fn ... } - ``` -- Reduce generics to the least restrictive necessary. __Never overspecify the contraints__. There's no automated tool to check the useless constraints, so you have to verify this manually. +- Reduce generics to the least restrictive necessary. __Never overspecify the constraints__. There's no automated tool to check the useless constraints, so you have to verify this manually. ```rust pub struct X where @@ -45,17 +44,37 @@ pub struct X { fn ... } - ``` -- Traits which have an associated type should refer to the associated type, not the concrete/generic. In other words, you should only have the associated type when you can define a getter to it. For example, in the following code, you can define a associate type. + +- Prefer generic to associated types in traits definition as much as possible. They are much easier to use around, and avoid tricky caveats / type repetition in the code. It is also much easier to have unconstrained struct definitions. + +Try not to write this: +```rust +pub trait X +{ + type A; + + fn a(&self) -> Self::A; +} +``` +Try to write this instead: +```rust +pub trait X +{ + fn a(&self) -> A; +} +``` + +- Traits which have an associated type (if you have made sure you cannot use a generic instead) should refer to the associated type, not the concrete/generic. In other words, you should only have the associated type when you can define a getter to it. For example, in the following code, you can define a associate type. ```rust pub trait X { type A; // <- You should(can) define it as long as you have a getter to it. - fn a(&self) -> A; + + fn a(&self) -> Self::A; } - ``` + - __Ideally__ the types used in the the arguments of methods in traits should have the same as the types defined on the traits. ```rust pub trait X // <- this trait have 3 generics, A, B, and C diff --git a/MIGRATION.md b/MIGRATION.md index af6972e069..f50bf045b3 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -14,7 +14,9 @@ - Trait restrictions have been simplified - 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 + - `Input` is now only accessible through generic. `Input` associated types have been definitely removed. + - `HasCorpus` bound has been removed in many places it was unused before. + - `StdMutationalStage::transforming` must now explicitly state the Inputs types. As a result, `StdMutationalStage::transforming` must be written `StdMutationalStage::<_, _, FirstInputType, SecondInputType, _, _, _>::transforming`. - The `State` trait is now private in favour of individual and more specific traits - Restrictions from certain schedulers and stages that required their inner observer to implement `MapObserver` have been lifted in favor of requiring `Hash` - Related: removed `hash_simple` from `MapObserver` diff --git a/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs index a7b036f669..3b3abdbfb8 100644 --- a/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs @@ -47,17 +47,17 @@ impl CustomExecutor { } } -impl Executor::Input, S, Z> for CustomExecutor +impl Executor for CustomExecutor where - S: HasCorpus + HasExecutions, - ::Input: HasTargetBytes, + S: HasCorpus + HasExecutions, + I: HasTargetBytes, { fn run_target( &mut self, _fuzzer: &mut Z, state: &mut S, _mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { // We need to keep track of the exec count. *state.executions_mut() += 1; diff --git a/fuzzers/baby/baby_fuzzer_unicode/src/main.rs b/fuzzers/baby/baby_fuzzer_unicode/src/main.rs index fb9dfedfd8..5e7b5eed80 100644 --- a/fuzzers/baby/baby_fuzzer_unicode/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_unicode/src/main.rs @@ -13,7 +13,10 @@ use libafl::{ feedbacks::{CrashFeedback, MaxMapFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, - mutators::{StdScheduledMutator, UnicodeCategoryRandMutator, UnicodeSubcategoryRandMutator}, + mutators::{ + StdScheduledMutator, UnicodeCategoryRandMutator, UnicodeInput, + UnicodeSubcategoryRandMutator, + }, observers::StdMapObserver, schedulers::QueueScheduler, stages::{mutational::StdMutationalStage, UnicodeIdentificationStage}, @@ -134,7 +137,7 @@ pub fn main() { )); let mut stages = tuple_list!( UnicodeIdentificationStage::new(), - StdMutationalStage::transforming(mutator) + StdMutationalStage::<_, _, UnicodeInput, BytesInput, _, _, _>::transforming(mutator) ); fuzzer diff --git a/fuzzers/baby/tutorial/src/metadata.rs b/fuzzers/baby/tutorial/src/metadata.rs index 0c93ebd5f7..87084c011c 100644 --- a/fuzzers/baby/tutorial/src/metadata.rs +++ b/fuzzers/baby/tutorial/src/metadata.rs @@ -1,11 +1,10 @@ use std::borrow::Cow; use libafl::{ - corpus::{Corpus, Testcase}, + corpus::Testcase, executors::ExitKind, feedbacks::{Feedback, MapIndexesMetadata, StateInitializer}, schedulers::{MinimizerScheduler, TestcaseScore}, - state::HasCorpus, Error, HasMetadata, }; use libafl_bolts::{Named, SerdeAny}; @@ -20,14 +19,11 @@ pub struct PacketLenMetadata { pub struct PacketLenTestcaseScore {} -impl TestcaseScore for PacketLenTestcaseScore +impl TestcaseScore for PacketLenTestcaseScore where - S: HasMetadata + HasCorpus, + S: HasMetadata, { - fn compute( - _state: &S, - entry: &mut Testcase<::Input>, - ) -> Result { + fn compute(_state: &S, entry: &mut Testcase) -> Result { Ok(entry .metadata_map() .get::() @@ -35,8 +31,8 @@ where } } -pub type PacketLenMinimizerScheduler = - MinimizerScheduler; +pub type PacketLenMinimizerScheduler = + MinimizerScheduler; #[derive(Serialize, Deserialize, Default, Clone, Debug)] pub struct PacketLenFeedback { diff --git a/fuzzers/binary_only/frida_executable_libpng/src/fuzzer.rs b/fuzzers/binary_only/frida_executable_libpng/src/fuzzer.rs index 65493e720f..bd3e2202a4 100644 --- a/fuzzers/binary_only/frida_executable_libpng/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_executable_libpng/src/fuzzer.rs @@ -96,7 +96,7 @@ unsafe fn fuzz( let shmem_provider = StdShMemProvider::new()?; let mut run_client = |state: Option<_>, - mgr: LlmpRestartingEventManager<_, _, _>, + mgr: LlmpRestartingEventManager<_, _, _, _>, client_description: ClientDescription| { // The restarting state will spawn the same process again as child, then restarted it each time it crashes. @@ -104,7 +104,7 @@ unsafe fn fuzz( if options.asan && options.asan_cores.contains(client_description.core_id()) { (|state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _client_description| { let gum = Gum::obtain(); @@ -231,7 +231,7 @@ unsafe fn fuzz( })(state, mgr, client_description) } else if options.cmplog && options.cmplog_cores.contains(client_description.core_id()) { (|state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _client_description| { let gum = Gum::obtain(); @@ -367,7 +367,7 @@ unsafe fn fuzz( })(state, mgr, client_description) } else { (|state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _client_description| { let gum = Gum::obtain(); diff --git a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs index 9a94d2459a..adc03b5212 100644 --- a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs @@ -81,7 +81,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { }; let mut run_client = |state: Option<_>, - mgr: LlmpRestartingEventManager<_, _, _>, + mgr: LlmpRestartingEventManager<_, _, _, _>, client_description: ClientDescription| { // The restarting state will spawn the same process again as child, then restarted it each time it crashes. @@ -100,7 +100,9 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { }; // if options.asan && options.asan_cores.contains(client_description.core_id()) { - (|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _>, _client_description| { + (|state: Option<_>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, + _client_description| { let gum = Gum::obtain(); let coverage = CoverageRuntime::new(); diff --git a/fuzzers/binary_only/frida_windows_gdiplus/src/fuzzer.rs b/fuzzers/binary_only/frida_windows_gdiplus/src/fuzzer.rs index 42e9d5de25..7e613bf238 100644 --- a/fuzzers/binary_only/frida_windows_gdiplus/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_windows_gdiplus/src/fuzzer.rs @@ -78,7 +78,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { let shmem_provider = StdShMemProvider::new()?; let mut run_client = |state: Option<_>, - mgr: LlmpRestartingEventManager<_, _, _>, + mgr: LlmpRestartingEventManager<_, _, _, _>, client_description: ClientDescription| { // The restarting state will spawn the same process again as child, then restarted it each time it crashes. @@ -98,7 +98,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { if options.asan && options.asan_cores.contains(client_description.core_id()) { (|state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _client_description| { let gum = Gum::obtain(); @@ -214,7 +214,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { })(state, mgr, client_description) } else if options.cmplog && options.cmplog_cores.contains(client_description.core_id()) { (|state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _client_description| { let gum = Gum::obtain(); @@ -344,7 +344,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { })(state, mgr, client_description) } else { (|state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _client_description| { let gum = Gum::obtain(); diff --git a/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs b/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs index 5f8d5b666d..9fd14cf324 100644 --- a/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs +++ b/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs @@ -9,8 +9,7 @@ use clap::{builder::Str, Parser}; use libafl::{ corpus::{Corpus, InMemoryCorpus}, events::{ - launcher::Launcher, ClientDescription, EventConfig, EventRestarter, - LlmpRestartingEventManager, ManagerExit, + launcher::Launcher, ClientDescription, EventConfig, LlmpRestartingEventManager, ManagerExit, }, executors::ExitKind, fuzzer::StdFuzzer, @@ -31,7 +30,7 @@ use libafl_bolts::{ use libafl_qemu::{ elf::EasyElf, modules::{drcov::DrCovModule, utils::filters::StdAddressFilter}, - ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, Qemu, QemuExecutor, + ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, QemuExecutor, QemuExitReason, QemuRWError, QemuShutdownCause, Regs, }; @@ -124,7 +123,7 @@ pub fn fuzz() { env::remove_var("LD_LIBRARY_PATH"); let mut run_client = |state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, client_description: ClientDescription| { let mut cov_path = options.coverage_path.clone(); diff --git a/fuzzers/binary_only/qemu_launcher/src/client.rs b/fuzzers/binary_only/qemu_launcher/src/client.rs index 3ab3fdfb97..9a7b9e0459 100644 --- a/fuzzers/binary_only/qemu_launcher/src/client.rs +++ b/fuzzers/binary_only/qemu_launcher/src/client.rs @@ -23,7 +23,7 @@ use crate::{ #[expect(clippy::module_name_repetitions)] pub type ClientState = - StdState, StdRand, OnDiskCorpus>; + StdState, BytesInput, StdRand, OnDiskCorpus>; pub struct Client<'a> { options: &'a FuzzerOptions, diff --git a/fuzzers/binary_only/qemu_launcher/src/instance.rs b/fuzzers/binary_only/qemu_launcher/src/instance.rs index 3401e04e36..fd1756c9e8 100644 --- a/fuzzers/binary_only/qemu_launcher/src/instance.rs +++ b/fuzzers/binary_only/qemu_launcher/src/instance.rs @@ -52,13 +52,15 @@ use typed_builder::TypedBuilder; use crate::{harness::Harness, options::FuzzerOptions}; pub type ClientState = - StdState, StdRand, OnDiskCorpus>; + StdState, BytesInput, StdRand, OnDiskCorpus>; #[cfg(feature = "simplemgr")] pub type ClientMgr = SimpleEventManager; #[cfg(not(feature = "simplemgr"))] -pub type ClientMgr = - MonitorTypedEventManager, M>; +pub type ClientMgr = MonitorTypedEventManager< + LlmpRestartingEventManager<(), BytesInput, ClientState, StdShMemProvider>, + M, +>; #[derive(TypedBuilder)] pub struct Instance<'a, M: Monitor> { @@ -321,7 +323,7 @@ impl Instance<'_, M> { stages: &mut ST, ) -> Result<(), Error> where - Z: Fuzzer, ClientState, ST> + Z: Fuzzer, BytesInput, ClientState, ST> + Evaluator, BytesInput, ClientState>, ST: StagesTuple, ClientState, Z>, { diff --git a/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs b/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs index cd63d37f00..70db2c148a 100644 --- a/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs +++ b/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs @@ -376,7 +376,7 @@ fn fuzz( let cb = |_fuzzer: &mut _, _executor: &mut _, - state: &mut StdState<_, InMemoryOnDiskCorpus<_>, _, _>, + state: &mut StdState, _, _, _>, _event_manager: &mut _| -> Result { let testcase = state.current_testcase()?; diff --git a/fuzzers/forkserver/libafl-fuzz/src/executor.rs b/fuzzers/forkserver/libafl-fuzz/src/executor.rs index 5824e94618..71bcdb2f1f 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/executor.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/executor.rs @@ -6,7 +6,6 @@ use std::{ }; use libafl::{ - corpus::Corpus, executors::{Executor, ExitKind, HasObservers, HasTimeout}, state::HasCorpus, Error, @@ -253,25 +252,23 @@ fn check_file_found(file: &Path, perm: u32) -> bool { } #[cfg(feature = "nyx")] -pub enum SupportedExecutors { - Forkserver(FSV, PhantomData<(S, OT, NYX)>), +pub enum SupportedExecutors { + Forkserver(FSV, PhantomData<(FSV, I, OT)>), Nyx(NYX), } #[cfg(feature = "nyx")] -impl Executor::Input, S, Z> - for SupportedExecutors +impl Executor for SupportedExecutors where - S: HasCorpus, - NYX: Executor::Input, S, Z>, - FSV: Executor::Input, S, Z>, + NYX: Executor, + FSV: Executor, { fn run_target( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { match self { Self::Forkserver(fsrv, _) => fsrv.run_target(fuzzer, state, mgr, input), @@ -282,7 +279,7 @@ where } #[cfg(feature = "nyx")] -impl HasObservers for SupportedExecutors +impl HasObservers for SupportedExecutors where NYX: HasObservers, FSV: HasObservers, @@ -308,7 +305,7 @@ where } #[cfg(feature = "nyx")] -impl HasTimeout for SupportedExecutors +impl HasTimeout for SupportedExecutors where FSV: HasTimeout, NYX: HasTimeout, @@ -330,23 +327,22 @@ where } #[cfg(not(feature = "nyx"))] -pub enum SupportedExecutors { - Forkserver(FSV, PhantomData<(S, OT)>), +pub enum SupportedExecutors { + Forkserver(FSV, PhantomData<(I, OT, S)>), } #[cfg(not(feature = "nyx"))] -impl Executor::Input, S, Z> - for SupportedExecutors +impl Executor for SupportedExecutors where - S: HasCorpus, - FSV: Executor::Input, S, Z>, + S: HasCorpus, + FSV: Executor, { fn run_target( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { match self { Self::Forkserver(fsrv, _) => fsrv.run_target(fuzzer, state, mgr, input), @@ -355,7 +351,7 @@ where } #[cfg(not(feature = "nyx"))] -impl HasObservers for SupportedExecutors +impl HasObservers for SupportedExecutors where FSV: HasObservers, { @@ -376,7 +372,7 @@ where } #[cfg(not(feature = "nyx"))] -impl HasTimeout for SupportedExecutors +impl HasTimeout for SupportedExecutors where FSV: HasTimeout, { diff --git a/fuzzers/forkserver/libafl-fuzz/src/feedback/filepath.rs b/fuzzers/forkserver/libafl-fuzz/src/feedback/filepath.rs index 842fe53924..28fc3d2009 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/feedback/filepath.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/feedback/filepath.rs @@ -4,10 +4,9 @@ use std::{ }; use libafl::{ - corpus::{Corpus, Testcase}, + corpus::Testcase, executors::ExitKind, feedbacks::{Feedback, FeedbackFactory, StateInitializer}, - state::HasCorpus, }; use libafl_bolts::{Error, Named}; use serde::{Deserialize, Serialize}; @@ -53,18 +52,16 @@ impl Named for CustomFilepathToTestcaseFeedback { impl StateInitializer for CustomFilepathToTestcaseFeedback {} -impl Feedback::Input, OT, S> - for CustomFilepathToTestcaseFeedback +impl Feedback for CustomFilepathToTestcaseFeedback where - S: HasCorpus, - F: FnMut(&mut S, &mut Testcase<::Input>, &Path) -> Result<(), Error>, + F: FnMut(&mut S, &mut Testcase, &Path) -> Result<(), Error>, { #[inline] fn is_interesting( &mut self, _state: &mut S, _manager: &mut EM, - _input: &::Input, + _input: &I, _observers: &OT, _exit_kind: &ExitKind, ) -> Result { @@ -76,7 +73,7 @@ where state: &mut S, _manager: &mut EM, _observers: &OT, - testcase: &mut Testcase<::Input>, + testcase: &mut Testcase, ) -> Result<(), Error> { (self.func)(state, testcase, &self.out_dir)?; Ok(()) diff --git a/fuzzers/forkserver/libafl-fuzz/src/feedback/persistent_record.rs b/fuzzers/forkserver/libafl-fuzz/src/feedback/persistent_record.rs index ba1dda32a1..a64ea76e42 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/feedback/persistent_record.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/feedback/persistent_record.rs @@ -52,8 +52,7 @@ impl StateInitializer for PersitentRecordFeedback {} impl Feedback for PersitentRecordFeedback where - S: HasCorpus, - S::Corpus: Corpus, + S: HasCorpus, I: Input, { #[inline] diff --git a/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs b/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs index 7ee439740f..5d545207ad 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs @@ -73,12 +73,13 @@ use crate::{ }; pub type LibaflFuzzState = - StdState, StdRand, OnDiskCorpus>; + StdState, BytesInput, StdRand, OnDiskCorpus>; #[cfg(not(feature = "fuzzbench"))] type LibaflFuzzManager = CentralizedEventManager< - LlmpRestartingEventManager<(), LibaflFuzzState, StdShMemProvider>, + LlmpRestartingEventManager<(), BytesInput, LibaflFuzzState, StdShMemProvider>, (), + BytesInput, LibaflFuzzState, StdShMemProvider, >; @@ -521,7 +522,7 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, { ); // Run our fuzzer; WITH CmpLog - run_fuzzer_with_stages( + run_fuzzer_with_stages::<_, _, BytesInput, _, _, _>( opt, &mut fuzzer, &mut stages, @@ -540,7 +541,7 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, { ); // Run our fuzzer; NO CmpLog - run_fuzzer_with_stages( + run_fuzzer_with_stages::<_, _, BytesInput, _, _, _>( opt, &mut fuzzer, &mut stages, @@ -648,7 +649,7 @@ pub fn fuzzer_target_mode(opt: &Opt) -> Cow<'static, str> { #[derive(Debug, Serialize, Deserialize, SerdeAny)] pub struct IsInitialCorpusEntryMetadata {} -pub fn run_fuzzer_with_stages( +pub fn run_fuzzer_with_stages( opt: &Opt, fuzzer: &mut Z, stages: &mut ST, @@ -657,7 +658,7 @@ pub fn run_fuzzer_with_stages( mgr: &mut EM, ) -> Result<(), Error> where - Z: Fuzzer, + Z: Fuzzer, EM: ProgressReporter, ST: StagesTuple, S: HasLastReportTime + HasExecutions + HasMetadata, diff --git a/fuzzers/forkserver/libafl-fuzz/src/hooks.rs b/fuzzers/forkserver/libafl-fuzz/src/hooks.rs index 7b50ead881..672c420363 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/hooks.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/hooks.rs @@ -1,7 +1,6 @@ use libafl::{ - corpus::Corpus, events::{Event, EventManagerHook}, - state::{HasCorpus, Stoppable}, + state::Stoppable, Error, }; use libafl_bolts::ClientId; @@ -11,15 +10,15 @@ pub struct LibAflFuzzEventHook { exit_on_solution: bool, } -impl EventManagerHook<::Input, S> for LibAflFuzzEventHook +impl EventManagerHook for LibAflFuzzEventHook where - S: HasCorpus + Stoppable, + S: Stoppable, { fn pre_exec( &mut self, state: &mut S, _client_id: ClientId, - event: &Event<::Input>, + event: &Event, ) -> Result { if self.exit_on_solution && matches!(event, Event::Objective { .. }) { // TODO: dump state diff --git a/fuzzers/forkserver/libafl-fuzz/src/scheduler.rs b/fuzzers/forkserver/libafl-fuzz/src/scheduler.rs index fa50cdf338..b34089f962 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/scheduler.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/scheduler.rs @@ -13,19 +13,17 @@ pub enum SupportedSchedulers { Weighted(W, PhantomData), } -impl RemovableScheduler<::Input, S> for SupportedSchedulers +impl RemovableScheduler for SupportedSchedulers where - Q: Scheduler<::Input, S> - + RemovableScheduler<::Input, S>, - W: Scheduler<::Input, S> - + RemovableScheduler<::Input, S>, - S: HasCorpus + HasTestcase, + Q: Scheduler + RemovableScheduler, + W: Scheduler + RemovableScheduler, + S: HasTestcase, { fn on_remove( &mut self, state: &mut S, id: CorpusId, - testcase: &Option::Input>>, + testcase: &Option>, ) -> Result<(), Error> { match self { Self::Queue(queue, _) => queue.on_remove(state, id, testcase), @@ -33,12 +31,7 @@ where } } - fn on_replace( - &mut self, - state: &mut S, - id: CorpusId, - prev: &Testcase<::Input>, - ) -> Result<(), Error> { + fn on_replace(&mut self, state: &mut S, id: CorpusId, prev: &Testcase) -> Result<(), Error> { match self { Self::Queue(queue, _) => queue.on_replace(state, id, prev), Self::Weighted(weighted, _) => weighted.on_replace(state, id, prev), @@ -46,11 +39,11 @@ where } } -impl Scheduler<::Input, S> for SupportedSchedulers +impl Scheduler for SupportedSchedulers where - Q: Scheduler<::Input, S>, - W: Scheduler<::Input, S>, - S: HasCorpus + HasTestcase, + Q: Scheduler, + W: Scheduler, + S: HasCorpus + HasTestcase, { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { match self { @@ -82,12 +75,7 @@ where Self::Weighted(weighted, _) => weighted.next(state), } } - fn on_evaluation( - &mut self, - state: &mut S, - input: &::Input, - observers: &OTB, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, input: &I, observers: &OTB) -> Result<(), Error> where OTB: MatchName, { diff --git a/fuzzers/inprocess/fuzzbench_text/src/lib.rs b/fuzzers/inprocess/fuzzbench_text/src/lib.rs index 62426bead5..82dd8400da 100644 --- a/fuzzers/inprocess/fuzzbench_text/src/lib.rs +++ b/fuzzers/inprocess/fuzzbench_text/src/lib.rs @@ -23,7 +23,7 @@ use libafl::{ feedback_or, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, fuzzer::{Fuzzer, StdFuzzer}, - inputs::{BytesInput, HasTargetBytes}, + inputs::{BytesInput, GeneralizedInputMetadata, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ grimoire::{ @@ -604,7 +604,10 @@ fn fuzz_text( 3, ); - let grimoire = StdMutationalStage::transforming(grimoire_mutator); + let grimoire = + StdMutationalStage::<_, _, GeneralizedInputMetadata, BytesInput, _, _, _>::transforming( + grimoire_mutator, + ); // A minimization+queue policy to get testcasess from the corpus let scheduler = IndexesLenTimeMinimizerScheduler::new( diff --git a/fuzzers/inprocess/libfuzzer_libpng_centralized/src/lib.rs b/fuzzers/inprocess/libfuzzer_libpng_centralized/src/lib.rs index 1ffbabb60d..8eb53dafe8 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_centralized/src/lib.rs +++ b/fuzzers/inprocess/libfuzzer_libpng_centralized/src/lib.rs @@ -141,7 +141,7 @@ pub extern "C" fn libafl_main() { let mut secondary_run_client = |state: Option<_>, - mut mgr: CentralizedEventManager<_, _, _, _>, + mut mgr: CentralizedEventManager<_, _, _, _, _>, _client_description: ClientDescription| { // Create an observation channel using the coverage map let edges_observer = diff --git a/fuzzers/inprocess/libfuzzer_libpng_cmin/src/lib.rs b/fuzzers/inprocess/libfuzzer_libpng_cmin/src/lib.rs index fbfb76f6e6..88e552b437 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_cmin/src/lib.rs +++ b/fuzzers/inprocess/libfuzzer_libpng_cmin/src/lib.rs @@ -219,7 +219,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re let orig_size = state.corpus().count(); let msg = "Started distillation...".to_string(); - as EventFirer>::log( + as EventFirer>::log( &mut restarting_mgr, &mut state, LogSeverity::Info, @@ -227,7 +227,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re )?; minimizer.minimize(&mut fuzzer, &mut executor, &mut restarting_mgr, &mut state)?; let msg = format!("Distilled out {} cases", orig_size - state.corpus().count()); - as EventFirer>::log( + as EventFirer>::log( &mut restarting_mgr, &mut state, LogSeverity::Info, diff --git a/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs b/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs index 5acd766852..8b299b1517 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs +++ b/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs @@ -162,7 +162,7 @@ pub extern "C" fn libafl_main() { ); let mut run_client = |state: Option<_>, - mut restarting_mgr: LlmpRestartingEventManager<_, _, _>, + mut restarting_mgr: LlmpRestartingEventManager<_, _, _, _>, client_description: ClientDescription| { // Create an observation channel using the coverage map let edges_observer = diff --git a/fuzzers/structure_aware/baby_fuzzer_grimoire/src/main.rs b/fuzzers/structure_aware/baby_fuzzer_grimoire/src/main.rs index 9f3f4b9d40..2fc08297e1 100644 --- a/fuzzers/structure_aware/baby_fuzzer_grimoire/src/main.rs +++ b/fuzzers/structure_aware/baby_fuzzer_grimoire/src/main.rs @@ -8,7 +8,7 @@ use libafl::{ executors::{inprocess::InProcessExecutor, ExitKind}, feedbacks::{CrashFeedback, MaxMapFeedback}, fuzzer::{Evaluator, Fuzzer, StdFuzzer}, - inputs::{BytesInput, HasTargetBytes}, + inputs::{BytesInput, GeneralizedInputMetadata, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ havoc_mutations, scheduled::StdScheduledMutator, GrimoireExtensionMutator, @@ -157,7 +157,9 @@ pub fn main() { let mut stages = tuple_list!( generalization, StdMutationalStage::new(mutator), - StdMutationalStage::transforming(grimoire_mutator) + StdMutationalStage::<_, _, GeneralizedInputMetadata, BytesInput, _, _, _>::transforming( + grimoire_mutator + ) ); for input in initial_inputs { diff --git a/libafl/examples/tui_mock/main.rs b/libafl/examples/tui_mock/main.rs index 6ca34fc9cd..ccc18171ea 100644 --- a/libafl/examples/tui_mock/main.rs +++ b/libafl/examples/tui_mock/main.rs @@ -9,7 +9,7 @@ use libafl_bolts::ClientId; pub fn main() { let mut monitor = TuiMonitor::builder().build(); - let client_stats = ClientStats { + let _client_stats = ClientStats { corpus_size: 1024, executions: 512, ..ClientStats::default() diff --git a/libafl/src/corpus/cached.rs b/libafl/src/corpus/cached.rs index 2e21fee65c..ecc9007ccf 100644 --- a/libafl/src/corpus/cached.rs +++ b/libafl/src/corpus/cached.rs @@ -1,7 +1,7 @@ //! The [`CachedOnDiskCorpus`] stores [`Testcase`]s to disk, keeping a subset of them in memory/cache, evicting in a FIFO manner. use alloc::{collections::vec_deque::VecDeque, string::String}; -use core::cell::RefCell; +use core::cell::{Ref, RefCell, RefMut}; use std::path::Path; use serde::{Deserialize, Serialize}; @@ -55,12 +55,11 @@ where Ok(()) } } -impl Corpus for CachedOnDiskCorpus + +impl Corpus for CachedOnDiskCorpus where I: Input, { - type Input = I; - /// Returns the number of all enabled entries #[inline] fn count(&self) -> usize { @@ -98,7 +97,7 @@ where } /// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases. - fn remove(&mut self, id: CorpusId) -> Result, Error> { + fn remove(&mut self, id: CorpusId) -> Result, Error> { let testcase = self.inner.remove(id)?; self.cached_indexes.borrow_mut().retain(|e| *e != id); Ok(testcase) @@ -113,7 +112,7 @@ where } /// Get by id; considers both enabled and disabled testcases #[inline] - fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error> { + fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error> { let testcase = { self.inner.get_from_all(id)? }; self.cache_testcase(testcase, id)?; Ok(testcase) @@ -169,25 +168,25 @@ where } #[inline] - fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error> { + fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error> { self.inner.load_input_into(testcase) } #[inline] - fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error> { + fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error> { self.inner.store_input_from(testcase) } } -impl HasTestcase for CachedOnDiskCorpus +impl HasTestcase for CachedOnDiskCorpus where I: Input, { - fn testcase(&self, id: CorpusId) -> Result>, Error> { + fn testcase(&self, id: CorpusId) -> Result>, Error> { Ok(self.get(id)?.borrow()) } - fn testcase_mut(&self, id: CorpusId) -> Result>, Error> { + fn testcase_mut(&self, id: CorpusId) -> Result>, Error> { Ok(self.get(id)?.borrow_mut()) } } diff --git a/libafl/src/corpus/inmemory.rs b/libafl/src/corpus/inmemory.rs index 4af250506c..f89b6f6d69 100644 --- a/libafl/src/corpus/inmemory.rs +++ b/libafl/src/corpus/inmemory.rs @@ -1,7 +1,7 @@ //! In-memory corpus, keeps all test cases in memory at all times use alloc::vec::Vec; -use core::cell::RefCell; +use core::cell::{Ref, RefCell, RefMut}; use serde::{Deserialize, Serialize}; @@ -314,9 +314,7 @@ pub struct InMemoryCorpus { current: Option, } -impl Corpus for InMemoryCorpus { - type Input = I; - +impl Corpus for InMemoryCorpus { /// Returns the number of all enabled entries #[inline] fn count(&self) -> usize { @@ -360,7 +358,7 @@ impl Corpus for InMemoryCorpus { /// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases #[inline] - fn remove(&mut self, id: CorpusId) -> Result, Error> { + fn remove(&mut self, id: CorpusId) -> Result, Error> { let mut testcase = self.storage.enabled.remove(id); if testcase.is_none() { testcase = self.storage.disabled.remove(id); @@ -380,7 +378,7 @@ impl Corpus for InMemoryCorpus { } /// Get by id; considers both enabled and disabled testcases #[inline] - fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error> { + fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error> { let mut testcase = self.storage.enabled.get(id); if testcase.is_none() { testcase = self.storage.disabled.get(id); @@ -400,17 +398,17 @@ impl Corpus for InMemoryCorpus { &mut self.current } + #[inline] + fn next(&self, id: CorpusId) -> Option { + self.storage.enabled.next(id) + } + /// Peek the next free corpus id #[inline] fn peek_free_id(&self) -> CorpusId { self.storage.peek_free_id() } - #[inline] - fn next(&self, id: CorpusId) -> Option { - self.storage.enabled.next(id) - } - #[inline] fn prev(&self, id: CorpusId) -> Option { self.storage.enabled.prev(id) @@ -443,29 +441,23 @@ impl Corpus for InMemoryCorpus { } #[inline] - fn load_input_into(&self, _: &mut Testcase) -> Result<(), Error> { + fn load_input_into(&self, _: &mut Testcase) -> Result<(), Error> { // Inputs never get evicted, nothing to load here. Ok(()) } #[inline] - fn store_input_from(&self, _: &Testcase) -> Result<(), Error> { + fn store_input_from(&self, _: &Testcase) -> Result<(), Error> { Ok(()) } } -impl HasTestcase for InMemoryCorpus { - fn testcase( - &self, - id: CorpusId, - ) -> Result::Input>>, Error> { +impl HasTestcase for InMemoryCorpus { + fn testcase(&self, id: CorpusId) -> Result>, Error> { Ok(self.get(id)?.borrow()) } - fn testcase_mut( - &self, - id: CorpusId, - ) -> Result::Input>>, Error> { + fn testcase_mut(&self, id: CorpusId) -> Result>, Error> { Ok(self.get(id)?.borrow_mut()) } } diff --git a/libafl/src/corpus/inmemory_ondisk.rs b/libafl/src/corpus/inmemory_ondisk.rs index 8afccf93cb..e5a51b3434 100644 --- a/libafl/src/corpus/inmemory_ondisk.rs +++ b/libafl/src/corpus/inmemory_ondisk.rs @@ -5,7 +5,7 @@ //! which only stores a certain number of [`Testcase`]s and removes additional ones in a FIFO manner. use alloc::string::String; -use core::cell::RefCell; +use core::cell::{Ref, RefCell, RefMut}; use std::{ fs, fs::{File, OpenOptions}, @@ -59,12 +59,10 @@ pub struct InMemoryOnDiskCorpus { locking: bool, } -impl Corpus for InMemoryOnDiskCorpus +impl Corpus for InMemoryOnDiskCorpus where I: Input, { - type Input = I; - /// Returns the number of all enabled entries #[inline] fn count(&self) -> usize { @@ -182,7 +180,7 @@ where self.inner.nth_from_all(nth) } - fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error> { + fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error> { if testcase.input_mut().is_none() { let Some(file_path) = testcase.file_path().as_ref() else { return Err(Error::illegal_argument( @@ -195,7 +193,7 @@ where Ok(()) } - fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error> { + fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error> { // Store the input to disk let Some(file_path) = testcase.file_path() else { return Err(Error::illegal_argument( @@ -211,21 +209,15 @@ where } } -impl HasTestcase for InMemoryOnDiskCorpus +impl HasTestcase for InMemoryOnDiskCorpus where I: Input, { - fn testcase( - &self, - id: CorpusId, - ) -> Result::Input>>, Error> { + fn testcase(&self, id: CorpusId) -> Result>, Error> { Ok(self.get(id)?.borrow()) } - fn testcase_mut( - &self, - id: CorpusId, - ) -> Result::Input>>, Error> { + fn testcase_mut(&self, id: CorpusId) -> Result>, Error> { Ok(self.get(id)?.borrow_mut()) } } @@ -242,7 +234,7 @@ impl InMemoryOnDiskCorpus { /// If you don't want metadata, use [`InMemoryOnDiskCorpus::no_meta`]. /// To pick a different metadata format, use [`InMemoryOnDiskCorpus::with_meta_format`]. /// - /// Will error, if [`std::fs::create_dir_all()`] failed for `dir_path`. + /// Will error, if [`fs::create_dir_all()`] failed for `dir_path`. pub fn new

(dir_path: P) -> Result where P: AsRef, @@ -257,7 +249,7 @@ impl InMemoryOnDiskCorpus { /// Creates the [`InMemoryOnDiskCorpus`] specifying the format in which `Metadata` will be saved to disk. /// - /// Will error, if [`std::fs::create_dir_all()`] failed for `dir_path`. + /// Will error, if [`fs::create_dir_all()`] failed for `dir_path`. pub fn with_meta_format

( dir_path: P, meta_format: Option, @@ -271,7 +263,7 @@ impl InMemoryOnDiskCorpus { /// Creates the [`InMemoryOnDiskCorpus`] specifying the format in which `Metadata` will be saved to disk /// and the prefix for the filenames. /// - /// Will error, if [`std::fs::create_dir_all()`] failed for `dir_path`. + /// Will error, if [`fs::create_dir_all()`] failed for `dir_path`. pub fn with_meta_format_and_prefix

( dir_path: P, meta_format: Option, @@ -286,7 +278,7 @@ impl InMemoryOnDiskCorpus { /// Creates an [`InMemoryOnDiskCorpus`] that will not store .metadata files /// - /// Will error, if [`std::fs::create_dir_all()`] failed for `dir_path`. + /// Will error, if [`fs::create_dir_all()`] failed for `dir_path`. pub fn no_meta

(dir_path: P) -> Result where P: AsRef, diff --git a/libafl/src/corpus/minimizer.rs b/libafl/src/corpus/minimizer.rs index 42fd357a0f..35f8f8ed9f 100644 --- a/libafl/src/corpus/minimizer.rs +++ b/libafl/src/corpus/minimizer.rs @@ -29,16 +29,16 @@ use crate::{ /// /// Algorithm based on WMOPT: #[derive(Debug)] -pub struct MapCorpusMinimizer { +pub struct MapCorpusMinimizer { observer_handle: Handle, - phantom: PhantomData<(E, O, S, T, TS)>, + phantom: PhantomData<(E, I, O, S, T, TS)>, } /// Standard corpus minimizer, which weights inputs by length and time. -pub type StdCorpusMinimizer = - MapCorpusMinimizer; +pub type StdCorpusMinimizer = + MapCorpusMinimizer; -impl MapCorpusMinimizer +impl MapCorpusMinimizer where C: Named, { @@ -52,14 +52,14 @@ where } } -impl MapCorpusMinimizer +impl MapCorpusMinimizer where for<'a> O: MapObserver + AsIter<'a, Item = T>, C: AsRef, - S: HasMetadata + HasCorpus + HasExecutions, - ::Input: Input, + I: Input, + S: HasMetadata + HasCorpus + HasExecutions, T: Copy + Hash + Eq, - TS: TestcaseScore, + TS: TestcaseScore, { /// Do the minimization #[expect(clippy::too_many_lines)] @@ -71,12 +71,11 @@ where state: &mut S, ) -> Result<(), Error> where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, - CS: Scheduler<::Input, S> - + RemovableScheduler<::Input, S>, - EM: EventFirer<::Input, S>, - Z: HasScheduler<::Input, S, Scheduler = CS>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, + CS: Scheduler + RemovableScheduler, + EM: EventFirer, + Z: HasScheduler, { // don't delete this else it won't work after restart let current = *state.corpus().current(); diff --git a/libafl/src/corpus/mod.rs b/libafl/src/corpus/mod.rs index 8e4917c225..d7670d1a10 100644 --- a/libafl/src/corpus/mod.rs +++ b/libafl/src/corpus/mod.rs @@ -1,5 +1,11 @@ //! Corpuses contain the testcases, either in memory, on disk, or somewhere else. +use core::{cell::RefCell, fmt, marker::PhantomData}; + +use serde::{Deserialize, Serialize}; + +use crate::Error; + pub mod testcase; pub use testcase::{HasTestcase, SchedulerTestcaseMetadata, Testcase}; @@ -23,15 +29,11 @@ pub use cached::CachedOnDiskCorpus; #[cfg(all(feature = "cmin", unix))] pub mod minimizer; -use core::{cell::RefCell, fmt}; pub mod nop; #[cfg(all(feature = "cmin", unix))] pub use minimizer::*; pub use nop::NopCorpus; -use serde::{Deserialize, Serialize}; - -use crate::Error; /// An abstraction for the index that identify a testcase in the corpus #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] @@ -101,10 +103,7 @@ macro_rules! random_corpus_id_with_disabled { } /// Corpus with all current [`Testcase`]s, or solutions -pub trait Corpus: Sized { - /// The type of input contained in this corpus - type Input; - +pub trait Corpus: Sized { /// Returns the number of all enabled entries fn count(&self) -> usize; @@ -120,26 +119,22 @@ pub trait Corpus: Sized { } /// Add an enabled testcase to the corpus and return its index - fn add(&mut self, testcase: Testcase) -> Result; + fn add(&mut self, testcase: Testcase) -> Result; /// Add a disabled testcase to the corpus and return its index - fn add_disabled(&mut self, testcase: Testcase) -> Result; + fn add_disabled(&mut self, testcase: Testcase) -> Result; /// Replaces the [`Testcase`] at the given idx, returning the existing. - fn replace( - &mut self, - id: CorpusId, - testcase: Testcase, - ) -> Result, Error>; + fn replace(&mut self, id: CorpusId, testcase: Testcase) -> Result, Error>; /// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases - fn remove(&mut self, id: CorpusId) -> Result, Error>; + fn remove(&mut self, id: CorpusId) -> Result, Error>; /// Get by id; considers only enabled testcases - fn get(&self, id: CorpusId) -> Result<&RefCell>, Error>; + fn get(&self, id: CorpusId) -> Result<&RefCell>, Error>; /// Get by id; considers both enabled and disabled testcases - fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error>; + fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error>; /// Current testcase scheduled fn current(&self) -> &Option; @@ -163,11 +158,12 @@ pub trait Corpus: Sized { fn last(&self) -> Option; /// An iterator over very active corpus id - fn ids(&self) -> CorpusIdIterator<'_, Self> { + fn ids(&self) -> CorpusIdIterator<'_, Self, I> { CorpusIdIterator { corpus: self, cur: self.first(), cur_back: self.last(), + phantom: PhantomData, } } @@ -184,15 +180,15 @@ pub trait Corpus: Sized { /// Method to load the input for this [`Testcase`] from persistent storage, /// if necessary, and if was not already loaded (`== Some(input)`). /// After this call, `testcase.input()` must always return `Some(input)`. - fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error>; + fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error>; /// Method to store the input of this `Testcase` to persistent storage, if necessary. - fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error>; + fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error>; /// Loads the `Input` for a given [`CorpusId`] from the [`Corpus`], and returns the clone. - fn cloned_input_for_id(&self, id: CorpusId) -> Result + fn cloned_input_for_id(&self, id: CorpusId) -> Result where - Self::Input: Clone, + I: Clone, { let mut testcase = self.get(id)?.borrow_mut(); Ok(testcase.load_input(self)?.clone()) @@ -213,18 +209,16 @@ pub trait HasCurrentCorpusId { /// [`Iterator`] over the ids of a [`Corpus`] #[derive(Debug)] -pub struct CorpusIdIterator<'a, C> -where - C: Corpus, -{ +pub struct CorpusIdIterator<'a, C, I> { corpus: &'a C, cur: Option, cur_back: Option, + phantom: PhantomData, } -impl Iterator for CorpusIdIterator<'_, C> +impl Iterator for CorpusIdIterator<'_, C, I> where - C: Corpus, + C: Corpus, { type Item = CorpusId; @@ -238,9 +232,9 @@ where } } -impl DoubleEndedIterator for CorpusIdIterator<'_, C> +impl DoubleEndedIterator for CorpusIdIterator<'_, C, I> where - C: Corpus, + C: Corpus, { fn next_back(&mut self) -> Option { if let Some(cur_back) = self.cur_back { diff --git a/libafl/src/corpus/nop.rs b/libafl/src/corpus/nop.rs index e50173f9e0..87d3cc8d40 100644 --- a/libafl/src/corpus/nop.rs +++ b/libafl/src/corpus/nop.rs @@ -15,8 +15,7 @@ pub struct NopCorpus { phantom: PhantomData, } -impl Corpus for NopCorpus { - type Input = I; +impl Corpus for NopCorpus { /// Returns the number of all enabled entries #[inline] fn count(&self) -> usize { @@ -76,12 +75,6 @@ impl Corpus for NopCorpus { &self.empty } - /// Peek the next free corpus id - #[inline] - fn peek_free_id(&self) -> CorpusId { - CorpusId::from(0_usize) - } - /// Current testcase scheduled (mutable) #[inline] fn current_mut(&mut self) -> &mut Option { @@ -93,6 +86,12 @@ impl Corpus for NopCorpus { None } + /// Peek the next free corpus id + #[inline] + fn peek_free_id(&self) -> CorpusId { + CorpusId::from(0_usize) + } + #[inline] fn prev(&self, _id: CorpusId) -> Option { None @@ -121,12 +120,12 @@ impl Corpus for NopCorpus { } #[inline] - fn load_input_into(&self, _testcase: &mut Testcase) -> Result<(), Error> { + fn load_input_into(&self, _testcase: &mut Testcase) -> Result<(), Error> { Err(Error::unsupported("Unsupported by NopCorpus")) } #[inline] - fn store_input_from(&self, _testcase: &Testcase) -> Result<(), Error> { + fn store_input_from(&self, _testcase: &Testcase) -> Result<(), Error> { Err(Error::unsupported("Unsupported by NopCorpus")) } } diff --git a/libafl/src/corpus/ondisk.rs b/libafl/src/corpus/ondisk.rs index 5c6569538f..c6bc604202 100644 --- a/libafl/src/corpus/ondisk.rs +++ b/libafl/src/corpus/ondisk.rs @@ -2,7 +2,7 @@ //! //! It _never_ keeps any of them in memory. //! This is a good solution for solutions that are never reused, or for *very* memory-constraint environments. -//! For any other occasions, consider using [`crate::corpus::CachedOnDiskCorpus`] +//! For any other occasions, consider using [`CachedOnDiskCorpus`] //! which stores a certain number of [`Testcase`]s in memory and removes additional ones in a FIFO manner. use alloc::string::String; @@ -56,11 +56,10 @@ pub struct OnDiskCorpus { inner: CachedOnDiskCorpus, } -impl Corpus for OnDiskCorpus +impl Corpus for OnDiskCorpus where I: Input, { - type Input = I; /// Returns the number of all enabled entries #[inline] fn count(&self) -> usize { @@ -96,12 +95,6 @@ where self.inner.replace(id, testcase) } - /// Peek the next free corpus id - #[inline] - fn peek_free_id(&self) -> CorpusId { - self.inner.peek_free_id() - } - /// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases #[inline] fn remove(&mut self, id: CorpusId) -> Result, Error> { @@ -137,6 +130,12 @@ where self.inner.next(id) } + /// Peek the next free corpus id + #[inline] + fn peek_free_id(&self) -> CorpusId { + self.inner.peek_free_id() + } + #[inline] fn prev(&self, id: CorpusId) -> Option { self.inner.prev(id) @@ -164,17 +163,17 @@ where } #[inline] - fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error> { + fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error> { self.inner.load_input_into(testcase) } #[inline] - fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error> { + fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error> { self.inner.store_input_from(testcase) } } -impl HasTestcase for OnDiskCorpus +impl HasTestcase for OnDiskCorpus where I: Input, { diff --git a/libafl/src/corpus/testcase.rs b/libafl/src/corpus/testcase.rs index 776de28c70..8a86ff6d7a 100644 --- a/libafl/src/corpus/testcase.rs +++ b/libafl/src/corpus/testcase.rs @@ -15,24 +15,18 @@ use libafl_bolts::{serdeany::SerdeAnyMap, HasLen}; use serde::{Deserialize, Serialize}; use super::Corpus; -use crate::{corpus::CorpusId, state::HasCorpus, Error, HasMetadata}; +use crate::{corpus::CorpusId, Error, HasMetadata}; /// Shorthand to receive a [`Ref`] or [`RefMut`] to a stored [`Testcase`], by [`CorpusId`]. /// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives. -pub trait HasTestcase: HasCorpus { +pub trait HasTestcase { /// Shorthand to receive a [`Ref`] to a stored [`Testcase`], by [`CorpusId`]. /// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives. - fn testcase( - &self, - id: CorpusId, - ) -> Result::Input>>, Error>; + fn testcase(&self, id: CorpusId) -> Result>, Error>; /// Shorthand to receive a [`RefMut`] to a stored [`Testcase`], by [`CorpusId`]. /// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives. - fn testcase_mut( - &self, - id: CorpusId, - ) -> Result::Input>>, Error>; + fn testcase_mut(&self, id: CorpusId) -> Result>, Error>; } /// An entry in the [`Testcase`] Corpus @@ -87,7 +81,7 @@ impl HasMetadata for Testcase { /// Impl of a testcase impl Testcase { /// Returns this [`Testcase`] with a loaded `Input`] - pub fn load_input>(&mut self, corpus: &C) -> Result<&I, Error> { + pub fn load_input>(&mut self, corpus: &C) -> Result<&I, Error> { corpus.load_input_into(self)?; Ok(self.input.as_ref().unwrap()) } @@ -358,7 +352,7 @@ where } /// Get the `len` or calculate it, if not yet calculated. - pub fn load_len>(&mut self, corpus: &C) -> Result { + pub fn load_len>(&mut self, corpus: &C) -> Result { match &self.input { Some(i) => { let l = i.len(); diff --git a/libafl/src/events/centralized.rs b/libafl/src/events/centralized.rs index f2c4c3656b..bc636b6bf9 100644 --- a/libafl/src/events/centralized.rs +++ b/libafl/src/events/centralized.rs @@ -29,7 +29,6 @@ use super::{CanSerializeObserver, ManagerExit, NopEventManager}; use crate::events::llmp::COMPRESS_THRESHOLD; use crate::{ common::HasMetadata, - corpus::Corpus, events::{ serialize_observers_adaptive, std_maybe_report_progress, std_report_progress, AdaptiveSerializer, Event, EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, @@ -39,9 +38,7 @@ use crate::{ fuzzer::{EvaluatorObservers, ExecutionProcessor}, inputs::{Input, NopInput}, observers::TimeObserver, - state::{ - HasCorpus, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, NopState, Stoppable, - }, + state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, NopState, Stoppable}, Error, }; @@ -49,7 +46,7 @@ pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453); /// A wrapper manager to implement a main-secondary architecture with another broker #[derive(Debug)] -pub struct CentralizedEventManager +pub struct CentralizedEventManager where SP: ShMemProvider, { @@ -61,10 +58,10 @@ where time_ref: Option>, hooks: EMH, is_main: bool, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl CentralizedEventManager, NopShMemProvider> { +impl CentralizedEventManager, NopShMemProvider> { /// Creates a builder for [`CentralizedEventManager`] #[must_use] pub fn builder() -> CentralizedEventManagerBuilder { @@ -98,13 +95,13 @@ impl CentralizedEventManagerBuilder { } /// Creates a new [`CentralizedEventManager`]. - pub fn build_from_client( + pub fn build_from_client( self, inner: EM, hooks: EMH, client: LlmpClient, time_obs: Option>, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, { @@ -124,14 +121,14 @@ impl CentralizedEventManagerBuilder { /// /// If the port is not yet bound, it will act as a broker; otherwise, it /// will act as a client. - pub fn build_on_port( + pub fn build_on_port( self, inner: EM, hooks: EMH, shmem_provider: SP, port: u16, time_obs: Option>, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, { @@ -141,14 +138,14 @@ impl CentralizedEventManagerBuilder { /// If a client respawns, it may reuse the existing connection, previously /// stored by [`LlmpClient::to_env()`]. - pub fn build_existing_client_from_env( + pub fn build_existing_client_from_env( self, inner: EM, hooks: EMH, shmem_provider: SP, env_name: &str, time_obs: Option>, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, { @@ -157,14 +154,14 @@ impl CentralizedEventManagerBuilder { } /// Create an existing client from description - pub fn existing_client_from_description( + pub fn existing_client_from_description( self, inner: EM, hooks: EMH, shmem_provider: SP, description: &LlmpClientDescription, time_obs: Option>, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, { @@ -173,7 +170,7 @@ impl CentralizedEventManagerBuilder { } } -impl AdaptiveSerializer for CentralizedEventManager +impl AdaptiveSerializer for CentralizedEventManager where EM: AdaptiveSerializer, SP: ShMemProvider, @@ -209,25 +206,20 @@ where } } -impl EventFirer<::Input, S> - for CentralizedEventManager +impl EventFirer for CentralizedEventManager where - EM: HasEventManagerId + EventFirer<::Input, S>, - EMH: EventManagerHooksTuple<<::Corpus as Corpus>::Input, S>, + EM: HasEventManagerId + EventFirer, + EMH: EventManagerHooksTuple, SP: ShMemProvider, - S: HasCorpus + Stoppable, - <::Corpus as Corpus>::Input: Input, + S: Stoppable, + I: Input, { fn should_send(&self) -> bool { self.inner.should_send() } #[expect(clippy::match_same_arms)] - fn fire( - &mut self, - state: &mut S, - mut event: Event<::Input>, - ) -> Result<(), Error> { + fn fire(&mut self, state: &mut S, mut event: Event) -> Result<(), Error> { if !self.is_main { // secondary node let mut is_tc = false; @@ -270,7 +262,7 @@ where } } -impl EventRestarter for CentralizedEventManager +impl EventRestarter for CentralizedEventManager where SP: ShMemProvider, EM: EventRestarter, @@ -283,7 +275,7 @@ where } } -impl CanSerializeObserver for CentralizedEventManager +impl CanSerializeObserver for CentralizedEventManager where EM: AdaptiveSerializer, SP: ShMemProvider, @@ -299,7 +291,7 @@ where } } -impl ManagerExit for CentralizedEventManager +impl ManagerExit for CentralizedEventManager where EM: ManagerExit, SP: ShMemProvider, @@ -316,17 +308,16 @@ where } } -impl EventProcessor for CentralizedEventManager +impl EventProcessor for CentralizedEventManager where E: HasObservers, E::Observers: DeserializeOwned, - EM: EventProcessor + HasEventManagerId + EventFirer<::Input, S>, - EMH: EventManagerHooksTuple<::Input, S>, - S: HasCorpus + Stoppable, - ::Input: Input, + EM: EventProcessor + HasEventManagerId + EventFirer, + EMH: EventManagerHooksTuple, + S: Stoppable, + I: Input, SP: ShMemProvider, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + Z: ExecutionProcessor + EvaluatorObservers, { fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { if self.is_main { @@ -345,17 +336,12 @@ where } } -impl ProgressReporter for CentralizedEventManager +impl ProgressReporter for CentralizedEventManager where - EM: EventFirer<::Input, S> + HasEventManagerId, - EMH: EventManagerHooksTuple<<::Corpus as Corpus>::Input, S>, - S: HasExecutions - + HasMetadata - + HasLastReportTime - + Stoppable - + HasCorpus - + MaybeHasClientPerfMonitor, - ::Input: Input, + EM: EventFirer + HasEventManagerId, + EMH: EventManagerHooksTuple, + S: HasExecutions + HasMetadata + HasLastReportTime + Stoppable + MaybeHasClientPerfMonitor, + I: Input, SP: ShMemProvider, { fn maybe_report_progress( @@ -371,7 +357,7 @@ where } } -impl HasEventManagerId for CentralizedEventManager +impl HasEventManagerId for CentralizedEventManager where EM: HasEventManagerId, SP: ShMemProvider, @@ -381,7 +367,7 @@ where } } -impl CentralizedEventManager +impl CentralizedEventManager where SP: ShMemProvider, { @@ -402,19 +388,16 @@ where } } -impl CentralizedEventManager +impl CentralizedEventManager where - EM: HasEventManagerId + EventFirer<::Input, S>, - EMH: EventManagerHooksTuple<::Input, S>, - S: HasCorpus + Stoppable, - ::Input: Input, + EM: HasEventManagerId + EventFirer, + EMH: EventManagerHooksTuple, + S: Stoppable, + I: Input, SP: ShMemProvider, { #[cfg(feature = "llmp_compression")] - fn forward_to_main(&mut self, event: &Event) -> Result<(), Error> - where - I: Input, - { + fn forward_to_main(&mut self, event: &Event) -> Result<(), Error> { let serialized = postcard::to_allocvec(event)?; let flags = LLMP_FLAG_INITIALIZED; @@ -434,10 +417,7 @@ where } #[cfg(not(feature = "llmp_compression"))] - fn forward_to_main(&mut self, event: &Event) -> Result<(), Error> - where - I: Input, - { + fn forward_to_main(&mut self, event: &Event) -> Result<(), Error> { let serialized = postcard::to_allocvec(event)?; self.client.send_buf(_LLMP_TAG_TO_MAIN, &serialized)?; Ok(()) @@ -452,8 +432,7 @@ where where E: HasObservers, E::Observers: DeserializeOwned, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + Z: ExecutionProcessor + EvaluatorObservers, { // TODO: Get around local event copy by moving handle_in_client let self_id = self.client.sender().id(); @@ -478,7 +457,7 @@ where } else { msg }; - let event: Event<::Input> = postcard::from_bytes(event_bytes)?; + let event: Event = 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; @@ -493,13 +472,12 @@ where executor: &mut E, state: &mut S, client_id: ClientId, - event: Event<::Input>, + event: Event, ) -> Result<(), Error> where E: HasObservers, E::Observers: DeserializeOwned, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + Z: ExecutionProcessor + EvaluatorObservers, { log::debug!("handle_in_main!"); @@ -594,14 +572,3 @@ where Ok(()) } } - -/* -impl Drop for CentralizedEventManager -where - EM: UsesState, SP: ShMemProvider + 'static, -{ - /// LLMP clients will have to wait until their pages are mapped by somebody. - fn drop(&mut self) { - self.await_restart_safe(); - } -}*/ diff --git a/libafl/src/events/launcher.rs b/libafl/src/events/launcher.rs index ea66e4aeff..5fb4695bfa 100644 --- a/libafl/src/events/launcher.rs +++ b/libafl/src/events/launcher.rs @@ -51,14 +51,12 @@ 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::HasCorpus, Error, }; @@ -214,15 +212,15 @@ where { /// Launch the broker and the clients and fuzz #[cfg(any(windows, not(feature = "fork"), all(unix, feature = "fork")))] - pub fn launch(&mut self) -> Result<(), Error> + pub fn launch(&mut self) -> Result<(), Error> where - S: DeserializeOwned + HasCorpus + Serialize, - ::Input: DeserializeOwned, CF: FnOnce( Option, - LlmpRestartingEventManager<(), S, SP>, + LlmpRestartingEventManager<(), I, S, SP>, ClientDescription, ) -> Result<(), Error>, + I: DeserializeOwned, + S: DeserializeOwned + Serialize, { Self::launch_with_hooks(self, tuple_list!()) } @@ -235,14 +233,14 @@ where { /// Launch the broker and the clients and fuzz with a user-supplied hook #[cfg(all(unix, feature = "fork"))] - pub fn launch_with_hooks(&mut self, hooks: EMH) -> Result<(), Error> + pub fn launch_with_hooks(&mut self, hooks: EMH) -> Result<(), Error> where - S: DeserializeOwned + HasCorpus + Serialize, - ::Input: DeserializeOwned, - EMH: EventManagerHooksTuple<::Input, S> + Clone + Copy, + S: DeserializeOwned + Serialize, + I: DeserializeOwned, + EMH: EventManagerHooksTuple + Clone + Copy, CF: FnOnce( Option, - LlmpRestartingEventManager, + LlmpRestartingEventManager, ClientDescription, ) -> Result<(), Error>, { @@ -314,7 +312,7 @@ where ClientDescription::new(index, overcommit_id, bind_to); // Fuzzer client. keeps retrying the connection to broker till the broker starts - let builder = RestartingMgr::::builder() + let builder = RestartingMgr::::builder() .shmem_provider(self.shmem_provider.clone()) .broker_port(self.broker_port) .kind(ManagerKind::Client { @@ -341,7 +339,7 @@ where log::info!("I am broker!!."); // TODO we don't want always a broker here, think about using different laucher process to spawn different configurations - let builder = RestartingMgr::::builder() + let builder = RestartingMgr::::builder() .shmem_provider(self.shmem_provider.clone()) .monitor(Some(self.monitor.clone())) .broker_port(self.broker_port) @@ -383,18 +381,18 @@ where /// Launch the broker and the clients and fuzz #[cfg(any(windows, not(feature = "fork")))] #[expect(clippy::too_many_lines, clippy::match_wild_err_arm)] - pub fn launch_with_hooks(&mut self, hooks: EMH) -> Result<(), Error> + pub fn launch_with_hooks(&mut self, hooks: EMH) -> Result<(), Error> where - S: DeserializeOwned + HasCorpus + Serialize, - ::Input: DeserializeOwned, - EMH: EventManagerHooksTuple<::Input, S> + Clone + Copy, CF: FnOnce( Option, - LlmpRestartingEventManager, + LlmpRestartingEventManager, ClientDescription, ) -> Result<(), Error>, + EMH: EventManagerHooksTuple + Clone + Copy, + I: DeserializeOwned, + S: DeserializeOwned + Serialize, { - use libafl_bolts::core_affinity; + use libafl_bolts::core_affinity::get_core_ids; let is_client = std::env::var(_AFL_LAUNCHER_CLIENT); @@ -403,7 +401,7 @@ where let client_description = ClientDescription::from_safe_string(&core_conf); // the actual client. do the fuzzing - let builder = RestartingMgr::::builder() + let builder = RestartingMgr::::builder() .shmem_provider(self.shmem_provider.clone()) .broker_port(self.broker_port) .kind(ManagerKind::Client { @@ -423,7 +421,7 @@ where // I am a broker // before going to the broker loop, spawn n clients - let core_ids = core_affinity::get_core_ids().unwrap(); + let core_ids = get_core_ids().unwrap(); let mut handles = vec![]; log::info!("spawning on cores: {:?}", self.cores); @@ -504,7 +502,7 @@ where if self.spawn_broker { log::info!("I am broker!!."); - let builder = RestartingMgr::::builder() + let builder = RestartingMgr::::builder() .shmem_provider(self.shmem_provider.clone()) .monitor(Some(self.monitor.clone())) .broker_port(self.broker_port) @@ -622,7 +620,7 @@ impl Debug for CentralizedLauncher<'_, CF, MF, MT, SP> { } /// The standard inner manager of centralized -pub type StdCentralizedInnerMgr = LlmpRestartingEventManager<(), S, SP>; +pub type StdCentralizedInnerMgr = LlmpRestartingEventManager<(), I, S, SP>; #[cfg(all(unix, feature = "fork"))] impl CentralizedLauncher<'_, CF, MF, MT, SP> @@ -631,25 +629,25 @@ where SP: ShMemProvider + 'static, { /// Launch a standard Centralized-based fuzzer - pub fn launch(&mut self) -> Result<(), Error> + pub fn launch(&mut self) -> Result<(), Error> where - S: DeserializeOwned + HasCorpus + Serialize, - ::Input: DeserializeOwned + Input + Send + Sync + 'static, + S: DeserializeOwned + Serialize, + I: DeserializeOwned + Input + Send + Sync + 'static, CF: FnOnce( Option, - CentralizedEventManager, (), S, SP>, + CentralizedEventManager, (), I, S, SP>, ClientDescription, ) -> Result<(), Error>, MF: FnOnce( Option, - CentralizedEventManager, (), S, SP>, + CentralizedEventManager, (), I, S, SP>, ClientDescription, ) -> Result<(), Error>, { let restarting_mgr_builder = |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() + let builder = RestartingMgr::<(), I, MT, S, SP>::builder() .shmem_provider(centralized_launcher.shmem_provider.clone()) .broker_port(centralized_launcher.broker_port) .kind(ManagerKind::Client { client_description }) @@ -675,23 +673,22 @@ where /// Launch a Centralized-based fuzzer. /// - `main_inner_mgr_builder` will be called to build the inner manager of the main node. /// - `secondary_inner_mgr_builder` will be called to build the inner manager of the secondary nodes. - pub fn launch_generic( + pub fn launch_generic( &mut self, main_inner_mgr_builder: EMB, secondary_inner_mgr_builder: EMB, ) -> Result<(), Error> where - S: HasCorpus, - ::Input: Input + Send + Sync + 'static, + I: Input + Send + Sync + 'static, CF: FnOnce( Option, - CentralizedEventManager, + CentralizedEventManager, ClientDescription, ) -> Result<(), Error>, EMB: FnOnce(&Self, ClientDescription) -> Result<(Option, EM), Error>, MF: FnOnce( Option, - CentralizedEventManager, // No broker_hooks for centralized EM + CentralizedEventManager, // No broker_hooks for centralized EM ClientDescription, ) -> Result<(), Error>, { @@ -835,7 +832,7 @@ where } = unsafe { TcpMultiMachineHooks::builder() .node_descriptor(self.multi_machine_node_descriptor.clone()) - .build::<::Input>()? + .build::()? }; let mut brokers = Brokers::new(); @@ -845,13 +842,12 @@ where brokers.add(Box::new({ #[cfg(feature = "multi_machine")] let centralized_hooks = tuple_list!( - CentralizedLlmpHook::<::Input>::new()?, + CentralizedLlmpHook::::new()?, multi_machine_receiver_hook, ); #[cfg(not(feature = "multi_machine"))] - let centralized_hooks = - tuple_list!(CentralizedLlmpHook::<::Input>::new()?); + let centralized_hooks = tuple_list!(CentralizedLlmpHook::::new()?); // TODO switch to false after solving the bug let mut broker = LlmpBroker::with_keep_pages_attach_to_tcp( @@ -875,13 +871,11 @@ where log::info!("I am broker!!."); #[cfg(not(feature = "multi_machine"))] - let llmp_hook = tuple_list!(StdLlmpEventHook::<::Input, MT>::new( - self.monitor.clone() - )?); + let llmp_hook = tuple_list!(StdLlmpEventHook::::new(self.monitor.clone())?); #[cfg(feature = "multi_machine")] let llmp_hook = tuple_list!( - StdLlmpEventHook::<::Input, MT>::new(self.monitor.clone())?, + StdLlmpEventHook::::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 b1cad00989..8cf5379f47 100644 --- a/libafl/src/events/llmp/mgr.rs +++ b/libafl/src/events/llmp/mgr.rs @@ -34,7 +34,6 @@ 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}, std_maybe_report_progress, std_on_restart, std_report_progress, AdaptiveSerializer, Event, @@ -47,8 +46,8 @@ use crate::{ observers::TimeObserver, stages::HasCurrentStageId, state::{ - HasCorpus, HasExecutions, HasImported, HasLastReportTime, MaybeHasClientPerfMonitor, - NopState, Stoppable, + HasExecutions, HasImported, HasLastReportTime, MaybeHasClientPerfMonitor, NopState, + Stoppable, }, Error, HasMetadata, }; @@ -58,7 +57,7 @@ const INITIAL_EVENT_BUFFER_SIZE: usize = 1024 * 4; /// 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 +pub struct LlmpEventManager where SP: ShMemProvider, { @@ -80,11 +79,11 @@ where serializations_cnt: usize, should_serialize_cnt: usize, pub(crate) time_ref: Option>, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, event_buffer: Vec, } -impl LlmpEventManager<(), NopState, NopShMemProvider> { +impl LlmpEventManager<(), NopState, NopInput, NopShMemProvider> { /// Creates a builder for [`LlmpEventManager`] #[must_use] pub fn builder() -> LlmpEventManagerBuilder<()> { @@ -133,12 +132,12 @@ impl LlmpEventManagerBuilder { } /// Create a manager from a raw LLMP client - pub fn build_from_client( + pub fn build_from_client( self, llmp: LlmpClient, configuration: EventConfig, time_ref: Option>, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, { @@ -163,13 +162,13 @@ impl LlmpEventManagerBuilder { /// Create an LLMP event manager on a port. /// It expects a broker to exist on this port. #[cfg(feature = "std")] - pub fn build_on_port( + pub fn build_on_port( self, shmem_provider: SP, port: u16, configuration: EventConfig, time_ref: Option>, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, { @@ -180,13 +179,13 @@ impl LlmpEventManagerBuilder { /// 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, configuration: EventConfig, time_ref: Option>, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, { @@ -195,13 +194,13 @@ impl LlmpEventManagerBuilder { } /// Create an existing client from description - pub fn build_existing_client_from_description( + pub fn build_existing_client_from_description( self, shmem_provider: SP, description: &LlmpClientDescription, configuration: EventConfig, time_ref: Option>, - ) -> Result, Error> + ) -> Result, Error> where SP: ShMemProvider, { @@ -211,7 +210,7 @@ impl LlmpEventManagerBuilder { } #[cfg(feature = "std")] -impl CanSerializeObserver for LlmpEventManager +impl CanSerializeObserver for LlmpEventManager where SP: ShMemProvider, OT: Serialize + MatchNameRef, @@ -221,7 +220,7 @@ where } } -impl AdaptiveSerializer for LlmpEventManager +impl AdaptiveSerializer for LlmpEventManager where SP: ShMemProvider, { @@ -256,7 +255,7 @@ where } } -impl core::fmt::Debug for LlmpEventManager +impl core::fmt::Debug for LlmpEventManager where SP: ShMemProvider, { @@ -273,7 +272,7 @@ where } } -impl Drop for LlmpEventManager +impl Drop for LlmpEventManager where SP: ShMemProvider, { @@ -283,7 +282,7 @@ where } } -impl LlmpEventManager +impl LlmpEventManager where SP: ShMemProvider, { @@ -333,7 +332,7 @@ where } } -impl LlmpEventManager +impl LlmpEventManager where SP: ShMemProvider, { @@ -344,16 +343,15 @@ where executor: &mut E, state: &mut S, client_id: ClientId, - event: Event<::Input>, + event: Event, ) -> Result<(), Error> where - S: HasCorpus + HasImported + Stoppable, - EMH: EventManagerHooksTuple<::Input, S>, - ::Input: Input, + S: HasImported + Stoppable, + EMH: EventManagerHooksTuple, + I: Input, E: HasObservers, E::Observers: DeserializeOwned, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + Z: ExecutionProcessor + EvaluatorObservers, { log::trace!("Got event in client: {} from {client_id:?}", event.name()); if !self.hooks.pre_exec_all(state, client_id, &event)? { @@ -409,7 +407,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. @@ -418,7 +416,7 @@ impl LlmpEventManager { } } -impl EventFirer for LlmpEventManager +impl EventFirer for LlmpEventManager where I: Serialize, SP: ShMemProvider, @@ -482,7 +480,7 @@ where } } -impl EventRestarter for LlmpEventManager +impl EventRestarter for LlmpEventManager where SP: ShMemProvider, S: HasCurrentStageId, @@ -492,7 +490,7 @@ where } } -impl ManagerExit for LlmpEventManager +impl ManagerExit for LlmpEventManager where SP: ShMemProvider, { @@ -508,16 +506,15 @@ where } } -impl EventProcessor for LlmpEventManager +impl EventProcessor for LlmpEventManager where E: HasObservers, E::Observers: DeserializeOwned, - S: HasCorpus + HasImported + Stoppable, - EMH: EventManagerHooksTuple<::Input, S>, - ::Input: DeserializeOwned + Input, + S: HasImported + Stoppable, + EMH: EventManagerHooksTuple, + I: DeserializeOwned + Input, SP: ShMemProvider, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + Z: ExecutionProcessor + EvaluatorObservers, { 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 @@ -543,7 +540,7 @@ where } else { msg }; - let event: Event<::Input> = postcard::from_bytes(event_bytes)?; + let event: Event = postcard::from_bytes(event_bytes)?; log::debug!("Received event in normal llmp {}", event.name_detailed()); // If the message comes from another machine, do not @@ -563,11 +560,11 @@ where } } -impl ProgressReporter for LlmpEventManager +impl ProgressReporter for LlmpEventManager where - S: HasExecutions + HasLastReportTime + HasMetadata + HasCorpus + MaybeHasClientPerfMonitor, + S: HasExecutions + HasLastReportTime + HasMetadata + MaybeHasClientPerfMonitor, SP: ShMemProvider, - ::Input: Serialize, + I: Serialize, { fn maybe_report_progress( &mut self, @@ -582,7 +579,7 @@ where } } -impl HasEventManagerId for LlmpEventManager +impl HasEventManagerId for LlmpEventManager where SP: ShMemProvider, { diff --git a/libafl/src/events/llmp/mod.rs b/libafl/src/events/llmp/mod.rs index 07be48a666..2d76ba52dd 100644 --- a/libafl/src/events/llmp/mod.rs +++ b/libafl/src/events/llmp/mod.rs @@ -15,11 +15,10 @@ use libafl_bolts::{ use serde::{de::DeserializeOwned, Serialize}; use crate::{ - corpus::Corpus, events::{Event, EventFirer}, fuzzer::EvaluatorObservers, inputs::{Input, InputConverter, NopInput, NopInputConverter}, - state::{HasCorpus, NopState}, + state::NopState, Error, }; @@ -83,7 +82,7 @@ impl LlmpShouldSaveState { } /// A manager-like llmp client that converts between input types -pub struct LlmpEventConverter +pub struct LlmpEventConverter where SP: ShMemProvider, { @@ -94,11 +93,12 @@ where compressor: GzipCompressor, converter: Option, converter_back: Option, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } impl LlmpEventConverter< + NopInput, NopInputConverter, NopInputConverter, NopState, @@ -134,12 +134,12 @@ 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, { @@ -157,13 +157,13 @@ 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, { @@ -182,13 +182,13 @@ 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, { @@ -206,11 +206,11 @@ impl LlmpEventConverterBuilder { } } -impl Debug for LlmpEventConverter +impl Debug for LlmpEventConverter where SP: ShMemProvider, - ICB: Debug, IC: Debug, + ICB: Debug, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut debug_struct = f.debug_struct("LlmpEventConverter"); @@ -226,9 +226,8 @@ where } } -impl LlmpEventConverter +impl LlmpEventConverter where - S: HasCorpus, SP: ShMemProvider, { // TODO other new_* routines @@ -265,8 +264,8 @@ where event: Event, ) -> Result<(), Error> where - ICB: InputConverter::Input, From = DI>, - Z: EvaluatorObservers::Input, S>, + ICB: InputConverter, + Z: EvaluatorObservers, { match event { Event::NewTestcase { @@ -308,9 +307,9 @@ where manager: &mut EM, ) -> Result where - ICB: InputConverter::Input, From = DI>, + ICB: InputConverter, DI: DeserializeOwned + Input, - Z: EvaluatorObservers::Input, S>, + Z: EvaluatorObservers, { // TODO: Get around local event copy by moving handle_in_client let self_id = self.llmp.sender().id(); @@ -345,11 +344,9 @@ where } } -impl EventFirer<::Input, S> - for LlmpEventConverter +impl EventFirer for LlmpEventConverter where - IC: InputConverter::Input>, - S: HasCorpus, + IC: InputConverter, SP: ShMemProvider, IC::To: Serialize, { @@ -362,11 +359,7 @@ where } #[cfg(feature = "llmp_compression")] - fn fire( - &mut self, - _state: &mut S, - event: Event<::Input>, - ) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { if self.converter.is_none() { return Ok(()); } @@ -418,11 +411,7 @@ where } #[cfg(not(feature = "llmp_compression"))] - fn fire( - &mut self, - _state: &mut S, - event: Event<::Input>, - ) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S, event: Event) -> 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 1bc1fcd8cb..8c8d5f31b3 100644 --- a/libafl/src/events/llmp/restarting.rs +++ b/libafl/src/events/llmp/restarting.rs @@ -33,7 +33,6 @@ use typed_builder::TypedBuilder; use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::{ common::HasMetadata, - corpus::Corpus, events::{ launcher::ClientDescription, serialize_observers_adaptive, std_maybe_report_progress, std_report_progress, AdaptiveSerializer, CanSerializeObserver, Event, EventConfig, @@ -47,28 +46,25 @@ use crate::{ monitors::Monitor, observers::TimeObserver, stages::HasCurrentStageId, - state::{ - HasCorpus, HasExecutions, HasImported, HasLastReportTime, MaybeHasClientPerfMonitor, - Stoppable, - }, + state::{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 +pub struct LlmpRestartingEventManager where SP: ShMemProvider, { /// The embedded LLMP event manager - llmp_mgr: LlmpEventManager, + llmp_mgr: LlmpEventManager, /// The staterestorer to serialize the state for the next runner staterestorer: StateRestorer, /// Decide if the state restorer must save the serialized state save_state: LlmpShouldSaveState, } -impl AdaptiveSerializer for LlmpRestartingEventManager +impl AdaptiveSerializer for LlmpRestartingEventManager where SP: ShMemProvider, { @@ -103,16 +99,11 @@ where } } -impl ProgressReporter for LlmpRestartingEventManager +impl ProgressReporter for LlmpRestartingEventManager where - S: HasExecutions - + HasLastReportTime - + HasMetadata - + HasCorpus - + Serialize - + MaybeHasClientPerfMonitor, + S: HasExecutions + HasLastReportTime + HasMetadata + Serialize + MaybeHasClientPerfMonitor, SP: ShMemProvider, - ::Input: Serialize, + I: Serialize, { fn maybe_report_progress( &mut self, @@ -127,14 +118,14 @@ where } } -impl EventFirer for LlmpRestartingEventManager +impl EventFirer for LlmpRestartingEventManager where I: Serialize, - S: HasCorpus + Serialize, + S: Serialize, SP: ShMemProvider, { fn should_send(&self) -> bool { - as EventFirer>::should_send(&self.llmp_mgr) + as EventFirer>::should_send(&self.llmp_mgr) } fn fire(&mut self, state: &mut S, event: Event) -> Result<(), Error> { @@ -145,12 +136,12 @@ where } fn configuration(&self) -> EventConfig { - as EventFirer>::configuration(&self.llmp_mgr) + as EventFirer>::configuration(&self.llmp_mgr) } } #[cfg(feature = "std")] -impl CanSerializeObserver for LlmpRestartingEventManager +impl CanSerializeObserver for LlmpRestartingEventManager where SP: ShMemProvider, OT: Serialize + MatchNameRef, @@ -160,7 +151,7 @@ where } } -impl EventRestarter for LlmpRestartingEventManager +impl EventRestarter for LlmpRestartingEventManager where SP: ShMemProvider, S: Serialize + HasCurrentStageId, @@ -186,7 +177,7 @@ where } } -impl ManagerExit for LlmpRestartingEventManager +impl ManagerExit for LlmpRestartingEventManager where SP: ShMemProvider, { @@ -205,21 +196,16 @@ where } } -impl EventProcessor for LlmpRestartingEventManager +impl EventProcessor for LlmpRestartingEventManager where - EMH: EventManagerHooksTuple<::Input, S>, + EMH: EventManagerHooksTuple, E: HasObservers, E::Observers: DeserializeOwned, - S: HasCorpus + HasImported + Stoppable + Serialize, - ::Input: DeserializeOwned + Input, - S::Corpus: Serialize, + S: HasImported + Stoppable + Serialize, + I: DeserializeOwned + Input, SP: ShMemProvider, - Z: ExecutionProcessor< - LlmpEventManager, - ::Input, - E::Observers, - S, - > + EvaluatorObservers, ::Input, S>, + Z: ExecutionProcessor, I, E::Observers, S> + + EvaluatorObservers, I, S>, { fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { let res = self.llmp_mgr.process(fuzzer, state, executor)?; @@ -232,7 +218,7 @@ where } } -impl HasEventManagerId for LlmpRestartingEventManager +impl HasEventManagerId for LlmpRestartingEventManager where SP: ShMemProvider, { @@ -247,13 +233,16 @@ const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER"; /// The llmp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages) const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT"; -impl LlmpRestartingEventManager +impl LlmpRestartingEventManager where SP: ShMemProvider, S: Serialize, { /// Create a new runner, the executed child doing the actual fuzzing. - pub fn new(llmp_mgr: LlmpEventManager, staterestorer: StateRestorer) -> Self { + pub fn new( + llmp_mgr: LlmpEventManager, + staterestorer: StateRestorer, + ) -> Self { Self { llmp_mgr, staterestorer, @@ -263,7 +252,7 @@ where /// Create a new runner specifying if it must save the serialized state on restart. pub fn with_save_state( - llmp_mgr: LlmpEventManager, + llmp_mgr: LlmpEventManager, staterestorer: StateRestorer, save_state: LlmpShouldSaveState, ) -> Self { @@ -315,21 +304,21 @@ pub enum ManagerKind { /// The restarting mgr is a combination of restarter and runner, that can be used on systems with and without `fork` support. /// The restarter will spawn a new process each time the child crashes or timeouts. #[expect(clippy::type_complexity)] -pub fn setup_restarting_mgr_std( +pub fn setup_restarting_mgr_std( monitor: MT, broker_port: u16, configuration: EventConfig, ) -> Result< ( Option, - LlmpRestartingEventManager<(), S, StdShMemProvider>, + LlmpRestartingEventManager<(), I, S, StdShMemProvider>, ), Error, > where MT: Monitor + Clone, - S: HasCorpus + Serialize + DeserializeOwned, - ::Input: DeserializeOwned, + S: Serialize + DeserializeOwned, + I: DeserializeOwned, { RestartingMgr::builder() .shmem_provider(StdShMemProvider::new()?) @@ -347,7 +336,7 @@ where /// The restarter will spawn a new process each time the child crashes or timeouts. /// This one, additionally uses the timeobserver for the adaptive serialization #[expect(clippy::type_complexity)] -pub fn setup_restarting_mgr_std_adaptive( +pub fn setup_restarting_mgr_std_adaptive( monitor: MT, broker_port: u16, configuration: EventConfig, @@ -355,14 +344,14 @@ pub fn setup_restarting_mgr_std_adaptive( ) -> Result< ( Option, - LlmpRestartingEventManager<(), S, StdShMemProvider>, + LlmpRestartingEventManager<(), I, S, StdShMemProvider>, ), Error, > where MT: Monitor + Clone, - S: HasCorpus + Serialize + DeserializeOwned, - ::Input: DeserializeOwned, + S: Serialize + DeserializeOwned, + I: DeserializeOwned, { RestartingMgr::builder() .shmem_provider(StdShMemProvider::new()?) @@ -381,7 +370,7 @@ where /// `restarter` and `runner`, that can be used on systems both with and without `fork` support. The /// `restarter` will start a new process each time the child crashes or times out. #[derive(TypedBuilder, Debug)] -pub struct RestartingMgr { +pub struct RestartingMgr { /// The shared memory provider to use for the broker or client spawned by the restarting /// manager. shmem_provider: SP, @@ -415,20 +404,22 @@ pub struct RestartingMgr { #[builder(default = None)] time_ref: Option>, #[builder(setter(skip), default = PhantomData)] - phantom_data: PhantomData<(EMH, S)>, + phantom_data: PhantomData<(EMH, I, S)>, } #[expect(clippy::type_complexity, clippy::too_many_lines)] -impl RestartingMgr +impl RestartingMgr where - EMH: EventManagerHooksTuple<::Input, S> + Copy + Clone, + EMH: EventManagerHooksTuple + Copy + Clone, SP: ShMemProvider, - S: HasCorpus + Serialize + DeserializeOwned, - ::Input: DeserializeOwned, + S: Serialize + DeserializeOwned, + I: DeserializeOwned, MT: Monitor + Clone, { /// Launch the broker and the clients and fuzz - pub fn launch(&mut self) -> Result<(Option, LlmpRestartingEventManager), Error> { + pub fn launch( + &mut self, + ) -> Result<(Option, LlmpRestartingEventManager), Error> { // We start ourselves as child process to actually fuzz let (staterestorer, new_shmem_provider, core_id) = if std::env::var(_ENV_FUZZER_SENDER) .is_err() @@ -458,9 +449,7 @@ where match connection { LlmpConnection::IsBroker { broker } => { let llmp_hook = - StdLlmpEventHook::<::Input, MT>::new( - self.monitor.take().unwrap(), - )?; + StdLlmpEventHook::::new(self.monitor.take().unwrap())?; // Yep, broker. Just loop here. log::info!( @@ -475,7 +464,7 @@ where return Err(Error::shutting_down()); } LlmpConnection::IsClient { client } => { - let mgr: LlmpEventManager = LlmpEventManager::builder() + let mgr: LlmpEventManager = LlmpEventManager::builder() .hooks(self.hooks) .build_from_client( client, diff --git a/libafl/src/events/mod.rs b/libafl/src/events/mod.rs index f7cbca659c..c89909d555 100644 --- a/libafl/src/events/mod.rs +++ b/libafl/src/events/mod.rs @@ -45,11 +45,10 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ - corpus::Corpus, executors::ExitKind, inputs::Input, monitors::UserStats, - state::{HasCorpus, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor}, + state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor}, Error, HasMetadata, }; @@ -489,10 +488,10 @@ where /// 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> +pub fn std_report_progress(reporter: &mut EM, state: &mut S) -> Result<(), Error> where - EM: EventFirer<::Input, S>, - S: HasExecutions + HasLastReportTime + HasCorpus + MaybeHasClientPerfMonitor, + EM: EventFirer, + S: HasExecutions + HasLastReportTime + MaybeHasClientPerfMonitor, { let executions = *state.executions(); let cur = current_time(); diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index 44ad11ccd7..475517be4b 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -22,7 +22,6 @@ use super::{std_on_restart, ProgressReporter}; #[cfg(all(unix, feature = "std", not(miri)))] use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::{ - corpus::Corpus, events::{ std_maybe_report_progress, std_report_progress, BrokerEventResult, CanSerializeObserver, Event, EventFirer, EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, @@ -30,7 +29,7 @@ use crate::{ }, monitors::Monitor, stages::HasCurrentStageId, - state::{HasCorpus, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable}, + state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable}, Error, HasMetadata, }; #[cfg(feature = "std")] @@ -141,13 +140,7 @@ impl ProgressReporter for SimpleEventManager where I: Debug, MT: Monitor, - S: HasMetadata - + HasExecutions - + HasLastReportTime - + Stoppable - + HasCorpus - + MaybeHasClientPerfMonitor, - S::Corpus: Corpus, + S: HasMetadata + HasExecutions + HasLastReportTime + Stoppable + MaybeHasClientPerfMonitor, { fn maybe_report_progress( &mut self, @@ -383,13 +376,7 @@ where I: Debug, MT: Monitor, SP: ShMemProvider, - S: HasExecutions - + HasMetadata - + HasLastReportTime - + Stoppable - + HasCorpus - + MaybeHasClientPerfMonitor, - S::Corpus: Corpus, + S: HasExecutions + HasMetadata + HasLastReportTime + Stoppable + MaybeHasClientPerfMonitor, { fn maybe_report_progress( &mut self, @@ -435,7 +422,7 @@ where /// 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 - S: DeserializeOwned + Serialize + HasCorpus + HasSolutions, + S: DeserializeOwned + Serialize + HasSolutions, MT: Debug, { // We start ourself as child process to actually fuzz diff --git a/libafl/src/events/tcp.rs b/libafl/src/events/tcp.rs index 69e16ccc72..cbb7b4e932 100644 --- a/libafl/src/events/tcp.rs +++ b/libafl/src/events/tcp.rs @@ -42,7 +42,6 @@ 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::{ std_on_restart, BrokerEventResult, Event, EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, ProgressReporter, @@ -53,10 +52,7 @@ use crate::{ monitors::Monitor, observers::ObserversTuple, stages::HasCurrentStageId, - state::{ - HasCorpus, HasExecutions, HasImported, HasLastReportTime, MaybeHasClientPerfMonitor, - Stoppable, - }, + state::{HasExecutions, HasImported, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable}, Error, HasMetadata, }; @@ -409,7 +405,7 @@ where } /// An `EventManager` that forwards all events to other attached via tcp. -pub struct TcpEventManager { +pub struct TcpEventManager { /// We send message every `throttle` second throttle: Option, /// When we sent the last message @@ -425,32 +421,32 @@ pub struct TcpEventManager { /// A node will not re-use the observer values sent over TCP /// from nodes with other configurations. configuration: EventConfig, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl TcpEventManager<(), S> { +impl TcpEventManager<(), I, S> { /// Create a builder for [`TcpEventManager`] #[must_use] - pub fn builder() -> TcpEventManagerBuilder<(), S> { + pub fn builder() -> TcpEventManagerBuilder<(), I, S> { TcpEventManagerBuilder::new() } } /// Builder for `TcpEventManager` #[derive(Debug, Copy, Clone)] -pub struct TcpEventManagerBuilder { +pub struct TcpEventManagerBuilder { throttle: Option, hooks: EMH, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl Default for TcpEventManagerBuilder<(), S> { +impl Default for TcpEventManagerBuilder<(), I, S> { fn default() -> Self { Self::new() } } -impl TcpEventManagerBuilder<(), S> { +impl TcpEventManagerBuilder<(), I, S> { /// Set the constructor #[must_use] pub fn new() -> Self { @@ -463,7 +459,7 @@ impl TcpEventManagerBuilder<(), S> { /// Set the hooks #[must_use] - pub fn hooks(self, hooks: EMH) -> TcpEventManagerBuilder { + pub fn hooks(self, hooks: EMH) -> TcpEventManagerBuilder { TcpEventManagerBuilder { throttle: self.throttle, hooks, @@ -472,7 +468,7 @@ impl TcpEventManagerBuilder<(), S> { } } -impl TcpEventManagerBuilder { +impl TcpEventManagerBuilder { /// Set the throttle #[must_use] pub fn throttle(mut self, throttle: Duration) -> Self { @@ -486,7 +482,7 @@ impl TcpEventManagerBuilder { addr: &A, client_id: ClientId, configuration: EventConfig, - ) -> Result, Error> { + ) -> Result, Error> { let mut tcp = TcpStream::connect(addr)?; let mut our_client_id_buf = client_id.0.to_le_bytes(); @@ -521,7 +517,7 @@ impl TcpEventManagerBuilder { port: u16, client_id: ClientId, configuration: EventConfig, - ) -> Result, Error> { + ) -> Result, Error> { Self::build_from_client(self, &("127.0.0.1", port), client_id, configuration) } @@ -534,13 +530,13 @@ impl TcpEventManagerBuilder { addr: &A, env_name: &str, configuration: EventConfig, - ) -> Result, Error> { + ) -> Result, Error> { let this_id = ClientId(str::parse::(&env::var(env_name)?)?); Self::build_from_client(self, addr, this_id, configuration) } } -impl core::fmt::Debug for TcpEventManager { +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); @@ -554,17 +550,17 @@ impl core::fmt::Debug for TcpEventManager { } } -impl Drop for TcpEventManager { +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(); } } -impl TcpEventManager +impl TcpEventManager where - EMH: EventManagerHooksTuple<::Input, S>, - S: HasExecutions + HasMetadata + HasImported + HasCorpus + Stoppable, + EMH: EventManagerHooksTuple, + S: HasExecutions + HasMetadata + HasImported + Stoppable, { /// Write the client id for a client `EventManager` to env vars pub fn to_env(&self, env_name: &str) { @@ -578,14 +574,13 @@ where executor: &mut E, state: &mut S, client_id: ClientId, - event: Event<::Input>, + event: Event, ) -> Result<(), Error> where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: Serialize + ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: Serialize + ObserversTuple, for<'a> E::Observers: Deserialize<'a>, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + Z: ExecutionProcessor + EvaluatorObservers, { if !self.hooks.pre_exec_all(state, client_id, &event)? { return Ok(()); @@ -630,7 +625,7 @@ where } } -impl TcpEventManager { +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. @@ -641,11 +636,10 @@ impl TcpEventManager { } } -impl EventFirer<::Input, S> for TcpEventManager +impl EventFirer for TcpEventManager where - EMH: EventManagerHooksTuple<::Input, S>, - S: HasCorpus, - ::Input: Serialize, + EMH: EventManagerHooksTuple, + I: Serialize, { fn should_send(&self) -> bool { if let Some(throttle) = self.throttle { @@ -655,11 +649,7 @@ where } } - fn fire( - &mut self, - _state: &mut S, - event: Event<::Input>, - ) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { let serialized = postcard::to_allocvec(&event)?; #[cfg(feature = "tcp_compression")] @@ -679,7 +669,7 @@ where } } -impl EventRestarter for TcpEventManager +impl EventRestarter for TcpEventManager where S: HasCurrentStageId, { @@ -688,16 +678,15 @@ where } } -impl EventProcessor for TcpEventManager +impl EventProcessor for TcpEventManager where - E: HasObservers + Executor::Input, S, Z>, - E::Observers: Serialize + ObserversTuple<::Input, S>, + E: HasObservers + Executor, + E::Observers: Serialize + ObserversTuple, for<'a> E::Observers: Deserialize<'a>, - EMH: EventManagerHooksTuple<::Input, S>, - S: HasExecutions + HasMetadata + HasImported + HasCorpus + Stoppable, - ::Input: DeserializeOwned, - Z: ExecutionProcessor::Input, E::Observers, S> - + EvaluatorObservers::Input, S>, + EMH: EventManagerHooksTuple, + S: HasExecutions + HasMetadata + HasImported + Stoppable, + I: DeserializeOwned, + Z: ExecutionProcessor + EvaluatorObservers, { 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 @@ -758,7 +747,7 @@ where } } -impl ManagerExit for TcpEventManager { +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) { @@ -773,11 +762,11 @@ impl ManagerExit for TcpEventManager { } } -impl ProgressReporter for TcpEventManager +impl ProgressReporter for TcpEventManager where - EMH: EventManagerHooksTuple<::Input, S>, - ::Input: Serialize, - S: HasExecutions + HasMetadata + HasLastReportTime + HasCorpus + MaybeHasClientPerfMonitor, + EMH: EventManagerHooksTuple, + I: Serialize, + S: HasExecutions + HasMetadata + HasLastReportTime + MaybeHasClientPerfMonitor, { fn maybe_report_progress( &mut self, @@ -792,7 +781,7 @@ where } } -impl HasEventManagerId for TcpEventManager { +impl HasEventManagerId for TcpEventManager { /// Gets the id assigned to this staterestorer. fn mgr_id(&self) -> EventManagerId { EventManagerId(self.client_id.0 as usize) @@ -801,23 +790,23 @@ impl HasEventManagerId for TcpEventManager { /// A manager that can restart on the fly, storing states in-between (in `on_restart`) #[derive(Debug)] -pub struct TcpRestartingEventManager +pub struct TcpRestartingEventManager where SP: ShMemProvider, { /// The embedded TCP event manager - tcp_mgr: TcpEventManager, + tcp_mgr: TcpEventManager, /// The staterestorer to serialize the state for the next runner staterestorer: StateRestorer, /// Decide if the state restorer must save the serialized state save_state: bool, } -impl ProgressReporter for TcpRestartingEventManager +impl ProgressReporter for TcpRestartingEventManager where - EMH: EventManagerHooksTuple<::Input, S>, - S: HasMetadata + HasExecutions + HasLastReportTime + HasCorpus + MaybeHasClientPerfMonitor, - ::Input: Serialize, + EMH: EventManagerHooksTuple, + S: HasMetadata + HasExecutions + HasLastReportTime + MaybeHasClientPerfMonitor, + I: Serialize, SP: ShMemProvider, { fn maybe_report_progress( @@ -833,23 +822,17 @@ where } } -impl EventFirer<::Input, S> - for TcpRestartingEventManager +impl EventFirer for TcpRestartingEventManager where - EMH: EventManagerHooksTuple<::Input, S>, - S: HasCorpus, - ::Input: Serialize, + EMH: EventManagerHooksTuple, + I: Serialize, SP: ShMemProvider, { fn should_send(&self) -> bool { self.tcp_mgr.should_send() } - fn fire( - &mut self, - state: &mut S, - event: Event<::Input>, - ) -> Result<(), Error> { + 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.tcp_mgr.fire(state, event) } @@ -859,7 +842,7 @@ where } } -impl ManagerExit for TcpRestartingEventManager +impl ManagerExit for TcpRestartingEventManager where SP: ShMemProvider, { @@ -878,10 +861,10 @@ where } } -impl EventRestarter for TcpRestartingEventManager +impl EventRestarter for TcpRestartingEventManager where - EMH: EventManagerHooksTuple<::Input, S>, - S: HasCorpus + HasExecutions + HasCurrentStageId + Serialize, + EMH: EventManagerHooksTuple, + S: 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. @@ -901,17 +884,17 @@ where } } -impl EventProcessor for TcpRestartingEventManager +impl EventProcessor for TcpRestartingEventManager where - E: HasObservers + Executor, ::Input, S, Z>, + E: HasObservers + Executor, I, S, Z>, for<'a> E::Observers: Deserialize<'a>, - E::Observers: ObserversTuple<::Input, S> + Serialize, - EMH: EventManagerHooksTuple<::Input, S>, - S: HasExecutions + HasMetadata + HasImported + HasCorpus + Stoppable, - ::Input: DeserializeOwned, + E::Observers: ObserversTuple + Serialize, + EMH: EventManagerHooksTuple, + I: DeserializeOwned, + S: HasExecutions + HasMetadata + HasImported + Stoppable, SP: ShMemProvider, - Z: ExecutionProcessor, ::Input, E::Observers, S> - + EvaluatorObservers, ::Input, S>, + Z: ExecutionProcessor, I, E::Observers, S> + + EvaluatorObservers, I, S>, { fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { self.tcp_mgr.process(fuzzer, state, executor) @@ -922,7 +905,7 @@ where } } -impl HasEventManagerId for TcpRestartingEventManager +impl HasEventManagerId for TcpRestartingEventManager where SP: ShMemProvider, { @@ -937,15 +920,13 @@ const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER"; /// The tcp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages) const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT"; -impl TcpRestartingEventManager +impl TcpRestartingEventManager where - EMH: EventManagerHooksTuple<::Input, S>, - S: HasCorpus, + EMH: EventManagerHooksTuple, SP: ShMemProvider, - //CE: CustomEvent, { /// Create a new runner, the executed child doing the actual fuzzing. - pub fn new(tcp_mgr: TcpEventManager, staterestorer: StateRestorer) -> Self { + pub fn new(tcp_mgr: TcpEventManager, staterestorer: StateRestorer) -> Self { Self { tcp_mgr, staterestorer, @@ -955,7 +936,7 @@ where /// Create a new runner specifying if it must save the serialized state on restart. pub fn with_save_state( - tcp_mgr: TcpEventManager, + tcp_mgr: TcpEventManager, staterestorer: StateRestorer, save_state: bool, ) -> Self { @@ -996,21 +977,21 @@ pub enum TcpManagerKind { /// The [`TcpRestartingEventManager`] is a combination of restarter and runner, that can be used on systems with and without `fork` support. /// The restarter will spawn a new process each time the child crashes or timeouts. #[expect(clippy::type_complexity)] -pub fn setup_restarting_mgr_tcp( +pub fn setup_restarting_mgr_tcp( monitor: MT, broker_port: u16, configuration: EventConfig, ) -> Result< ( Option, - TcpRestartingEventManager<(), S, StdShMemProvider>, + TcpRestartingEventManager<(), I, S, StdShMemProvider>, ), Error, > where MT: Monitor + Clone, - S: HasExecutions + HasMetadata + HasImported + HasCorpus + DeserializeOwned + Stoppable, - ::Input: Input, + S: HasExecutions + HasMetadata + HasImported + DeserializeOwned + Stoppable, + I: Input, { TcpRestartingMgr::builder() .shmem_provider(StdShMemProvider::new()?) @@ -1028,11 +1009,11 @@ where /// `restarter` and `runner`, that can be used on systems both with and without `fork` support. The /// `restarter` will start a new process each time the child crashes or times out. #[derive(TypedBuilder, Debug)] -pub struct TcpRestartingMgr +pub struct TcpRestartingMgr where + MT: Monitor, S: DeserializeOwned, SP: ShMemProvider + 'static, - MT: Monitor, { /// The shared memory provider to use for the broker or client spawned by the restarting /// manager. @@ -1065,25 +1046,26 @@ where /// The hooks for `handle_in_client` hooks: EMH, #[builder(setter(skip), default = PhantomData)] - phantom_data: PhantomData, + phantom_data: PhantomData<(I, S)>, } #[expect(clippy::type_complexity, clippy::too_many_lines)] -impl TcpRestartingMgr +impl TcpRestartingMgr where - EMH: EventManagerHooksTuple<::Input, S> + Copy + Clone, - SP: ShMemProvider, - S: HasExecutions + HasMetadata + HasImported + HasCorpus + DeserializeOwned + Stoppable, - ::Input: Input, + EMH: EventManagerHooksTuple + Copy + Clone, + I: Input, MT: Monitor + Clone, + SP: ShMemProvider, + S: HasExecutions + HasMetadata + HasImported + DeserializeOwned + Stoppable, { /// Launch the restarting manager - pub fn launch(&mut self) -> Result<(Option, TcpRestartingEventManager), Error> { + pub fn launch( + &mut self, + ) -> Result<(Option, TcpRestartingEventManager), Error> { // 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<::Input, MT>, - _remote_broker_addr| { + let broker_things = |mut broker: TcpEventBroker, _remote_broker_addr| { if let Some(exit_cleanly_after) = self.exit_cleanly_after { broker.set_exit_cleanly_after(exit_cleanly_after); } @@ -1097,11 +1079,10 @@ where let connection = create_nonblocking_listener(("127.0.0.1", self.broker_port)); match connection { Ok(listener) => { - let event_broker = - TcpEventBroker::<::Input, MT>::with_listener( - listener, - self.monitor.take().unwrap(), - ); + let event_broker = TcpEventBroker::::with_listener( + listener, + self.monitor.take().unwrap(), + ); // Yep, broker. Just loop here. log::info!( @@ -1129,7 +1110,7 @@ where } } TcpManagerKind::Broker => { - let event_broker = TcpEventBroker::<::Input, MT>::new( + let event_broker = TcpEventBroker::::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 e1bc56808d..f0eabc60b8 100644 --- a/libafl/src/executors/command.rs +++ b/libafl/src/executors/command.rs @@ -49,11 +49,10 @@ use super::HasTimeout; #[cfg(target_os = "linux")] use crate::executors::hooks::ExecutorHooksTuple; use crate::{ - corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, inputs::HasTargetBytes, observers::{ObserversTuple, StdErrObserver, StdOutObserver}, - state::{HasCorpus, HasExecutions}, + state::HasExecutions, std::borrow::ToOwned, Error, }; @@ -280,17 +279,16 @@ where /// /// Construct a `CommandExecutor` by implementing [`CommandConfigurator`] for a type of your choice and calling [`CommandConfigurator::into_executor`] on it. /// Instead, you can use [`CommandExecutor::builder()`] to construct a [`CommandExecutor`] backed by a [`StdCommandConfigurator`]. -pub struct CommandExecutor { +pub struct CommandExecutor { /// The wrapped command configurer configurer: T, /// The observers used by this executor observers: OT, hooks: HT, - phantom: PhantomData, - phantom_child: PhantomData, + phantom: PhantomData<(C, I, S)>, } -impl CommandExecutor<(), (), ()> { +impl CommandExecutor<(), (), (), ()> { /// Creates a builder for a new [`CommandExecutor`], /// backed by a [`StdCommandConfigurator`] /// This is usually the easiest way to construct a [`CommandExecutor`]. @@ -308,7 +306,7 @@ impl CommandExecutor<(), (), ()> { } } -impl Debug for CommandExecutor +impl Debug for CommandExecutor where T: Debug, OT: Debug, @@ -323,7 +321,7 @@ where } } -impl CommandExecutor { +impl CommandExecutor { /// Accesses the inner value pub fn inner(&mut self) -> &mut T { &mut self.configurer @@ -331,17 +329,13 @@ impl CommandExecutor { } // this only works on unix because of the reliance on checking the process signal for detecting OOM -impl CommandExecutor +impl CommandExecutor where - S: HasExecutions + HasCorpus, - T: CommandConfigurator<::Input> + Debug, - OT: ObserversTuple<::Input, S>, + S: HasExecutions, + T: CommandConfigurator + Debug, + OT: ObserversTuple, { - fn execute_input_with_command( - &mut self, - state: &mut S, - input: &::Input, - ) -> Result { + fn execute_input_with_command(&mut self, state: &mut S, input: &I) -> Result { use wait_timeout::ChildExt; *state.executions_mut() += 1; @@ -391,28 +385,27 @@ where } } -impl Executor::Input, S, Z> for CommandExecutor +impl Executor for CommandExecutor where - S: HasExecutions + HasCorpus, - T: CommandConfigurator<::Input> + Debug, - OT: MatchName + ObserversTuple<::Input, S>, + S: HasExecutions, + T: CommandConfigurator + Debug, + OT: MatchName + ObserversTuple, { fn run_target( &mut self, _fuzzer: &mut Z, state: &mut S, _mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { self.execute_input_with_command(state, input) } } // this only works on unix because of the reliance on checking the process signal for detecting OOM -impl HasTimeout for CommandExecutor +impl HasTimeout for CommandExecutor where - S: HasCorpus, - T: CommandConfigurator<::Input>, + T: CommandConfigurator, { #[inline] fn timeout(&self) -> Duration { @@ -426,13 +419,12 @@ where } #[cfg(target_os = "linux")] -impl Executor::Input, S, Z> - for CommandExecutor +impl Executor for CommandExecutor where - S: HasCorpus + HasExecutions, - T: CommandConfigurator<::Input, Pid> + Debug, - OT: MatchName + ObserversTuple<::Input, S>, - HT: ExecutorHooksTuple<::Input, S>, + HT: ExecutorHooksTuple, + OT: MatchName + ObserversTuple, + S: HasExecutions, + T: CommandConfigurator + Debug, { /// Linux specific low level implementation, to directly handle `fork`, `exec` and use linux /// `ptrace` @@ -444,7 +436,7 @@ where _fuzzer: &mut Z, state: &mut S, _mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { *state.executions_mut() += 1; @@ -502,10 +494,9 @@ where } } -impl HasObservers for CommandExecutor +impl HasObservers for CommandExecutor where - S: HasCorpus, - OT: ObserversTuple<::Input, S>, + OT: ObserversTuple, { type Observers = OT; @@ -683,14 +674,13 @@ impl CommandExecutorBuilder { } /// Builds the `CommandExecutor` - pub fn build( + pub fn build( &self, observers: OT, - ) -> Result, Error> + ) -> Result, Error> where - S: HasCorpus, - ::Input: HasTargetBytes, - OT: MatchName + ObserversTuple<::Input, S>, + I: HasTargetBytes, + OT: MatchName + ObserversTuple, { let Some(program) = &self.program else { return Err(Error::illegal_argument( @@ -737,9 +727,12 @@ impl CommandExecutorBuilder { timeout: self.timeout, command, }; - Ok(::Input, - >>::into_executor::(configurator, observers)) + Ok( + >::into_executor::( + configurator, + observers, + ), + ) } } @@ -747,7 +740,7 @@ impl CommandExecutorBuilder { /// # Example /// ``` /// use std::{io::Write, process::{Stdio, Command, Child}, time::Duration}; -/// use libafl::{Error, corpus::Corpus, inputs::{BytesInput, HasTargetBytes, Input}, executors::{Executor, command::CommandConfigurator}, state::{HasCorpus, HasExecutions}}; +/// use libafl::{Error, corpus::Corpus, inputs::{BytesInput, HasTargetBytes, Input}, executors::{Executor, command::CommandConfigurator}, state::{HasExecutions}}; /// use libafl_bolts::AsSlice; /// #[derive(Debug)] /// struct MyExecutor; @@ -779,8 +772,7 @@ impl CommandExecutorBuilder { /// /// fn make_executor() -> impl Executor /// where -/// S: HasCorpus + HasExecutions, -/// S::Corpus: Corpus +/// S: HasExecutions, /// { /// MyExecutor.into_executor(()) /// } @@ -816,13 +808,12 @@ pub trait CommandConfigurator: Sized { } /// Create an `Executor` from this `CommandConfigurator`. - fn into_executor(self, observers: OT) -> CommandExecutor { + fn into_executor(self, observers: OT) -> CommandExecutor { CommandExecutor { configurer: self, observers, hooks: (), phantom: PhantomData, - phantom_child: PhantomData, } } @@ -831,13 +822,12 @@ pub trait CommandConfigurator: Sized { self, observers: OT, hooks: HT, - ) -> CommandExecutor { + ) -> CommandExecutor { CommandExecutor { configurer: self, observers, hooks, phantom: PhantomData, - phantom_child: PhantomData, } } } @@ -890,7 +880,7 @@ mod tests { executor .run_target( &mut NopFuzzer::new(), - &mut NopState::new(), + &mut NopState::::new(), &mut mgr, &BytesInput::new(b"test".to_vec()), ) diff --git a/libafl/src/executors/differential.rs b/libafl/src/executors/differential.rs index b6a057def5..12f4a13f8d 100644 --- a/libafl/src/executors/differential.rs +++ b/libafl/src/executors/differential.rs @@ -19,23 +19,21 @@ use serde::{Deserialize, Serialize}; use super::HasTimeout; use crate::{ - corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, observers::{DifferentialObserversTuple, ObserversTuple}, - state::HasCorpus, Error, }; /// A [`DiffExecutor`] wraps a primary executor, forwarding its methods, and a secondary one #[derive(Debug)] -pub struct DiffExecutor { +pub struct DiffExecutor { primary: A, secondary: B, observers: UnsafeCell>, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl DiffExecutor { +impl DiffExecutor { /// Create a new `DiffExecutor`, wrapping the given `executor`s. pub fn new(primary: A, secondary: B, observers: DOT) -> Self { Self { @@ -61,23 +59,21 @@ impl DiffExecutor { } } -impl Executor::Input, S, Z> - for DiffExecutor +impl Executor + for DiffExecutor where - A: Executor::Input, S, Z> + HasObservers, - B: Executor::Input, S, Z> + HasObservers, - ::Observers: ObserversTuple<::Input, S>, - ::Observers: ObserversTuple<::Input, S>, - DOT: DifferentialObserversTuple::Input, S> - + MatchName, - S: HasCorpus, + A: Executor + HasObservers, + B: Executor + HasObservers, + ::Observers: ObserversTuple, + ::Observers: ObserversTuple, + DOT: DifferentialObserversTuple + MatchName, { fn run_target( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { self.observers(); // update in advance let observers = self.observers.get_mut(); @@ -117,7 +113,7 @@ where } } -impl HasTimeout for DiffExecutor +impl HasTimeout for DiffExecutor where A: HasTimeout, B: HasTimeout, @@ -233,14 +229,13 @@ impl ProxyObserversTuple { } } -impl HasObservers for DiffExecutor +impl HasObservers for DiffExecutor where A: HasObservers, B: HasObservers, - DOT: DifferentialObserversTuple::Input, S> + MatchName, - OTA: ObserversTuple<::Input, S>, - OTB: ObserversTuple<::Input, S>, - S: HasCorpus, + DOT: DifferentialObserversTuple + MatchName, + OTA: ObserversTuple, + OTB: ObserversTuple, { type Observers = ProxyObserversTuple; diff --git a/libafl/src/executors/forkserver.rs b/libafl/src/executors/forkserver.rs index 3ed868fd0e..825990a940 100644 --- a/libafl/src/executors/forkserver.rs +++ b/libafl/src/executors/forkserver.rs @@ -43,12 +43,11 @@ use crate::observers::{ get_asan_runtime_flags, get_asan_runtime_flags_with_log_path, AsanBacktraceObserver, }; use crate::{ - corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, - inputs::{BytesInput, Input, NopTargetBytesConverter, TargetBytesConverter}, + inputs::{BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter}, mutators::Tokens, observers::{MapObserver, Observer, ObserversTuple}, - state::{HasCorpus, HasExecutions}, + state::HasExecutions, Error, }; @@ -607,7 +606,7 @@ impl Forkserver { /// /// Shared memory feature is also available, but you have to set things up in your code. /// Please refer to AFL++'s docs. -pub struct ForkserverExecutor +pub struct ForkserverExecutor where SP: ShMemProvider, { @@ -619,7 +618,7 @@ where forkserver: Forkserver, observers: OT, map: Option, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, map_size: Option, min_input_size: usize, max_input_size: usize, @@ -629,7 +628,7 @@ where crash_exitcode: Option, } -impl Debug for ForkserverExecutor +impl Debug for ForkserverExecutor where TC: Debug, OT: Debug, @@ -649,7 +648,7 @@ where } } -impl ForkserverExecutor<(), (), (), UnixShMemProvider> { +impl ForkserverExecutor<(), (), (), UnixShMemProvider, ()> { /// Builder for `ForkserverExecutor` #[must_use] pub fn builder( @@ -659,12 +658,11 @@ impl ForkserverExecutor<(), (), (), UnixShMemProvider> { } } -impl ForkserverExecutor +impl ForkserverExecutor where - OT: ObserversTuple<::Input, S>, - S: HasCorpus, + OT: ObserversTuple, SP: ShMemProvider, - TC: TargetBytesConverter, + TC: TargetBytesConverter, { /// The `target` binary that's going to run. pub fn target(&self) -> &OsString { @@ -698,7 +696,7 @@ where /// Execute input and increase the execution counter. #[inline] - fn execute_input(&mut self, state: &mut S, input: &TC::Input) -> Result + fn execute_input(&mut self, state: &mut S, input: &I) -> Result where S: HasExecutions, { @@ -709,7 +707,7 @@ where /// Execute input, but side-step the execution counter. #[inline] - fn execute_input_uncounted(&mut self, input: &TC::Input) -> Result { + fn execute_input_uncounted(&mut self, input: &I) -> Result { let mut exit_kind = ExitKind::Ok; let last_run_timed_out = self.forkserver.last_run_timed_out_raw(); @@ -839,13 +837,14 @@ where /// in case no input file is specified. /// If `debug_child` is set, the child will print to `stdout`/`stderr`. #[expect(clippy::pedantic)] - pub fn build(mut self, observers: OT) -> Result, Error> + pub fn build( + mut self, + observers: OT, + ) -> Result, Error> where - OT: ObserversTuple<::Input, S>, - S: HasCorpus, - ::Input: Input, - TC: TargetBytesConverter, + OT: ObserversTuple, SP: ShMemProvider, + TC: TargetBytesConverter, { let (forkserver, input_file, map) = self.build_helper()?; @@ -901,18 +900,17 @@ where } /// Builds `ForkserverExecutor` downsizing the coverage map to fit exaclty the AFL++ map size. - #[expect(clippy::pedantic)] - pub fn build_dynamic_map( + #[expect(clippy::pedantic, clippy::type_complexity)] + pub fn build_dynamic_map( mut self, mut map_observer: A, other_observers: OT, - ) -> Result, Error> + ) -> Result, Error> where + A: Observer + AsMut, + I: Input + HasTargetBytes, MO: MapObserver + Truncate, // TODO maybe enforce Entry = u8 for the cov map - A: Observer<::Input, S> + AsMut, - OT: ObserversTuple<::Input, S> + Prepend, - ::Input: Input, - S: HasCorpus, + OT: ObserversTuple + Prepend, SP: ShMemProvider, { let (forkserver, input_file, map) = self.build_helper()?; @@ -1540,7 +1538,7 @@ impl<'a, TC> ForkserverExecutorBuilder<'a, TC, UnixShMemProvider> { impl<'a, TC, SP> ForkserverExecutorBuilder<'a, TC, SP> { /// Shmem provider for forkserver's shared memory testcase feature. - pub fn target_bytes_converter( + pub fn target_bytes_converter>( self, target_bytes_converter: TC2, ) -> ForkserverExecutorBuilder<'a, TC2, SP> { @@ -1579,13 +1577,12 @@ impl Default } } -impl Executor::Input, S, Z> - for ForkserverExecutor +impl Executor for ForkserverExecutor where - OT: ObserversTuple<::Input, S>, + OT: ObserversTuple, SP: ShMemProvider, - S: HasCorpus + HasExecutions, - TC: TargetBytesConverter::Input>, + S: HasExecutions, + TC: TargetBytesConverter, { #[inline] fn run_target( @@ -1593,13 +1590,13 @@ where _fuzzer: &mut Z, state: &mut S, _mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { self.execute_input(state, input) } } -impl HasTimeout for ForkserverExecutor +impl HasTimeout for ForkserverExecutor where SP: ShMemProvider, { @@ -1614,10 +1611,9 @@ where } } -impl HasObservers for ForkserverExecutor +impl HasObservers for ForkserverExecutor where - OT: ObserversTuple<::Input, S>, - S: HasCorpus, + OT: ObserversTuple, SP: ShMemProvider, { type Observers = OT; @@ -1677,7 +1673,7 @@ mod tests { .coverage_map_size(MAP_SIZE) .debug_child(false) .shmem_provider(&mut shmem_provider) - .build::<_, NopCorpus>(tuple_list!(edges_observer)); + .build::>(tuple_list!(edges_observer)); // Since /usr/bin/echo is not a instrumented binary file, the test will just check if the forkserver has failed at the initial handshake let result = match executor { diff --git a/libafl/src/executors/hooks/inprocess.rs b/libafl/src/executors/hooks/inprocess.rs index 06cbf45aae..6357f16592 100644 --- a/libafl/src/executors/hooks/inprocess.rs +++ b/libafl/src/executors/hooks/inprocess.rs @@ -23,15 +23,15 @@ use windows::Win32::System::Threading::{CRITICAL_SECTION, PTP_TIMER}; use crate::executors::hooks::timer::TimerStruct; #[cfg(all(unix, feature = "std"))] use crate::executors::hooks::unix::unix_signal_handler; -#[cfg(any(unix, windows))] -use crate::{corpus::Corpus, inputs::Input, observers::ObserversTuple, state::HasCurrentTestcase}; use crate::{ events::{EventFirer, EventRestarter}, executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers}, feedbacks::Feedback, - state::{HasCorpus, HasExecutions, HasSolutions}, + state::{HasExecutions, HasSolutions}, Error, HasObjective, }; +#[cfg(any(unix, windows))] +use crate::{inputs::Input, observers::ObserversTuple, state::HasCurrentTestcase}; /// The inmem executor's handlers. #[expect(missing_debug_implementations)] @@ -185,10 +185,7 @@ impl HasTimeout for InProcessHooks { } } -impl ExecutorHook for InProcessHooks -where - S: HasCorpus, -{ +impl ExecutorHook for InProcessHooks { fn init(&mut self, _state: &mut S) {} /// Call before running a target. fn pre_exec(&mut self, _state: &mut S, _input: &I) { @@ -223,10 +220,9 @@ impl InProcessHooks { E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, - S::Solutions: Corpus, { // # Safety // We get a pointer to `GLOBAL_STATE` that will be initialized at this point in time. @@ -268,8 +264,7 @@ impl InProcessHooks { EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, - S::Solutions: Corpus, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, { let ret; @@ -330,7 +325,7 @@ impl InProcessHooks { E: Executor + HasObservers + HasInProcessHooks, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus, + S: HasExecutions + HasSolutions, Z: HasObjective, { #[cfg_attr(miri, allow(unused_variables))] diff --git a/libafl/src/executors/hooks/inprocess_fork.rs b/libafl/src/executors/hooks/inprocess_fork.rs index b386a57296..753a5f6ce6 100644 --- a/libafl/src/executors/hooks/inprocess_fork.rs +++ b/libafl/src/executors/hooks/inprocess_fork.rs @@ -3,10 +3,10 @@ use alloc::vec::Vec; use core::{ ffi::c_void, marker::PhantomData, + mem::transmute, ptr::null, sync::atomic::{compiler_fence, Ordering}, }; -use std::intrinsics::transmute; #[cfg(not(miri))] use libafl_bolts::os::unix_signals::setup_signal_handler; @@ -21,7 +21,6 @@ use crate::{ HasObservers, }, observers::ObserversTuple, - state::HasCorpus, Error, }; @@ -35,10 +34,7 @@ pub struct InChildProcessHooks { phantom: PhantomData<(I, S)>, } -impl ExecutorHook for InChildProcessHooks -where - S: HasCorpus, -{ +impl ExecutorHook for InChildProcessHooks { /// Init this hook fn init(&mut self, _state: &mut S) {} @@ -61,7 +57,6 @@ impl InChildProcessHooks { where E: HasObservers, E::Observers: ObserversTuple, - S: HasCorpus, { #[cfg_attr(miri, allow(unused_variables, unused_unsafe))] unsafe { diff --git a/libafl/src/executors/hooks/intel_pt.rs b/libafl/src/executors/hooks/intel_pt.rs index 02889da393..45ed92dec5 100644 --- a/libafl/src/executors/hooks/intel_pt.rs +++ b/libafl/src/executors/hooks/intel_pt.rs @@ -10,7 +10,7 @@ use num_traits::SaturatingAdd; use serde::Serialize; use typed_builder::TypedBuilder; -use crate::{corpus::Corpus, executors::hooks::ExecutorHook, state::HasCorpus, Error}; +use crate::{executors::hooks::ExecutorHook, Error}; /// Info of a binary's section that can be used during `Intel PT` traces decoding #[derive(Debug, Clone, PartialEq, Eq)] @@ -36,18 +36,18 @@ pub struct IntelPTHook { map_len: usize, } -impl ExecutorHook<::Input, S> for IntelPTHook +impl ExecutorHook for IntelPTHook where - S: Serialize + HasCorpus, + S: Serialize, T: SaturatingAdd + From + Debug, { fn init(&mut self, _state: &mut S) {} - fn pre_exec(&mut self, _state: &mut S, _input: &::Input) { + fn pre_exec(&mut self, _state: &mut S, _input: &I) { self.intel_pt.enable_tracing().unwrap(); } - fn post_exec(&mut self, _state: &mut S, _input: &::Input) { + fn post_exec(&mut self, _state: &mut S, _input: &I) { let pt = &mut self.intel_pt; pt.disable_tracing().unwrap(); diff --git a/libafl/src/executors/hooks/unix.rs b/libafl/src/executors/hooks/unix.rs index 06dc3ad986..b78a585a9c 100644 --- a/libafl/src/executors/hooks/unix.rs +++ b/libafl/src/executors/hooks/unix.rs @@ -9,7 +9,6 @@ pub mod unix_signal_handler { use libc::siginfo_t; use crate::{ - corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{ common_signals, @@ -21,7 +20,7 @@ pub mod unix_signal_handler { fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, + state::{HasCurrentTestcase, HasExecutions, HasSolutions}, }; pub(crate) type HandlerFuncPtr = unsafe fn( @@ -83,8 +82,7 @@ pub mod unix_signal_handler { E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, - S::Solutions: Corpus, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, { @@ -133,10 +131,9 @@ pub mod unix_signal_handler { E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, - S::Solutions: Corpus, { // this stuff is for batch timeout if !data.executor_ptr.is_null() @@ -190,10 +187,9 @@ pub mod unix_signal_handler { E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, - S::Solutions: Corpus, { #[cfg(all(target_os = "android", target_arch = "aarch64"))] let _context = _context.map(|p| { diff --git a/libafl/src/executors/hooks/windows.rs b/libafl/src/executors/hooks/windows.rs index c5d8c60275..4a197e4c6a 100644 --- a/libafl/src/executors/hooks/windows.rs +++ b/libafl/src/executors/hooks/windows.rs @@ -9,7 +9,6 @@ pub mod windows_asan_handler { }; use crate::{ - corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{ hooks::inprocess::GLOBAL_STATE, inprocess::run_observers_and_save_state, Executor, @@ -19,7 +18,7 @@ pub mod windows_asan_handler { fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, + state::{HasCurrentTestcase, HasExecutions, HasSolutions}, }; /// # Safety @@ -31,8 +30,7 @@ pub mod windows_asan_handler { EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, - S::Solutions: Corpus, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, { let data = &raw mut GLOBAL_STATE; @@ -127,7 +125,6 @@ pub mod windows_exception_handler { }; use crate::{ - corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{ hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE}, @@ -138,7 +135,7 @@ pub mod windows_exception_handler { fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, + state::{HasCurrentTestcase, HasExecutions, HasSolutions}, }; pub(crate) type HandlerFuncPtr = @@ -189,8 +186,7 @@ pub mod windows_exception_handler { EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, - S::Solutions: Corpus, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, { let old_hook = panic::take_hook(); @@ -252,9 +248,8 @@ pub mod windows_exception_handler { EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, - S::Solutions: Corpus, { let data: &mut InProcessExecutorHandlerData = &mut *(global_state as *mut InProcessExecutorHandlerData); @@ -322,9 +317,8 @@ pub mod windows_exception_handler { EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, - S::Solutions: Corpus, { // Have we set a timer_before? if data.ptp_timer.is_some() { diff --git a/libafl/src/executors/inprocess/inner.rs b/libafl/src/executors/inprocess/inner.rs index deee22d49a..f5297ba65a 100644 --- a/libafl/src/executors/inprocess/inner.rs +++ b/libafl/src/executors/inprocess/inner.rs @@ -15,7 +15,6 @@ use crate::executors::hooks::inprocess::HasTimeout; #[cfg(all(windows, feature = "std"))] use crate::executors::hooks::inprocess::HasTimeout; use crate::{ - corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{ hooks::{ @@ -29,7 +28,7 @@ use crate::{ fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, + state::{HasCurrentTestcase, HasExecutions, HasSolutions}, Error, }; @@ -69,7 +68,6 @@ impl HasObservers for GenericInProcessExecutorInner impl GenericInProcessExecutorInner where OT: ObserversTuple, - S: HasCorpus, { /// This function marks the boundary between the fuzzer and the target /// @@ -132,7 +130,7 @@ impl GenericInProcessExecutorInner where HT: ExecutorHooksTuple, OT: ObserversTuple, - S: HasCorpus + HasExecutions + HasSolutions, + S: HasExecutions + HasSolutions, { /// Create a new in mem executor with the default timeout (5 sec) pub fn generic( @@ -148,8 +146,7 @@ where EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasCurrentTestcase + HasCorpus + HasSolutions, - S::Solutions: Corpus, + S: HasCurrentTestcase + HasSolutions, Z: HasObjective, { Self::with_timeout_generic::( @@ -178,8 +175,7 @@ where EM: EventFirer + EventRestarter, I: Input + Clone, OF: Feedback, - S: HasCurrentTestcase + HasCorpus + HasSolutions, - S::Solutions: Corpus, + S: HasCurrentTestcase + HasSolutions, Z: HasObjective, { let mut me = Self::with_timeout_generic::( @@ -210,9 +206,8 @@ where E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasCurrentTestcase + HasCorpus + HasSolutions, + S: HasCurrentTestcase + HasSolutions, Z: HasObjective, - S::Solutions: Corpus, I: Input + Clone, { let default = InProcessHooks::new::(timeout)?; diff --git a/libafl/src/executors/inprocess/mod.rs b/libafl/src/executors/inprocess/mod.rs index 57ecbe1f26..f019fb680d 100644 --- a/libafl/src/executors/inprocess/mod.rs +++ b/libafl/src/executors/inprocess/mod.rs @@ -77,7 +77,7 @@ where impl Executor for GenericInProcessExecutor where - S: HasCorpus + HasExecutions, + S: HasExecutions, OT: ObserversTuple, HT: ExecutorHooksTuple, HB: BorrowMut, @@ -124,8 +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 + HasExecutions + HasSolutions, - S::Solutions: Corpus, + S: HasCurrentTestcase + HasExecutions + HasSolutions, I: Input, { /// Create a new in mem executor with the default timeout (5 sec) @@ -227,8 +226,7 @@ where HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, - S: HasCorpus + HasCurrentTestcase + HasExecutions + HasSolutions, - S::Solutions: Corpus, + S: HasCurrentTestcase + HasExecutions + HasSolutions, I: Input, { /// Create a new in mem executor with the default timeout (5 sec) @@ -381,10 +379,9 @@ pub fn run_observers_and_save_state( E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, - S::Solutions: Corpus, { let mut observers = executor.observers_mut(); @@ -443,9 +440,8 @@ where E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, + S: HasExecutions + HasSolutions + HasCurrentTestcase, I: Input + Clone, - S::Solutions: Corpus, Z: HasObjective + ExecutionProcessor, { let data = &raw mut GLOBAL_STATE; diff --git a/libafl/src/executors/inprocess/stateful.rs b/libafl/src/executors/inprocess/stateful.rs index 11faf97390..c2f347952a 100644 --- a/libafl/src/executors/inprocess/stateful.rs +++ b/libafl/src/executors/inprocess/stateful.rs @@ -11,7 +11,6 @@ use core::{ use libafl_bolts::tuples::{tuple_list, RefIndexable}; use crate::{ - corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{ hooks::{inprocess::InProcessHooks, ExecutorHooksTuple}, @@ -22,7 +21,7 @@ use crate::{ fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, + state::{HasCurrentTestcase, HasExecutions, HasSolutions}, Error, }; @@ -74,7 +73,7 @@ where HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, - S: HasCorpus + HasExecutions, + S: HasExecutions, { fn run_target( &mut self, @@ -106,7 +105,6 @@ where HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, - S: HasCorpus, { type Observers = OT; #[inline] @@ -124,9 +122,8 @@ 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, + S: HasExecutions + HasSolutions + HasCurrentTestcase, I: Clone + Input, - S::Solutions: Corpus, { /// Create a new in mem executor with the default timeout (5 sec) pub fn new( @@ -246,8 +243,7 @@ where HT: ExecutorHooksTuple, I: Input + Clone, OT: ObserversTuple, - S: HasCorpus + HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, - S::Solutions: Corpus, + S: HasExecutions + HasSolutions + HasCurrentTestcase, { /// Create a new in mem executor with the default timeout (5 sec) pub fn generic( diff --git a/libafl/src/executors/inprocess_fork/inner.rs b/libafl/src/executors/inprocess_fork/inner.rs index 778d571036..b585bac18b 100644 --- a/libafl/src/executors/inprocess_fork/inner.rs +++ b/libafl/src/executors/inprocess_fork/inner.rs @@ -28,7 +28,6 @@ use crate::{ ExitKind, HasObservers, }, observers::ObserversTuple, - state::HasCorpus, Error, }; @@ -108,7 +107,6 @@ fn parse_itimerval(timeout: Duration) -> Itimerval { impl GenericInProcessForkExecutorInner where HT: ExecutorHooksTuple, - S: HasCorpus, SP: ShMemProvider, OT: ObserversTuple, { @@ -201,7 +199,6 @@ impl GenericInProcessForkExecutorInner, OT: ObserversTuple, - S: HasCorpus, { #[inline] /// This function marks the boundary between the fuzzer and the target. diff --git a/libafl/src/executors/inprocess_fork/mod.rs b/libafl/src/executors/inprocess_fork/mod.rs index d826b2d9fd..e0968334af 100644 --- a/libafl/src/executors/inprocess_fork/mod.rs +++ b/libafl/src/executors/inprocess_fork/mod.rs @@ -19,7 +19,7 @@ use crate::{ inprocess_fork::inner::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers, }, observers::ObserversTuple, - state::{HasCorpus, HasExecutions}, + state::HasExecutions, Error, }; @@ -45,7 +45,6 @@ pub type InProcessForkExecutor<'a, H, I, OT, S, SP, EM, Z> = impl<'a, H, I, OT, S, SP, EM, Z> InProcessForkExecutor<'a, H, I, OT, S, SP, EM, Z> where OT: ObserversTuple, - S: HasCorpus, { /// The constructor for `InProcessForkExecutor` pub fn new( @@ -107,7 +106,7 @@ impl Executor for GenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, EM, Z> where H: FnMut(&I) -> ExitKind + Sized, - S: HasCorpus + HasExecutions, + S: HasExecutions, SP: ShMemProvider, HT: ExecutorHooksTuple, OT: ObserversTuple, @@ -146,7 +145,6 @@ impl<'a, H, HT, I, OT, S, SP, EM, Z> GenericInProcessForkExecutor<'a, H, HT, I, where HT: ExecutorHooksTuple, OT: ObserversTuple, - S: HasCorpus, { /// Creates a new [`GenericInProcessForkExecutor`] with custom hooks #[expect(clippy::too_many_arguments)] diff --git a/libafl/src/executors/inprocess_fork/stateful.rs b/libafl/src/executors/inprocess_fork/stateful.rs index 56cbaa7ffc..0a1f1df141 100644 --- a/libafl/src/executors/inprocess_fork/stateful.rs +++ b/libafl/src/executors/inprocess_fork/stateful.rs @@ -20,7 +20,7 @@ use crate::{ ExitKind, HasObservers, }, observers::ObserversTuple, - state::{HasCorpus, HasExecutions}, + state::HasExecutions, Error, }; @@ -31,7 +31,6 @@ pub type StatefulInProcessForkExecutor<'a, H, I, OT, S, SP, ES, EM, Z> = impl<'a, H, I, OT, S, SP, ES, EM, Z> StatefulInProcessForkExecutor<'a, H, I, OT, S, SP, ES, EM, Z> where OT: ObserversTuple, - S: HasCorpus, { #[expect(clippy::too_many_arguments)] /// The constructor for `InProcessForkExecutor` @@ -99,7 +98,7 @@ impl Executor where H: FnMut(&mut ES, &I) -> ExitKind + Sized, HT: ExecutorHooksTuple, - S: HasCorpus + HasExecutions, + S: HasExecutions, SP: ShMemProvider, OT: ObserversTuple, { @@ -138,7 +137,6 @@ impl<'a, H, HT, I, OT, S, SP, ES, EM, Z> where HT: ExecutorHooksTuple, OT: ObserversTuple, - S: HasCorpus, { /// Creates a new [`StatefulGenericInProcessForkExecutor`] with custom hooks #[expect(clippy::too_many_arguments)] diff --git a/libafl/src/executors/shadow.rs b/libafl/src/executors/shadow.rs index 7fd1a4ea25..b633d9756e 100644 --- a/libafl/src/executors/shadow.rs +++ b/libafl/src/executors/shadow.rs @@ -10,23 +10,21 @@ use libafl_bolts::tuples::RefIndexable; use super::HasTimeout; use crate::{ - corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, observers::ObserversTuple, - state::HasCorpus, Error, }; /// A [`ShadowExecutor`] wraps an executor and a set of shadow observers -pub struct ShadowExecutor { +pub struct ShadowExecutor { /// The wrapped executor executor: E, /// The shadow observers shadow_observers: SOT, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl Debug for ShadowExecutor +impl Debug for ShadowExecutor where E: Debug, SOT: Debug, @@ -39,11 +37,10 @@ where } } -impl ShadowExecutor +impl ShadowExecutor where E: HasObservers, - S: HasCorpus, - SOT: ObserversTuple<::Input, S>, + SOT: ObserversTuple, { /// Create a new `ShadowExecutor`, wrapping the given `executor`. pub fn new(executor: E, shadow_observers: SOT) -> Self { @@ -67,25 +64,23 @@ where } } -impl Executor::Input, S, Z> - for ShadowExecutor +impl Executor for ShadowExecutor where - E: Executor::Input, S, Z> + HasObservers, - S: HasCorpus, - SOT: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + SOT: ObserversTuple, { fn run_target( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { self.executor.run_target(fuzzer, state, mgr, input) } } -impl HasTimeout for ShadowExecutor +impl HasTimeout for ShadowExecutor where E: HasTimeout, { @@ -99,11 +94,10 @@ where } } -impl HasObservers for ShadowExecutor +impl HasObservers for ShadowExecutor where E: HasObservers, - S: HasCorpus, - SOT: ObserversTuple<::Input, S>, + SOT: ObserversTuple, { type Observers = E::Observers; #[inline] diff --git a/libafl/src/executors/with_observers.rs b/libafl/src/executors/with_observers.rs index 37baeadee8..ecd6719d76 100644 --- a/libafl/src/executors/with_observers.rs +++ b/libafl/src/executors/with_observers.rs @@ -5,41 +5,37 @@ use core::{fmt::Debug, marker::PhantomData}; use libafl_bolts::tuples::RefIndexable; use crate::{ - corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, observers::ObserversTuple, - state::HasCorpus, Error, }; /// A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`]. #[derive(Debug)] -pub struct WithObservers { +pub struct WithObservers { executor: E, observers: OT, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl Executor::Input, S, Z> for WithObservers +impl Executor for WithObservers where - S: HasCorpus, - E: Executor::Input, S, Z>, + E: Executor, { fn run_target( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { self.executor.run_target(fuzzer, state, mgr, input) } } -impl HasObservers for WithObservers +impl HasObservers for WithObservers where - S: HasCorpus, - OT: ObserversTuple<::Input, S>, + OT: ObserversTuple, { type Observers = OT; fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> { @@ -51,7 +47,7 @@ where } } -impl WithObservers { +impl WithObservers { /// Wraps the given [`Executor`] with the given [`ObserversTuple`] to implement [`HasObservers`]. /// /// If the executor already implements [`HasObservers`], then the original implementation will be overshadowed by diff --git a/libafl/src/feedbacks/capture_feedback.rs b/libafl/src/feedbacks/capture_feedback.rs index c7d37b89cc..26fa58f2c9 100644 --- a/libafl/src/feedbacks/capture_feedback.rs +++ b/libafl/src/feedbacks/capture_feedback.rs @@ -38,7 +38,7 @@ impl StateInitializer for CaptureTimeoutFeedback {} impl Feedback for CaptureTimeoutFeedback where - S: HasCorpus + HasMetadata, + S: HasCorpus + HasMetadata, I: Debug + Serialize + DeserializeOwned + Default + 'static + Clone, { #[inline] diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs index 988f0a16dd..ce00b152aa 100644 --- a/libafl/src/feedbacks/map.rs +++ b/libafl/src/feedbacks/map.rs @@ -21,13 +21,12 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; #[cfg(feature = "track_hit_feedbacks")] use crate::feedbacks::premature_last_result_err; use crate::{ - corpus::{Corpus, Testcase}, + corpus::Testcase, events::{Event, EventFirer}, executors::ExitKind, feedbacks::{Feedback, HasObserverHandle, StateInitializer}, monitors::{AggregatorOps, UserStats, UserStatsValue}, observers::{CanTrack, MapObserver}, - state::HasCorpus, Error, HasMetadata, HasNamedMetadata, }; @@ -395,13 +394,13 @@ where impl Feedback for MapFeedback where C: CanTrack + AsRef, - EM: EventFirer<::Input, S>, + EM: EventFirer, N: IsNovel, O: MapObserver + for<'it> AsIter<'it, Item = O::Entry>, O::Entry: 'static + Default + Debug + DeserializeOwned + Serialize, OT: MatchName, R: Reducer, - S: HasNamedMetadata + HasCorpus, // delete me + S: HasNamedMetadata, { #[rustversion::nightly] default fn is_interesting( @@ -538,10 +537,10 @@ where impl Feedback for MapFeedback where C: CanTrack + AsRef, - EM: EventFirer<::Input, S>, + EM: EventFirer, O: MapObserver + for<'a> AsSlice<'a, Entry = u8> + for<'a> AsIter<'a, Item = u8>, OT: MatchName, - S: HasNamedMetadata + HasCorpus, + S: HasNamedMetadata, { fn is_interesting( &mut self, diff --git a/libafl/src/feedbacks/nautilus.rs b/libafl/src/feedbacks/nautilus.rs index b070d57c9e..f5754122a3 100644 --- a/libafl/src/feedbacks/nautilus.rs +++ b/libafl/src/feedbacks/nautilus.rs @@ -67,8 +67,7 @@ impl<'a> NautilusFeedback<'a> { testcase: &mut Testcase, ) -> Result<(), Error> where - S: HasCorpus + HasMetadata, - S::Corpus: Corpus, + S: HasCorpus + HasMetadata, { state.corpus().load_input_into(testcase)?; let input = testcase.input().as_ref().unwrap().clone(); @@ -93,8 +92,7 @@ impl StateInitializer for NautilusFeedback<'_> {} impl Feedback for NautilusFeedback<'_> where - S: HasMetadata + HasCorpus, - S::Corpus: Corpus, + S: HasMetadata + HasCorpus, { fn is_interesting( &mut self, diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index bbc1361442..e8a61afe34 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -129,9 +129,9 @@ pub trait ExecutionProcessor { /// Evaluates an input modifying the state of the fuzzer pub trait EvaluatorObservers { - /// Runs the input and triggers observers and feedback, - /// returns if is interesting an (option) the index of the new - /// [`crate::corpus::Testcase`] in the [`crate::corpus::Corpus`] + /// Runs the input and triggers observers and feedback. + /// if it is interesting, returns an (option) the index of the new + /// [`Testcase`] in the [`Corpus`] fn evaluate_input_with_observers( &mut self, state: &mut S, @@ -145,7 +145,7 @@ pub trait EvaluatorObservers { /// Evaluate an input modifying the state of the fuzzer pub trait Evaluator { /// Runs the input if it was (likely) not previously run and triggers observers and feedback and adds the input to the previously executed list - /// returns if is interesting an (option) the index of the new [`crate::corpus::Testcase`] in the corpus + /// if it is interesting, returns an (option) the index of the new [`Testcase`] in the corpus fn evaluate_filtered( &mut self, state: &mut S, @@ -155,7 +155,7 @@ pub trait Evaluator { ) -> Result<(ExecuteInputResult, Option), Error>; /// Runs the input and triggers observers and feedback, - /// returns if is interesting an (option) the index of the new [`crate::corpus::Testcase`] in the corpus + /// returns if is interesting an (option) the index of the new [`Testcase`] in the corpus fn evaluate_input( &mut self, state: &mut S, @@ -190,7 +190,7 @@ pub trait Evaluator { input: I, ) -> Result; - /// Adds the input to the corpus as disabled a input. + /// Adds the input to the corpus as a disabled input. /// Used during initial corpus loading. /// Disabled testcases are only used for splicing /// Returns the `index` of the new testcase in the corpus. @@ -199,11 +199,11 @@ pub trait Evaluator { } /// The main fuzzer trait. -pub trait Fuzzer { +pub trait Fuzzer { /// Fuzz for a single iteration. /// Returns the index of the last fuzzed corpus item. /// (Note: An iteration represents a complete run of every stage. - /// Therefore it does not mean that the harness is executed for once, + /// Therefore, it does not mean that the harness is executed for once, /// because each stage could run the harness for multiple times) /// /// If you use this fn in a restarting scenario to only run for `n` iterations, @@ -265,10 +265,9 @@ pub struct StdFuzzer { input_filter: IF, } -impl HasScheduler<::Input, S> for StdFuzzer +impl HasScheduler for StdFuzzer where - S: HasCorpus, - CS: Scheduler<::Input, S>, + CS: Scheduler, { type Scheduler = CS; @@ -305,23 +304,25 @@ impl HasObjective for StdFuzzer { } } -impl ExecutionProcessor::Input, OT, S> - for StdFuzzer +impl ExecutionProcessor for StdFuzzer where - CS: Scheduler<::Input, S>, - 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, - ::Input: Input, - S::Solutions: Corpus::Input>, + CS: Scheduler, + EM: EventFirer + CanSerializeObserver, + F: Feedback, + I: Input, + OF: Feedback, + OT: ObserversTuple + Serialize, + S: HasCorpus + + MaybeHasClientPerfMonitor + + HasCurrentTestcase + + HasSolutions + + HasLastFoundTime, { fn check_results( &mut self, state: &mut S, manager: &mut EM, - input: &::Input, + input: &I, observers: &OT, exit_kind: &ExitKind, ) -> Result { @@ -357,107 +358,12 @@ where Ok(res) } - fn evaluate_execution( - &mut self, - state: &mut S, - manager: &mut EM, - input: ::Input, - observers: &OT, - exit_kind: &ExitKind, - send_events: bool, - ) -> Result<(ExecuteInputResult, Option), Error> { - let exec_res = self.check_results(state, manager, &input, observers, exit_kind)?; - let corpus_id = self.process_execution(state, manager, &input, &exec_res, observers)?; - if send_events { - self.serialize_and_dispatch(state, manager, input, &exec_res, observers, exit_kind)?; - } - if exec_res != ExecuteInputResult::None { - *state.last_found_time_mut() = current_time(); - } - Ok((exec_res, corpus_id)) - } - - fn serialize_and_dispatch( - &mut self, - state: &mut S, - manager: &mut EM, - input: ::Input, - exec_res: &ExecuteInputResult, - observers: &OT, - exit_kind: &ExitKind, - ) -> Result<(), Error> { - // Now send off the event - let observers_buf = match exec_res { - ExecuteInputResult::Corpus => { - if manager.should_send() { - // TODO set None for fast targets - if manager.configuration() == EventConfig::AlwaysUnique { - None - } else { - manager.serialize_observers(observers)? - } - } else { - None - } - } - _ => None, - }; - - self.dispatch_event(state, manager, input, exec_res, observers_buf, exit_kind)?; - Ok(()) - } - - fn dispatch_event( - &mut self, - state: &mut S, - manager: &mut EM, - input: ::Input, - exec_res: &ExecuteInputResult, - observers_buf: Option>, - exit_kind: &ExitKind, - ) -> Result<(), Error> { - // Now send off the event - match exec_res { - ExecuteInputResult::Corpus => { - if manager.should_send() { - manager.fire( - state, - Event::NewTestcase { - input, - observers_buf, - exit_kind: *exit_kind, - corpus_size: state.corpus().count(), - client_config: manager.configuration(), - time: current_time(), - forward_id: None, - #[cfg(all(unix, feature = "std", feature = "multi_machine"))] - node_id: None, - }, - )?; - } - } - ExecuteInputResult::Solution => { - if manager.should_send() { - manager.fire( - state, - Event::Objective { - objective_size: state.solutions().count(), - time: current_time(), - }, - )?; - } - } - ExecuteInputResult::None => (), - } - Ok(()) - } - /// Evaluate if a set of observation channels has an interesting state fn process_execution( &mut self, state: &mut S, manager: &mut EM, - input: &::Input, + input: &I, exec_res: &ExecuteInputResult, observers: &OT, ) -> Result, Error> { @@ -504,25 +410,118 @@ where } } } + + fn serialize_and_dispatch( + &mut self, + state: &mut S, + manager: &mut EM, + input: I, + exec_res: &ExecuteInputResult, + observers: &OT, + exit_kind: &ExitKind, + ) -> Result<(), Error> { + // Now send off the event + let observers_buf = match exec_res { + ExecuteInputResult::Corpus => { + if manager.should_send() { + // TODO set None for fast targets + if manager.configuration() == EventConfig::AlwaysUnique { + None + } else { + manager.serialize_observers(observers)? + } + } else { + None + } + } + _ => None, + }; + + self.dispatch_event(state, manager, input, exec_res, observers_buf, exit_kind)?; + Ok(()) + } + + fn dispatch_event( + &mut self, + state: &mut S, + manager: &mut EM, + input: I, + exec_res: &ExecuteInputResult, + observers_buf: Option>, + exit_kind: &ExitKind, + ) -> Result<(), Error> { + // Now send off the event + match exec_res { + ExecuteInputResult::Corpus => { + if manager.should_send() { + manager.fire( + state, + Event::NewTestcase { + input, + observers_buf, + exit_kind: *exit_kind, + corpus_size: state.corpus().count(), + client_config: manager.configuration(), + time: current_time(), + forward_id: None, + #[cfg(all(unix, feature = "std", feature = "multi_machine"))] + node_id: None, + }, + )?; + } + } + ExecuteInputResult::Solution => { + if manager.should_send() { + manager.fire( + state, + Event::Objective { + objective_size: state.solutions().count(), + time: current_time(), + }, + )?; + } + } + ExecuteInputResult::None => (), + } + Ok(()) + } + + fn evaluate_execution( + &mut self, + state: &mut S, + manager: &mut EM, + input: I, + observers: &OT, + exit_kind: &ExitKind, + send_events: bool, + ) -> Result<(ExecuteInputResult, Option), Error> { + let exec_res = self.check_results(state, manager, &input, observers, exit_kind)?; + let corpus_id = self.process_execution(state, manager, &input, &exec_res, observers)?; + if send_events { + self.serialize_and_dispatch(state, manager, input, &exec_res, observers, exit_kind)?; + } + if exec_res != ExecuteInputResult::None { + *state.last_found_time_mut() = current_time(); + } + Ok((exec_res, corpus_id)) + } } -impl EvaluatorObservers::Input, S> - for StdFuzzer +impl EvaluatorObservers for StdFuzzer where - CS: Scheduler<::Input, S>, - E: HasObservers + Executor::Input, S, Self>, - E::Observers: MatchName + ObserversTuple<::Input, S> + Serialize, - EM: EventFirer<::Input, S> + CanSerializeObserver, - F: Feedback::Input, E::Observers, S>, - OF: Feedback::Input, E::Observers, S>, - S: HasCorpus - + HasSolutions + CS: Scheduler, + E: HasObservers + Executor, + E::Observers: MatchName + ObserversTuple + Serialize, + EM: EventFirer + CanSerializeObserver, + F: Feedback, + OF: Feedback, + S: HasCorpus + + HasSolutions + MaybeHasClientPerfMonitor - + HasCurrentTestcase + + HasCurrentTestcase + HasExecutions + HasLastFoundTime, - ::Input: Input, - S::Solutions: Corpus::Input>, + I: Input, { /// Process one input, adding to the respective corpora if needed and firing the right events #[inline] @@ -531,7 +530,7 @@ where state: &mut S, executor: &mut E, manager: &mut EM, - input: ::Input, + input: I, send_events: bool, ) -> Result<(ExecuteInputResult, Option), Error> { let exit_kind = self.execute_input(state, executor, manager, &input)?; @@ -583,31 +582,29 @@ impl InputFilter for BloomInputFilter { } } -impl Evaluator::Input, S> - for StdFuzzer +impl Evaluator for StdFuzzer where - CS: Scheduler<::Input, S>, - E: HasObservers + Executor::Input, S, Self>, - E::Observers: MatchName + ObserversTuple<::Input, S> + Serialize, - EM: EventFirer<::Input, S> + CanSerializeObserver, - F: Feedback::Input, E::Observers, S>, - OF: Feedback::Input, E::Observers, S>, - S: HasCorpus - + HasSolutions + CS: Scheduler, + E: HasObservers + Executor, + E::Observers: MatchName + ObserversTuple + Serialize, + EM: EventFirer + CanSerializeObserver, + F: Feedback, + OF: Feedback, + S: HasCorpus + + HasSolutions + MaybeHasClientPerfMonitor - + HasCurrentTestcase + + HasCurrentTestcase + HasLastFoundTime + HasExecutions, - ::Input: Input, - S::Solutions: Corpus::Input>, - IF: InputFilter<::Input>, + I: Input, + IF: InputFilter, { fn evaluate_filtered( &mut self, state: &mut S, executor: &mut E, manager: &mut EM, - input: ::Input, + input: I, ) -> Result<(ExecuteInputResult, Option), Error> { if self.input_filter.should_execute(&input) { self.evaluate_input(state, executor, manager, input) @@ -623,31 +620,19 @@ where state: &mut S, executor: &mut E, manager: &mut EM, - input: ::Input, + input: I, send_events: bool, ) -> Result<(ExecuteInputResult, Option), Error> { self.evaluate_input_with_observers(state, executor, manager, input, send_events) } - fn add_disabled_input( - &mut self, - state: &mut S, - input: ::Input, - ) -> Result { - let mut testcase = Testcase::from(input.clone()); - testcase.set_disabled(true); - // Add the disabled input to the main corpus - let id = state.corpus_mut().add_disabled(testcase)?; - Ok(id) - } - /// Adds an input, even if it's not considered `interesting` by any of the executors fn add_input( &mut self, state: &mut S, executor: &mut E, manager: &mut EM, - input: ::Input, + input: I, ) -> Result { *state.last_found_time_mut() = current_time(); @@ -738,17 +723,25 @@ where )?; Ok(id) } + + fn add_disabled_input(&mut self, state: &mut S, input: I) -> Result { + let mut testcase = Testcase::from(input.clone()); + testcase.set_disabled(true); + // Add the disabled input to the main corpus + let id = state.corpus_mut().add_disabled(testcase)?; + Ok(id) + } } -impl Fuzzer for StdFuzzer +impl Fuzzer for StdFuzzer where - CS: Scheduler<::Input, S>, + CS: Scheduler, EM: ProgressReporter + EventProcessor, S: HasExecutions + HasMetadata - + HasCorpus + + HasCorpus + HasLastReportTime - + HasTestcase + + HasTestcase + HasCurrentCorpusId + HasCurrentStageId + Stoppable @@ -855,7 +848,7 @@ where manager.report_progress(state)?; - // If we would assume the fuzzer loop will always exit after this, we could do this here: + // If we assumed the fuzzer loop will always exit after this, we could do this here: // manager.on_restart(state)?; // But as the state may grow to a few megabytes, // for now we won't, and the user has to do it (unless we find a way to do this on `Drop`). @@ -914,13 +907,12 @@ pub trait ExecutesInput { ) -> Result; } -impl ExecutesInput::Input, S> - for StdFuzzer +impl ExecutesInput for StdFuzzer where - CS: Scheduler<::Input, S>, - E: Executor::Input, S, Self> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, - S: HasExecutions + HasCorpus + MaybeHasClientPerfMonitor, + CS: Scheduler, + E: Executor + HasObservers, + E::Observers: ObserversTuple, + S: HasExecutions + HasCorpus + MaybeHasClientPerfMonitor, { /// Runs the input and triggers observers and feedback fn execute_input( @@ -928,7 +920,7 @@ where state: &mut S, executor: &mut E, event_mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { start_timer!(state); executor.observers_mut().pre_exec_all(state, input)?; @@ -966,7 +958,7 @@ impl Default for NopFuzzer { } } -impl Fuzzer for NopFuzzer +impl Fuzzer for NopFuzzer where EM: ProgressReporter + EventProcessor, ST: StagesTuple, diff --git a/libafl/src/inputs/generalized.rs b/libafl/src/inputs/generalized.rs index 91b7c00365..56f6d4ec09 100644 --- a/libafl/src/inputs/generalized.rs +++ b/libafl/src/inputs/generalized.rs @@ -9,7 +9,6 @@ use crate::{ corpus::Testcase, inputs::BytesInput, stages::mutational::{MutatedTransform, MutatedTransformPost}, - state::HasCorpus, Error, HasMetadata, }; @@ -105,10 +104,7 @@ impl GeneralizedInputMetadata { } } -impl MutatedTransform for GeneralizedInputMetadata -where - S: HasCorpus, -{ +impl MutatedTransform for GeneralizedInputMetadata { type Post = Self; fn try_transform_from(base: &mut Testcase, _state: &S) -> Result { @@ -130,4 +126,4 @@ where } } -impl MutatedTransformPost for GeneralizedInputMetadata where S: HasCorpus {} +impl MutatedTransformPost for GeneralizedInputMetadata {} diff --git a/libafl/src/inputs/mod.rs b/libafl/src/inputs/mod.rs index 348aa0609c..905cde8726 100644 --- a/libafl/src/inputs/mod.rs +++ b/libafl/src/inputs/mod.rs @@ -356,12 +356,9 @@ where } /// A converter that converts from `input` to target bytes -pub trait TargetBytesConverter { - /// The input - type Input; - +pub trait TargetBytesConverter { /// Create target bytes - fn to_target_bytes<'a>(&mut self, input: &'a Self::Input) -> OwnedSlice<'a, u8>; + fn to_target_bytes<'a>(&mut self, input: &'a I) -> OwnedSlice<'a, u8>; } /// Simply gets the target bytes out from a [`HasTargetBytes`] type. @@ -386,10 +383,11 @@ impl Default for NopTargetBytesConverter { } } -impl TargetBytesConverter for NopTargetBytesConverter { - type Input = I; - - fn to_target_bytes<'a>(&mut self, input: &'a Self::Input) -> OwnedSlice<'a, u8> { +impl TargetBytesConverter for NopTargetBytesConverter +where + I: HasTargetBytes, +{ + fn to_target_bytes<'a>(&mut self, input: &'a I) -> OwnedSlice<'a, u8> { input.target_bytes() } } diff --git a/libafl/src/inputs/nautilus.rs b/libafl/src/inputs/nautilus.rs index 2a87a4d2be..4fade05a1d 100644 --- a/libafl/src/inputs/nautilus.rs +++ b/libafl/src/inputs/nautilus.rs @@ -154,10 +154,8 @@ impl<'a> NautilusTargetBytesConverter<'a> { } } -impl TargetBytesConverter for NautilusTargetBytesConverter<'_> { - type Input = NautilusInput; - - fn to_target_bytes<'a>(&mut self, input: &'a Self::Input) -> OwnedSlice<'a, u8> { +impl TargetBytesConverter for NautilusTargetBytesConverter<'_> { + fn to_target_bytes<'a>(&mut self, input: &'a NautilusInput) -> OwnedSlice<'a, u8> { let mut bytes = Vec::new(); input.unparse(self.ctx, &mut bytes); OwnedSlice::from(bytes) diff --git a/libafl/src/lib.rs b/libafl/src/lib.rs index 58464b3ee6..346feb244b 100644 --- a/libafl/src/lib.rs +++ b/libafl/src/lib.rs @@ -190,14 +190,14 @@ mod tests { let state_serialized = postcard::to_allocvec(&state).unwrap(); let state_deserialized: StdState< - _, InMemoryCorpus, + _, StdRand, InMemoryCorpus, > = postcard::from_bytes::< StdState< - BytesInput, InMemoryCorpus, + BytesInput, RomuDuoJrRand, InMemoryCorpus, >, diff --git a/libafl/src/mutators/encoded_mutations.rs b/libafl/src/mutators/encoded_mutations.rs index deca65177d..cb71bcfbda 100644 --- a/libafl/src/mutators/encoded_mutations.rs +++ b/libafl/src/mutators/encoded_mutations.rs @@ -313,8 +313,7 @@ pub struct EncodedCrossoverInsertMutator; impl Mutator for EncodedCrossoverInsertMutator where - S: HasRand + HasCorpus + HasMaxSize, - S::Corpus: Corpus, + S: HasRand + HasCorpus + HasMaxSize, { fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result { let size = input.codes().len(); @@ -397,8 +396,7 @@ pub struct EncodedCrossoverReplaceMutator; impl Mutator for EncodedCrossoverReplaceMutator where - S: HasRand + HasCorpus, - S::Corpus: Corpus, + S: HasRand + HasCorpus, { fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result { let size = input.codes().len(); diff --git a/libafl/src/mutators/gramatron.rs b/libafl/src/mutators/gramatron.rs index 605c0f2358..26c77144dd 100644 --- a/libafl/src/mutators/gramatron.rs +++ b/libafl/src/mutators/gramatron.rs @@ -111,8 +111,7 @@ pub struct GramatronSpliceMutator; impl Mutator for GramatronSpliceMutator where - S: HasRand + HasCorpus + HasMetadata, - S::Corpus: Corpus, + S: HasRand + HasCorpus + HasMetadata, { fn mutate( &mut self, diff --git a/libafl/src/mutators/grimoire.rs b/libafl/src/mutators/grimoire.rs index 1a8300d41f..b82e5356e8 100644 --- a/libafl/src/mutators/grimoire.rs +++ b/libafl/src/mutators/grimoire.rs @@ -4,6 +4,7 @@ use alloc::{borrow::Cow, vec::Vec}; use core::{ cmp::{max, min}, + marker::PhantomData, num::NonZero, }; @@ -25,13 +26,13 @@ const RECURSIVE_REPLACEMENT_DEPTH: [usize; 6] = [2, 4, 8, 16, 32, 64]; const MAX_RECURSIVE_REPLACEMENT_LEN: usize = 64 << 10; const CHOOSE_SUBINPUT_PROB: f64 = 0.5; -fn extend_with_random_generalized( +fn extend_with_random_generalized( state: &mut S, items: &mut Vec, gap_indices: &mut Vec, ) -> Result where - S: HasMetadata + HasRand + HasCorpus, + S: HasMetadata + HasRand + HasCorpus, { let id = random_corpus_id!(state.corpus(), state.rand_mut()); @@ -116,13 +117,14 @@ where /// Extend the generalized input with another random one from the corpus #[derive(Debug, Default)] -pub struct GrimoireExtensionMutator { +pub struct GrimoireExtensionMutator { gap_indices: Vec, + phantom: PhantomData, } -impl Mutator for GrimoireExtensionMutator +impl Mutator for GrimoireExtensionMutator where - S: HasMetadata + HasRand + HasCorpus, + S: HasMetadata + HasRand + HasCorpus, { fn mutate( &mut self, @@ -137,33 +139,35 @@ where } } -impl Named for GrimoireExtensionMutator { +impl Named for GrimoireExtensionMutator { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("GrimoireExtensionMutator"); &NAME } } -impl GrimoireExtensionMutator { +impl GrimoireExtensionMutator { /// Creates a new [`GrimoireExtensionMutator`]. #[must_use] pub fn new() -> Self { Self { gap_indices: vec![], + phantom: PhantomData, } } } /// Extend the generalized input with another random one from the corpus #[derive(Debug, Default)] -pub struct GrimoireRecursiveReplacementMutator { +pub struct GrimoireRecursiveReplacementMutator { scratch: Vec, gap_indices: Vec, + phantom: PhantomData, } -impl Mutator for GrimoireRecursiveReplacementMutator +impl Mutator for GrimoireRecursiveReplacementMutator where - S: HasMetadata + HasRand + HasCorpus, + S: HasMetadata + HasRand + HasCorpus, { fn mutate( &mut self, @@ -215,31 +219,34 @@ where } } -impl Named for GrimoireRecursiveReplacementMutator { +impl Named for GrimoireRecursiveReplacementMutator { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("GrimoireRecursiveReplacementMutator"); &NAME } } -impl GrimoireRecursiveReplacementMutator { +impl GrimoireRecursiveReplacementMutator { /// Creates a new [`GrimoireRecursiveReplacementMutator`]. #[must_use] pub fn new() -> Self { Self { scratch: vec![], gap_indices: vec![], + phantom: PhantomData, } } } /// Replace matching tokens with others from the tokens metadata #[derive(Debug, Default)] -pub struct GrimoireStringReplacementMutator {} +pub struct GrimoireStringReplacementMutator { + phantom: PhantomData, +} -impl Mutator for GrimoireStringReplacementMutator +impl Mutator for GrimoireStringReplacementMutator where - S: HasMetadata + HasRand + HasCorpus, + S: HasMetadata + HasRand + HasCorpus, { fn mutate( &mut self, @@ -336,30 +343,33 @@ where } } -impl Named for GrimoireStringReplacementMutator { +impl Named for GrimoireStringReplacementMutator { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("GrimoireStringReplacementMutator"); &NAME } } -impl GrimoireStringReplacementMutator { +impl GrimoireStringReplacementMutator { /// Creates a new [`GrimoireExtensionMutator`]. #[must_use] pub fn new() -> Self { - Self::default() + Self { + phantom: PhantomData, + } } } /// Randomly delete a part of the generalized input #[derive(Debug, Default)] -pub struct GrimoireRandomDeleteMutator { +pub struct GrimoireRandomDeleteMutator { gap_indices: Vec, + phantom: PhantomData, } -impl Mutator for GrimoireRandomDeleteMutator +impl Mutator for GrimoireRandomDeleteMutator where - S: HasMetadata + HasRand + HasCorpus, + S: HasMetadata + HasRand + HasCorpus, { fn mutate( &mut self, @@ -400,19 +410,20 @@ where } } -impl Named for GrimoireRandomDeleteMutator { +impl Named for GrimoireRandomDeleteMutator { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("GrimoireRandomDeleteMutator"); &NAME } } -impl GrimoireRandomDeleteMutator { +impl GrimoireRandomDeleteMutator { /// Creates a new [`GrimoireExtensionMutator`]. #[must_use] pub fn new() -> Self { Self { gap_indices: vec![], + phantom: PhantomData, } } } diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index f2d1c512e3..38df927083 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -51,9 +51,9 @@ pub type HavocMutationsNoCrossoverType = tuple_list_type!( pub type HavocCrossoverType = tuple_list_type!(CrossoverInsertMutator, CrossoverReplaceMutator); /// Tuple type of the mutations that compose the Havoc mutator's crossover mutations for mapped input types -pub type MappedHavocCrossoverType = tuple_list_type!( - MappedCrossoverInsertMutator, - MappedCrossoverReplaceMutator, +pub type MappedHavocCrossoverType = tuple_list_type!( + MappedCrossoverInsertMutator, + MappedCrossoverReplaceMutator, ); /// Tuple type of the mutations that compose the Havoc mutator @@ -61,15 +61,15 @@ pub type HavocMutationsType = merge_tuple_list_type!(HavocMutationsNoCrossoverType, HavocCrossoverType); /// Tuple type of the mutations that compose the Havoc mutator for mapped input types -pub type MappedHavocMutationsType = map_tuple_list_type!( - merge_tuple_list_type!(HavocMutationsNoCrossoverType, MappedHavocCrossoverType), +pub type MappedHavocMutationsType = map_tuple_list_type!( + merge_tuple_list_type!(HavocMutationsNoCrossoverType, MappedHavocCrossoverType), ToMappingMutator ); /// Tuple type of the mutations that compose the Havoc mutator for mapped input types, for optional byte array input parts -pub type OptionMappedHavocMutationsType = map_tuple_list_type!( +pub type OptionMappedHavocMutationsType = map_tuple_list_type!( map_tuple_list_type!( - merge_tuple_list_type!(HavocMutationsNoCrossoverType, MappedHavocCrossoverType), + merge_tuple_list_type!(HavocMutationsNoCrossoverType, MappedHavocCrossoverType), ToOptionalMutator ), ToMappingMutator @@ -117,9 +117,9 @@ pub fn havoc_crossover() -> HavocCrossoverType { } /// Get the mutations that compose the Havoc mutator's crossover strategy with custom corpus extraction logic -pub fn havoc_crossover_with_corpus_mapper( +pub fn havoc_crossover_with_corpus_mapper( input_mapper: F, -) -> MappedHavocCrossoverType +) -> MappedHavocCrossoverType where F: Clone + Fn(&IO) -> &O, { @@ -130,9 +130,9 @@ where } /// Get the mutations that compose the Havoc mutator's crossover strategy with custom corpus extraction logic -pub fn havoc_crossover_with_corpus_mapper_optional( +pub fn havoc_crossover_with_corpus_mapper_optional( input_mapper: F, -) -> MappedHavocCrossoverType +) -> MappedHavocCrossoverType where F: Clone, { @@ -155,7 +155,7 @@ pub fn havoc_mutations() -> HavocMutationsType { pub fn mapped_havoc_mutations( current_input_mapper: F1, input_from_corpus_mapper: F2, -) -> MappedHavocMutationsType +) -> MappedHavocMutationsType where F1: Clone + FnMut(&mut IO1) -> &mut II, F2: Clone + Fn(&IO2) -> &O, @@ -172,7 +172,7 @@ where pub fn optional_mapped_havoc_mutations( current_input_mapper: F1, input_from_corpus_mapper: F2, -) -> OptionMappedHavocMutationsType +) -> OptionMappedHavocMutationsType where F1: Clone + FnMut(&mut IO1) -> &mut II, F2: Clone + Fn(&IO2) -> &O, diff --git a/libafl/src/mutators/mopt_mutator.rs b/libafl/src/mutators/mopt_mutator.rs index c3d0a827a9..bccedc11a0 100644 --- a/libafl/src/mutators/mopt_mutator.rs +++ b/libafl/src/mutators/mopt_mutator.rs @@ -371,7 +371,7 @@ pub struct StdMOptMutator { impl Mutator for StdMOptMutator where MT: MutatorsTuple, - S: HasRand + HasMetadata + HasCorpus + HasSolutions, + S: HasRand + HasMetadata + HasCorpus + HasSolutions, { #[inline] fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { @@ -519,7 +519,7 @@ impl StdMOptMutator { } fn core_mutate(&mut self, state: &mut S, input: &mut I) -> Result where - S: HasMetadata + HasRand + HasSolutions + HasCorpus, + S: HasMetadata + HasRand + HasSolutions + HasCorpus, MT: MutatorsTuple, { let mut r = MutationResult::Skipped; @@ -546,7 +546,7 @@ impl StdMOptMutator { fn pilot_mutate(&mut self, state: &mut S, input: &mut I) -> Result where - S: HasMetadata + HasRand + HasSolutions + HasCorpus, + S: HasMetadata + HasRand + HasSolutions + HasCorpus, MT: MutatorsTuple, { let mut r = MutationResult::Skipped; @@ -604,7 +604,7 @@ impl Named for StdMOptMutator { impl ScheduledMutator for StdMOptMutator where MT: MutatorsTuple, - S: HasRand + HasMetadata + HasCorpus + HasSolutions, + S: HasRand + HasMetadata + HasCorpus + HasSolutions, { /// Compute the number of iterations used to apply stacked mutations fn iterations(&self, state: &mut S, _: &I) -> u64 { diff --git a/libafl/src/mutators/multi.rs b/libafl/src/mutators/multi.rs index f7c353e866..a25d214f5d 100644 --- a/libafl/src/mutators/multi.rs +++ b/libafl/src/mutators/multi.rs @@ -118,9 +118,8 @@ impl_default_multipart!( impl Mutator, S> for CrossoverInsertMutator where - S: HasCorpus + HasMaxSize + HasRand, + S: HasCorpus> + HasMaxSize + HasRand, I: Input + HasMutatorResizableBytes, - S::Corpus: Corpus>, { fn mutate( &mut self, @@ -254,9 +253,8 @@ where impl Mutator, S> for CrossoverReplaceMutator where - S: HasCorpus + HasMaxSize + HasRand, + S: HasCorpus> + HasMaxSize + HasRand, I: Input + HasMutatorResizableBytes, - S::Corpus: Corpus>, { fn mutate( &mut self, diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index dce3ffb730..218ba1c11f 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -1125,9 +1125,8 @@ impl CrossoverInsertMutator { impl Mutator for CrossoverInsertMutator where - S: HasCorpus + HasRand + HasMaxSize, - ::Input: HasMutatorBytes, I: HasMutatorResizableBytes, + S: HasCorpus + HasRand + HasMaxSize, { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { let size = input.bytes().len(); @@ -1217,9 +1216,8 @@ impl CrossoverReplaceMutator { impl Mutator for CrossoverReplaceMutator where - S: HasCorpus + HasRand, - ::Input: HasMutatorBytes, I: HasMutatorBytes, + S: HasCorpus + HasRand, { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { let size = input.bytes().len(); @@ -1297,12 +1295,12 @@ impl IntoOptionBytes for Option> { /// Crossover insert mutation for inputs mapped to a bytes vector #[derive(Debug)] -pub struct MappedCrossoverInsertMutator { +pub struct MappedCrossoverInsertMutator { input_mapper: F, - phantom: PhantomData, + phantom: PhantomData<(I, O)>, } -impl MappedCrossoverInsertMutator { +impl MappedCrossoverInsertMutator { /// Creates a new [`MappedCrossoverInsertMutator`] pub fn new(input_mapper: F) -> Self { Self { @@ -1312,14 +1310,14 @@ impl MappedCrossoverInsertMutator { } } -impl Mutator for MappedCrossoverInsertMutator +impl Mutator for MappedCrossoverInsertMutator where - S: HasCorpus + HasMaxSize + HasRand, - I: HasMutatorResizableBytes, + F: Fn(&I1) -> &O, + I2: HasMutatorResizableBytes, O: IntoOptionBytes, - F: Fn(&::Input) -> &O, + S: HasCorpus + HasMaxSize + HasRand, { - fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { + fn mutate(&mut self, state: &mut S, input: &mut I2) -> Result { let size = input.bytes().len(); let max_size = state.max_size(); // TODO: fix bug if size is 0 (?) @@ -1377,7 +1375,7 @@ where } } -impl Named for MappedCrossoverInsertMutator { +impl Named for MappedCrossoverInsertMutator { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("MappedCrossoverInsertMutator"); &NAME @@ -1386,12 +1384,12 @@ impl Named for MappedCrossoverInsertMutator { /// Crossover replace mutation for inputs mapped to a bytes vector #[derive(Debug)] -pub struct MappedCrossoverReplaceMutator { +pub struct MappedCrossoverReplaceMutator { input_mapper: F, - phantom: PhantomData, + phantom: PhantomData<(I, O)>, } -impl MappedCrossoverReplaceMutator { +impl MappedCrossoverReplaceMutator { /// Creates a new [`MappedCrossoverReplaceMutator`] pub fn new(input_mapper: F) -> Self { Self { @@ -1401,14 +1399,14 @@ impl MappedCrossoverReplaceMutator { } } -impl Mutator for MappedCrossoverReplaceMutator +impl Mutator for MappedCrossoverReplaceMutator where - S: HasCorpus + HasMaxSize + HasRand, - I: HasMutatorBytes, + F: Fn(&I1) -> &O, + I2: HasMutatorBytes, O: IntoOptionBytes, - F: Fn(&::Input) -> &O, + S: HasCorpus + HasMaxSize + HasRand, { - fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { + fn mutate(&mut self, state: &mut S, input: &mut I2) -> Result { let size = input.bytes().len(); if size == 0 { return Ok(MutationResult::Skipped); @@ -1463,7 +1461,7 @@ where } } -impl Named for MappedCrossoverReplaceMutator { +impl Named for MappedCrossoverReplaceMutator { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("MappedCrossoverReplaceMutator"); &NAME @@ -1492,8 +1490,7 @@ pub struct SpliceMutator; impl Mutator for SpliceMutator where - S: HasCorpus + HasRand, - ::Input: HasMutatorBytes, + S: HasCorpus + HasRand, I: HasMutatorResizableBytes, { #[expect(clippy::cast_sign_loss)] @@ -1657,7 +1654,7 @@ mod tests { ) } - fn test_state() -> impl HasCorpus + HasMetadata + HasRand + HasMaxSize { + fn test_state() -> impl HasCorpus + HasMetadata + HasRand + HasMaxSize { let rand = StdRand::with_seed(1337); let mut corpus = InMemoryCorpus::new(); diff --git a/libafl/src/mutators/nautilus.rs b/libafl/src/mutators/nautilus.rs index 02ee3a50c0..494a75abcb 100644 --- a/libafl/src/mutators/nautilus.rs +++ b/libafl/src/mutators/nautilus.rs @@ -162,7 +162,7 @@ impl Debug for NautilusSpliceMutator<'_> { impl Mutator for NautilusSpliceMutator<'_> where - S: HasCorpus + HasMetadata + HasRand, + S: HasCorpus + HasMetadata + HasRand, { fn mutate( &mut self, diff --git a/libafl/src/mutators/numeric.rs b/libafl/src/mutators/numeric.rs index 998b894231..f0ed541671 100644 --- a/libafl/src/mutators/numeric.rs +++ b/libafl/src/mutators/numeric.rs @@ -1,6 +1,7 @@ //! Mutators for integer-style inputs use alloc::borrow::Cow; +use core::marker::PhantomData; use libafl_bolts::{ rands::Rand, @@ -31,7 +32,7 @@ pub type IntMutatorsType = tuple_list_type!( pub type IntMutatorsCrossoverType = tuple_list_type!(CrossoverMutator); /// Mapped mutators for integer-like inputs that implement some form of crossover. -pub type MappedIntMutatorsCrossoverType = tuple_list_type!(MappedCrossoverMutator); +pub type MappedIntMutatorsCrossoverType = tuple_list_type!(MappedCrossoverMutator); /// Mutators for integer-like inputs without crossover mutations pub type IntMutatorsNoCrossoverType = tuple_list_type!( @@ -64,7 +65,9 @@ pub fn int_mutators_crossover() -> IntMutatorsCrossoverType { /// Mutators for integer-like inputs that implement some form of crossover with a mapper to extract the crossed over information. #[must_use] -pub fn mapped_int_mutators_crossover(input_mapper: F) -> MappedIntMutatorsCrossoverType { +pub fn mapped_int_mutators_crossover( + input_mapper: F, +) -> MappedIntMutatorsCrossoverType { tuple_list!(MappedCrossoverMutator::new(input_mapper)) } @@ -77,14 +80,14 @@ pub fn int_mutators() -> IntMutatorsType { } /// Mapped mutators for integer-like inputs -pub type MappedIntMutatorsType = tuple_list_type!( +pub type MappedIntMutatorsType = tuple_list_type!( MappingMutator, MappingMutator, MappingMutator, MappingMutator, MappingMutator, MappingMutator, - MappingMutator,F1> + MappingMutator,F1> ); /// Mapped mutators for integer-like inputs @@ -93,7 +96,7 @@ pub type MappedIntMutatorsType = tuple_list_type!( pub fn mapped_int_mutators( current_input_mapper: F1, input_from_corpus_mapper: F2, -) -> MappedIntMutatorsType +) -> MappedIntMutatorsType where F1: Clone + FnMut(&mut IO) -> &mut II, { @@ -365,8 +368,7 @@ pub struct CrossoverMutator; impl Mutator for CrossoverMutator where - S: HasRand + HasCorpus, - S::Corpus: Corpus, + S: HasRand + HasCorpus, I: Copy, { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { @@ -389,24 +391,28 @@ impl Named for CrossoverMutator { } /// Crossover mutation for integer-like inputs with custom state extraction function #[derive(Debug)] -pub struct MappedCrossoverMutator { +pub struct MappedCrossoverMutator { input_mapper: F, + phantom: PhantomData, } -impl MappedCrossoverMutator { +impl MappedCrossoverMutator { /// Create a new [`MappedCrossoverMutator`] pub fn new(input_mapper: F) -> Self { - Self { input_mapper } + Self { + input_mapper, + phantom: PhantomData, + } } } -impl Mutator for MappedCrossoverMutator +impl Mutator for MappedCrossoverMutator where - S: HasRand + HasCorpus, - for<'b> F: Fn(&'b ::Input) -> &'b I, - I: Clone, + S: HasRand + HasCorpus, + for<'b> F: Fn(&'b I) -> &'b O, + O: Clone, { - fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { + fn mutate(&mut self, state: &mut S, input: &mut O) -> Result { let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut()); if state.corpus().current().is_some_and(|cur| cur == id) { @@ -421,7 +427,7 @@ where } } -impl Named for MappedCrossoverMutator { +impl Named for MappedCrossoverMutator { fn name(&self) -> &Cow<'static, str> { &Cow::Borrowed("MappedCrossoverMutator") } diff --git a/libafl/src/mutators/scheduled.rs b/libafl/src/mutators/scheduled.rs index 79c6cfd3fd..accc26aca2 100644 --- a/libafl/src/mutators/scheduled.rs +++ b/libafl/src/mutators/scheduled.rs @@ -215,7 +215,7 @@ impl Named for LoggerScheduledMutator { impl Mutator for LoggerScheduledMutator where - S: HasRand + HasCorpus, + S: HasRand + HasCorpus, SM: ScheduledMutator, SM::Mutations: MutatorsTuple + NamedTuple, { @@ -258,7 +258,7 @@ where impl ScheduledMutator for LoggerScheduledMutator where - S: HasRand + HasCorpus, + S: HasRand + HasCorpus, SM: ScheduledMutator, SM::Mutations: MutatorsTuple + NamedTuple, { diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index e56b118f4a..884b10bd1e 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -31,7 +31,7 @@ use crate::{ }, observers::cmp::{AFLppCmpValuesMetadata, CmpValues, CmpValuesMetadata}, stages::TaintMetadata, - state::{HasCorpus, HasMaxSize, HasRand}, + state::{HasMaxSize, HasRand}, Error, HasMetadata, }; @@ -1305,7 +1305,7 @@ impl AFLppRedQueen { impl MultiMutator for AFLppRedQueen where - S: HasMetadata + HasRand + HasMaxSize + HasCorpus + HasCurrentCorpusId, + S: HasMetadata + HasRand + HasMaxSize + HasCurrentCorpusId, I: HasMutatorResizableBytes + From>, { #[expect(clippy::needless_range_loop, clippy::too_many_lines)] diff --git a/libafl/src/mutators/unicode/mod.rs b/libafl/src/mutators/unicode/mod.rs index ef7dd90edb..fab05c534c 100644 --- a/libafl/src/mutators/unicode/mod.rs +++ b/libafl/src/mutators/unicode/mod.rs @@ -10,7 +10,7 @@ use core::{ use libafl_bolts::{rands::Rand, Error, HasLen, Named}; use crate::{ - corpus::{Corpus, CorpusId, HasTestcase, Testcase}, + corpus::{CorpusId, HasTestcase, Testcase}, inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes}, mutators::{rand_range, MutationResult, Mutator, Tokens}, nonzero, @@ -32,8 +32,7 @@ pub type UnicodeInput = (BytesInput, UnicodeIdentificationMetadata); impl MutatedTransform for UnicodeInput where - S: HasCorpus + HasTestcase, - S::Corpus: Corpus, + S: HasCorpus + HasTestcase, { type Post = UnicodeIdentificationMetadata; @@ -50,7 +49,7 @@ where impl MutatedTransformPost for UnicodeIdentificationMetadata where - S: HasTestcase, + S: HasTestcase, { fn post_exec(self, state: &mut S, corpus_id: Option) -> Result<(), Error> { if let Some(corpus_id) = corpus_id { diff --git a/libafl/src/schedulers/accounting.rs b/libafl/src/schedulers/accounting.rs index 23bb60d2c0..cd3e4b96a1 100644 --- a/libafl/src/schedulers/accounting.rs +++ b/libafl/src/schedulers/accounting.rs @@ -104,17 +104,17 @@ impl TopAccountingMetadata { /// A minimizer scheduler using coverage accounting #[derive(Debug)] -pub struct CoverageAccountingScheduler<'a, CS, O> { +pub struct CoverageAccountingScheduler<'a, CS, I, O> { accounting_map: &'a [u32], skip_non_favored_prob: f64, - inner: IndexesLenTimeMinimizerScheduler, + inner: IndexesLenTimeMinimizerScheduler, } -impl Scheduler<::Input, S> for CoverageAccountingScheduler<'_, CS, O> +impl Scheduler for CoverageAccountingScheduler<'_, CS, I, O> where - CS: Scheduler<::Input, S>, - S: HasCorpus + HasMetadata + HasRand, - ::Input: HasLen, + CS: Scheduler, + S: HasCorpus + HasMetadata + HasRand, + I: HasLen, O: CanTrack, { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { @@ -122,12 +122,7 @@ where self.inner.on_add(state, id) } - fn on_evaluation( - &mut self, - state: &mut S, - input: &::Input, - observers: &OT, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error> where OT: MatchName, { @@ -173,7 +168,7 @@ where } } -impl<'a, CS, O> CoverageAccountingScheduler<'a, CS, O> +impl<'a, CS, I, O> CoverageAccountingScheduler<'a, CS, I, O> where O: CanTrack, { @@ -181,7 +176,7 @@ where #[expect(clippy::cast_possible_wrap)] pub fn update_accounting_score(&self, state: &mut S, id: CorpusId) -> Result<(), Error> where - S: HasCorpus + HasMetadata, + S: HasCorpus + HasMetadata, { let mut indexes = vec![]; let mut new_favoreds = vec![]; @@ -268,7 +263,7 @@ where /// Cull the `Corpus` pub fn accounting_cull(&self, state: &S) -> Result<(), Error> where - S: HasCorpus + HasMetadata, + S: HasCorpus + HasMetadata, { let Some(top_rated) = state.metadata_map().get::() else { return Ok(()); diff --git a/libafl/src/schedulers/minimizer.rs b/libafl/src/schedulers/minimizer.rs index 17f6dcc307..3dccfb0121 100644 --- a/libafl/src/schedulers/minimizer.rs +++ b/libafl/src/schedulers/minimizer.rs @@ -72,28 +72,26 @@ impl Default for TopRatedsMetadata { /// /// E.g., it can use all the coverage seen so far to prioritize [`Testcase`]`s` using a [`TestcaseScore`]. #[derive(Debug, Clone)] -pub struct MinimizerScheduler { +pub struct MinimizerScheduler { base: CS, skip_non_favored_prob: f64, remove_metadata: bool, - phantom: PhantomData<(F, M, S)>, + phantom: PhantomData<(F, I, M, S)>, } -impl RemovableScheduler<::Input, S> - for MinimizerScheduler +impl RemovableScheduler for MinimizerScheduler where - CS: RemovableScheduler<::Input, S> - + Scheduler<::Input, S>, - F: TestcaseScore, + CS: RemovableScheduler + Scheduler, + F: TestcaseScore, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, - S: HasCorpus + HasMetadata + HasRand, + S: HasCorpus + HasMetadata + HasRand, { /// Replaces the [`Testcase`] at the given [`CorpusId`] fn on_replace( &mut self, state: &mut S, id: CorpusId, - testcase: &Testcase<::Input>, + testcase: &Testcase, ) -> Result<(), Error> { self.base.on_replace(state, id, testcase)?; self.update_score(state, id) @@ -104,7 +102,7 @@ where &mut self, state: &mut S, id: CorpusId, - testcase: &Option::Input>>, + testcase: &Option>, ) -> Result<(), Error> { self.base.on_remove(state, id, testcase)?; let mut entries = @@ -188,12 +186,12 @@ where } } -impl Scheduler<::Input, S> for MinimizerScheduler +impl Scheduler for MinimizerScheduler where - CS: Scheduler<::Input, S>, - F: TestcaseScore, + CS: Scheduler, + F: TestcaseScore, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, - S: HasCorpus + HasMetadata + HasRand, + S: HasCorpus + HasMetadata + HasRand, { /// Called when a [`Testcase`] is added to the corpus fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { @@ -202,12 +200,7 @@ where } /// An input has been evaluated - fn on_evaluation( - &mut self, - state: &mut S, - input: &::Input, - observers: &OT, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error> where OT: MatchName, { @@ -243,7 +236,7 @@ where } } -impl MinimizerScheduler +impl MinimizerScheduler where M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, { @@ -251,8 +244,8 @@ where #[expect(clippy::cast_possible_wrap)] pub fn update_score(&self, state: &mut S, id: CorpusId) -> Result<(), Error> where - F: TestcaseScore, - S: HasCorpus + HasMetadata, + F: TestcaseScore, + S: HasCorpus + HasMetadata, { // Create a new top rated meta if not existing if state.metadata_map().get::().is_none() { @@ -328,7 +321,7 @@ where /// Cull the [`Corpus`] using the [`MinimizerScheduler`] pub fn cull(&self, state: &S) -> Result<(), Error> where - S: HasCorpus + HasMetadata, + S: HasCorpus + HasMetadata, { let Some(top_rated) = state.metadata_map().get::() else { return Ok(()); @@ -356,7 +349,7 @@ where Ok(()) } } -impl HasQueueCycles for MinimizerScheduler +impl HasQueueCycles for MinimizerScheduler where CS: HasQueueCycles, { @@ -364,7 +357,7 @@ where self.base.queue_cycles() } } -impl MinimizerScheduler +impl MinimizerScheduler where O: CanTrack, { @@ -425,10 +418,10 @@ where } /// A [`MinimizerScheduler`] with [`LenTimeMulTestcaseScore`] to prioritize quick and small [`Testcase`]`s`. -pub type LenTimeMinimizerScheduler = - MinimizerScheduler; +pub type LenTimeMinimizerScheduler = + MinimizerScheduler; /// A [`MinimizerScheduler`] with [`LenTimeMulTestcaseScore`] to prioritize quick and small [`Testcase`]`s` /// that exercise all the entries registered in the [`MapIndexesMetadata`]. -pub type IndexesLenTimeMinimizerScheduler = - MinimizerScheduler; +pub type IndexesLenTimeMinimizerScheduler = + MinimizerScheduler; diff --git a/libafl/src/schedulers/mod.rs b/libafl/src/schedulers/mod.rs index 8d6add0f28..f340703ba7 100644 --- a/libafl/src/schedulers/mod.rs +++ b/libafl/src/schedulers/mod.rs @@ -66,14 +66,14 @@ pub trait RemovableScheduler { } /// Called when a [`Testcase`] is evaluated -pub fn on_add_metadata_default( +pub fn on_add_metadata_default( scheduler: &mut CS, state: &mut S, id: CorpusId, ) -> Result<(), Error> where CS: AflScheduler, - S: HasTestcase + HasCorpus, + S: HasTestcase + HasCorpus, { let current_id = *state.corpus().current(); @@ -131,9 +131,9 @@ where } /// Called when choosing the next [`Testcase`] -pub fn on_next_metadata_default(state: &mut S) -> Result<(), Error> +pub fn on_next_metadata_default(state: &mut S) -> Result<(), Error> where - S: HasCorpus + HasTestcase, + S: HasCorpus + HasTestcase, { let current_id = *state.corpus().current(); @@ -215,7 +215,7 @@ pub struct RandScheduler { impl Scheduler for RandScheduler where - S: HasCorpus + HasRand, + S: HasCorpus + HasRand, { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { // Set parent id diff --git a/libafl/src/schedulers/powersched.rs b/libafl/src/schedulers/powersched.rs index 28a382954a..5bb646398b 100644 --- a/libafl/src/schedulers/powersched.rs +++ b/libafl/src/schedulers/powersched.rs @@ -326,7 +326,7 @@ impl HasQueueCycles for PowerQueueScheduler { impl Scheduler for PowerQueueScheduler where - S: HasCorpus + HasMetadata + HasTestcase, + S: HasCorpus + HasMetadata + HasTestcase, O: Hash, C: AsRef, { diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs index a7772a232f..dccc63e082 100644 --- a/libafl/src/schedulers/probabilistic_sampling.rs +++ b/libafl/src/schedulers/probabilistic_sampling.rs @@ -63,10 +63,10 @@ impl ProbabilitySamplingScheduler { } /// Calculate the score and store in `ProbabilityMetadata` - pub fn store_probability(&self, state: &mut S, id: CorpusId) -> Result<(), Error> + pub fn store_probability(&self, state: &mut S, id: CorpusId) -> Result<(), Error> where - F: TestcaseScore, - S: HasCorpus + HasMetadata + HasRand, + F: TestcaseScore, + S: HasCorpus + HasMetadata + HasRand, { let prob = F::compute(state, &mut *state.corpus().get(id)?.borrow_mut())?; debug_assert!( @@ -83,16 +83,16 @@ impl ProbabilitySamplingScheduler { } } -impl RemovableScheduler<::Input, S> for ProbabilitySamplingScheduler +impl RemovableScheduler for ProbabilitySamplingScheduler where - F: TestcaseScore, - S: HasCorpus + HasMetadata + HasRand, + F: TestcaseScore, + S: HasCorpus + HasMetadata + HasRand, { fn on_remove( &mut self, state: &mut S, id: CorpusId, - _testcase: &Option::Input>>, + _testcase: &Option>, ) -> Result<(), Error> { let meta = state .metadata_map_mut() @@ -108,7 +108,7 @@ where &mut self, state: &mut S, id: CorpusId, - _prev: &Testcase<::Input>, + _prev: &Testcase, ) -> Result<(), Error> { let meta = state .metadata_map_mut() @@ -122,10 +122,10 @@ where } } -impl Scheduler<::Input, S> for ProbabilitySamplingScheduler +impl Scheduler for ProbabilitySamplingScheduler where - F: TestcaseScore, - S: HasCorpus + HasMetadata + HasRand, + F: TestcaseScore, + S: HasCorpus + HasMetadata + HasRand, { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { let current_id = *state.corpus().current(); @@ -202,14 +202,11 @@ mod tests { #[derive(Debug, Clone)] pub struct UniformDistribution {} - impl TestcaseScore for UniformDistribution + impl TestcaseScore for UniformDistribution where - S: HasCorpus, + S: HasCorpus, { - fn compute( - _state: &S, - _: &mut Testcase<::Input>, - ) -> Result { + fn compute(_state: &S, _: &mut Testcase) -> Result { Ok(FACTOR) } } diff --git a/libafl/src/schedulers/queue.rs b/libafl/src/schedulers/queue.rs index 8787eb5379..640228d2a7 100644 --- a/libafl/src/schedulers/queue.rs +++ b/libafl/src/schedulers/queue.rs @@ -20,7 +20,7 @@ impl RemovableScheduler for QueueScheduler {} impl Scheduler for QueueScheduler where - S: HasCorpus, + S: HasCorpus, { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { // Set parent id diff --git a/libafl/src/schedulers/testcase_score.rs b/libafl/src/schedulers/testcase_score.rs index b6a2e77d30..3abf911526 100644 --- a/libafl/src/schedulers/testcase_score.rs +++ b/libafl/src/schedulers/testcase_score.rs @@ -15,13 +15,9 @@ use crate::{ }; /// Compute the favor factor of a [`Testcase`]. Higher is better. -pub trait TestcaseScore -where - S: HasCorpus, -{ +pub trait TestcaseScore { /// Computes the favor factor of a [`Testcase`]. Higher is better. - fn compute(state: &S, entry: &mut Testcase<::Input>) - -> Result; + fn compute(state: &S, entry: &mut Testcase) -> Result; } /// Multiply the testcase size with the execution time. @@ -29,16 +25,13 @@ where #[derive(Debug, Clone)] pub struct LenTimeMulTestcaseScore {} -impl TestcaseScore for LenTimeMulTestcaseScore +impl TestcaseScore for LenTimeMulTestcaseScore where - S: HasCorpus, - ::Input: HasLen, + S: HasCorpus, + I: HasLen, { #[expect(clippy::cast_precision_loss)] - fn compute( - state: &S, - entry: &mut Testcase<::Input>, - ) -> Result { + fn compute(state: &S, entry: &mut Testcase) -> Result { // TODO maybe enforce entry.exec_time().is_some() Ok(entry.exec_time().map_or(1, |d| d.as_millis()) as f64 * entry.load_len(state.corpus())? as f64) @@ -55,16 +48,13 @@ const HAVOC_MAX_MULT: f64 = 64.0; #[derive(Debug, Clone)] pub struct CorpusPowerTestcaseScore {} -impl TestcaseScore for CorpusPowerTestcaseScore +impl TestcaseScore for CorpusPowerTestcaseScore where - S: HasCorpus + HasMetadata, + S: HasCorpus + HasMetadata, { /// Compute the `power` we assign to each corpus entry #[expect(clippy::cast_precision_loss, clippy::too_many_lines)] - fn compute( - state: &S, - entry: &mut Testcase<::Input>, - ) -> Result { + fn compute(state: &S, entry: &mut Testcase) -> Result { let psmeta = state.metadata::()?; let fuzz_mu = if let Some(strat) = psmeta.strat() { @@ -272,16 +262,13 @@ where #[derive(Debug, Clone)] pub struct CorpusWeightTestcaseScore {} -impl TestcaseScore for CorpusWeightTestcaseScore +impl TestcaseScore for CorpusWeightTestcaseScore where - S: HasCorpus + HasMetadata, + S: HasCorpus + HasMetadata, { /// Compute the `weight` used in weighted corpus entry selection algo #[expect(clippy::cast_precision_loss)] - fn compute( - state: &S, - entry: &mut Testcase<::Input>, - ) -> Result { + fn compute(state: &S, entry: &mut Testcase) -> Result { let mut weight = 1.0; let psmeta = state.metadata::()?; diff --git a/libafl/src/schedulers/tuneable.rs b/libafl/src/schedulers/tuneable.rs index 7505cc1ccf..fb6dc11c39 100644 --- a/libafl/src/schedulers/tuneable.rs +++ b/libafl/src/schedulers/tuneable.rs @@ -90,9 +90,9 @@ impl TuneableScheduler { } /// Gets the current corpus entry id - pub fn get_current(state: &S) -> CorpusId + pub fn get_current(state: &S) -> CorpusId where - S: HasCorpus, + S: HasCorpus, { state .corpus() @@ -105,7 +105,7 @@ impl RemovableScheduler for TuneableScheduler {} impl Scheduler for TuneableScheduler where - S: HasCorpus + HasMetadata, + S: HasCorpus + HasMetadata, { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { // Set parent id diff --git a/libafl/src/schedulers/weighted.rs b/libafl/src/schedulers/weighted.rs index c4a3720ae0..ff652e7456 100644 --- a/libafl/src/schedulers/weighted.rs +++ b/libafl/src/schedulers/weighted.rs @@ -155,10 +155,10 @@ where /// Create a new alias table when the fuzzer finds a new corpus entry #[expect(clippy::cast_precision_loss)] - pub fn create_alias_table(&self, state: &mut S) -> Result<(), Error> + pub fn create_alias_table(&self, state: &mut S) -> Result<(), Error> where - F: TestcaseScore, - S: HasCorpus + HasMetadata, + F: TestcaseScore, + S: HasCorpus + HasMetadata, { let n = state.corpus().count(); @@ -303,12 +303,12 @@ impl HasQueueCycles for WeightedScheduler { } } -impl Scheduler<::Input, S> for WeightedScheduler +impl Scheduler for WeightedScheduler where C: AsRef + Named, - F: TestcaseScore, + F: TestcaseScore, O: Hash, - S: HasCorpus + HasMetadata + HasRand + HasTestcase, + S: HasCorpus + HasMetadata + HasRand + HasTestcase, { /// Called when a [`Testcase`] is added to the corpus fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { @@ -317,12 +317,7 @@ where Ok(()) } - fn on_evaluation( - &mut self, - state: &mut S, - _input: &::Input, - observers: &OT, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, _input: &I, observers: &OT) -> Result<(), Error> where OT: MatchName, { diff --git a/libafl/src/stages/afl_stats.rs b/libafl/src/stages/afl_stats.rs index b68005f71a..b118e5fe10 100644 --- a/libafl/src/stages/afl_stats.rs +++ b/libafl/src/stages/afl_stats.rs @@ -75,7 +75,7 @@ libafl_bolts::impl_serdeany!(FuzzTime); /// The [`AflStatsStage`] is a Stage that calculates and writes /// AFL++'s `fuzzer_stats` and `plot_data` information. #[derive(Debug, Clone)] -pub struct AflStatsStage { +pub struct AflStatsStage { map_observer_handle: Handle, stats_file_path: Option, plot_file_path: Option, @@ -114,7 +114,7 @@ pub struct AflStatsStage { autotokens_enabled: bool, /// The core we are bound to core_id: CoreId, - phantom_data: PhantomData<(O, E, EM, S, Z)>, + phantom_data: PhantomData<(E, EM, I, O, S, Z)>, } /// AFL++'s `fuzzer_stats` @@ -236,13 +236,14 @@ pub struct AFLPlotData<'a> { edges_found: &'a u64, } -impl Stage for AflStatsStage +impl Stage for AflStatsStage where + C: AsRef + Named, E: HasObservers, - EM: EventFirer<::Input, S>, - Z: HasScheduler<::Input, S>, + EM: EventFirer, + Z: HasScheduler, S: HasImported - + HasCorpus + + HasCorpus + HasMetadata + HasStartTime + HasExecutions @@ -441,17 +442,17 @@ where } } -impl AflStatsStage +impl AflStatsStage where E: HasObservers, - EM: EventFirer<::Input, S>, - S: HasImported + HasCorpus + HasMetadata + HasExecutions, + EM: EventFirer, + S: HasImported + HasMetadata + HasExecutions, C: AsRef + Named, O: MapObserver, { /// Builder for `AflStatsStage` #[must_use] - pub fn builder() -> AflStatsStageBuilder { + pub fn builder() -> AflStatsStageBuilder { AflStatsStageBuilder::new() } @@ -479,13 +480,13 @@ where Ok(()) } - fn maybe_update_is_favored_size(&mut self, testcase: &Testcase<::Input>) { + fn maybe_update_is_favored_size(&mut self, testcase: &Testcase) { if testcase.has_metadata::() { self.is_favored_size += 1; } } - fn maybe_update_slowest_exec(&mut self, testcase: &Testcase<::Input>) { + fn maybe_update_slowest_exec(&mut self, testcase: &Testcase) { if let Some(exec_time) = testcase.exec_time() { if exec_time > &self.slowest_exec { self.slowest_exec = *exec_time; @@ -497,7 +498,7 @@ where self.has_fuzzed_size += 1; } - fn maybe_update_max_depth(&mut self, testcase: &Testcase<::Input>) { + fn maybe_update_max_depth(&mut self, testcase: &Testcase) { if let Ok(metadata) = testcase.metadata::() { if metadata.depth() > self.max_depth { self.max_depth = metadata.depth(); @@ -510,11 +511,7 @@ where } #[cfg(feature = "track_hit_feedbacks")] - fn maybe_update_last_crash( - &mut self, - testcase: &Testcase<::Input>, - state: &S, - ) { + fn maybe_update_last_crash(&mut self, testcase: &Testcase, state: &S) { #[cfg(feature = "track_hit_feedbacks")] if testcase .hit_objectives() @@ -526,11 +523,7 @@ where } #[cfg(feature = "track_hit_feedbacks")] - fn maybe_update_last_hang( - &mut self, - testcase: &Testcase<::Input>, - state: &S, - ) { + fn maybe_update_last_hang(&mut self, testcase: &Testcase, state: &S) { if testcase .hit_objectives() .contains(&Cow::Borrowed(TIMEOUT_FEEDBACK_NAME)) @@ -652,7 +645,7 @@ pub fn get_run_cmdline() -> Cow<'static, str> { /// The Builder for `AflStatsStage` #[derive(Debug)] -pub struct AflStatsStageBuilder { +pub struct AflStatsStageBuilder { stats_file_path: Option, plot_file_path: Option, core_id: Option, @@ -664,16 +657,16 @@ pub struct AflStatsStageBuilder { banner: String, version: String, target_mode: String, - phantom_data: PhantomData<(O, E, EM, S, Z)>, + phantom_data: PhantomData<(E, EM, I, O, S, Z)>, } -impl AflStatsStageBuilder +impl AflStatsStageBuilder where - E: HasObservers, - EM: EventFirer<::Input, S>, - S: HasImported + HasCorpus + HasMetadata + HasExecutions, C: AsRef + Named, + E: HasObservers, + EM: EventFirer, O: MapObserver, + S: HasImported + HasMetadata + HasExecutions, { fn new() -> Self { Self { @@ -785,7 +778,8 @@ where /// Cannot create the plot file (if provided) /// No `MapObserver` supplied to the builder /// No `stats_file_path` provieded - pub fn build(self) -> Result, Error> { + #[allow(clippy::type_complexity)] + pub fn build(self) -> Result, Error> { if self.map_observer_handle.is_none() { return Err(Error::illegal_argument("Must set `map_observer`")); } diff --git a/libafl/src/stages/calibrate.rs b/libafl/src/stages/calibrate.rs index 35f8aec8fc..f0eab61b9c 100644 --- a/libafl/src/stages/calibrate.rs +++ b/libafl/src/stages/calibrate.rs @@ -79,33 +79,33 @@ impl Default for UnstableEntriesMetadata { /// The calibration stage will measure the average exec time and the target's stability for this input. #[derive(Clone, Debug)] -pub struct CalibrationStage { +pub struct CalibrationStage { map_observer_handle: Handle, map_name: Cow<'static, str>, name: Cow<'static, str>, stage_max: usize, /// If we should track stability track_stability: bool, - phantom: PhantomData<(E, O, OT, S)>, + phantom: PhantomData<(E, I, O, OT, S)>, } -impl Stage for CalibrationStage +impl Stage for CalibrationStage where - E: Executor::Input, S, Z> + HasObservers, - EM: EventFirer<::Input, S>, + E: Executor + HasObservers, + EM: EventFirer, O: MapObserver, C: AsRef, for<'de> ::Entry: Serialize + Deserialize<'de> + 'static + Default + Debug + Bounded, - OT: ObserversTuple<::Input, S>, - S: HasCorpus + OT: ObserversTuple, + S: HasCorpus + HasMetadata + HasNamedMetadata + HasExecutions - + HasCurrentTestcase + + HasCurrentTestcase + HasCurrentCorpusId, - Z: Evaluator::Input, S>, - ::Input: Input, + Z: Evaluator, + I: Input, { #[inline] #[expect(clippy::too_many_lines, clippy::cast_precision_loss)] @@ -380,13 +380,12 @@ where } } -impl CalibrationStage +impl CalibrationStage where + C: AsRef, O: MapObserver, for<'it> O: AsIter<'it, Item = O::Entry>, - C: AsRef, - OT: ObserversTuple<::Input, S>, - S: HasCorpus, + OT: ObserversTuple, { /// Create a new [`CalibrationStage`]. #[must_use] @@ -419,7 +418,7 @@ where } } -impl Named for CalibrationStage { +impl Named for CalibrationStage { fn name(&self) -> &Cow<'static, str> { &self.name } diff --git a/libafl/src/stages/colorization.rs b/libafl/src/stages/colorization.rs index bccc4a35e9..295d98ca8e 100644 --- a/libafl/src/stages/colorization.rs +++ b/libafl/src/stages/colorization.rs @@ -15,10 +15,10 @@ use libafl_bolts::{ use serde::{Deserialize, Serialize}; use crate::{ - corpus::{Corpus, HasCurrentCorpusId}, + corpus::HasCurrentCorpusId, events::EventFirer, executors::{Executor, HasObservers}, - inputs::{HasMutatorBytes, HasMutatorResizableBytes}, + inputs::HasMutatorResizableBytes, mutators::mutations::buffer_copy, nonzero, observers::ObserversTuple, @@ -63,25 +63,25 @@ impl Ord for Earlier { pub const COLORIZATION_STAGE_NAME: &str = "colorization"; /// The mutational stage using power schedules #[derive(Clone, Debug)] -pub struct ColorizationStage { +pub struct ColorizationStage { map_observer_handle: Handle, name: Cow<'static, str>, - phantom: PhantomData<(E, EM, O, E, S, Z)>, + phantom: PhantomData<(E, EM, I, O, E, S, Z)>, } -impl Named for ColorizationStage { +impl Named for ColorizationStage { fn name(&self) -> &Cow<'static, str> { &self.name } } -impl Stage for ColorizationStage +impl Stage for ColorizationStage where - EM: EventFirer<::Input, S>, - E: HasObservers + Executor::Input, S, Z>, - S: HasCorpus + HasMetadata + HasRand + HasNamedMetadata + HasCurrentCorpusId, - E::Observers: ObserversTuple<::Input, S>, - ::Input: HasMutatorResizableBytes + Clone, + EM: EventFirer, + E: HasObservers + Executor, + S: HasCorpus + HasMetadata + HasRand + HasNamedMetadata + HasCurrentCorpusId, + E::Observers: ObserversTuple, + I: HasMutatorResizableBytes + Clone, O: Hash, C: AsRef + Named, { @@ -107,7 +107,7 @@ where } fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { - RetryCountRestartHelper::clear_progress(state, &self.name) + RetryCountRestartHelper::clear_progress::(state, &self.name) } } @@ -150,15 +150,15 @@ impl TaintMetadata { libafl_bolts::impl_serdeany!(TaintMetadata); -impl ColorizationStage +impl ColorizationStage where - EM: EventFirer<::Input, S>, + EM: EventFirer, O: Hash, C: AsRef + Named, - E: HasObservers + Executor::Input, S, Z>, - E::Observers: ObserversTuple<::Input, S>, - S: HasCorpus + HasMetadata + HasRand + HasCurrentCorpusId + HasCurrentTestcase, - ::Input: HasMutatorResizableBytes + Clone, + E: HasObservers + Executor, + E::Observers: ObserversTuple, + S: HasCorpus + HasMetadata + HasRand + HasCurrentCorpusId + HasCurrentTestcase, + I: HasMutatorResizableBytes + Clone, { #[inline] fn colorize( @@ -167,7 +167,7 @@ where state: &mut S, manager: &mut EM, observer_handle: &Handle, - ) -> Result<::Input, Error> { + ) -> Result { let mut input = state.current_input_cloned()?; // The backup of the input let backup = input.clone(); @@ -308,7 +308,7 @@ where executor: &mut E, state: &mut S, manager: &mut EM, - input: &::Input, + input: &I, observer_handle: &Handle, ) -> Result { executor.observers_mut().pre_exec_all(state, input)?; diff --git a/libafl/src/stages/concolic.rs b/libafl/src/stages/concolic.rs index ba820ab7bd..52949ac263 100644 --- a/libafl/src/stages/concolic.rs +++ b/libafl/src/stages/concolic.rs @@ -15,7 +15,7 @@ use libafl_bolts::{ #[cfg(all(feature = "concolic_mutation", feature = "introspection"))] use crate::monitors::PerfFeature; use crate::{ - corpus::{Corpus, HasCurrentCorpusId}, + corpus::HasCurrentCorpusId, executors::{Executor, HasObservers}, observers::{concolic::ConcolicObserver, ObserversTuple}, stages::{RetryCountRestartHelper, Stage, TracingStage}, @@ -32,29 +32,29 @@ use crate::{ /// Wraps a [`TracingStage`] to add concolic observing. #[derive(Clone, Debug)] -pub struct ConcolicTracingStage<'a, EM, TE, S, Z> { +pub struct ConcolicTracingStage<'a, EM, I, TE, S, Z> { name: Cow<'static, str>, - inner: TracingStage, + inner: TracingStage, observer_handle: Handle>, } /// The name for concolic tracer pub const CONCOLIC_TRACING_STAGE_NAME: &str = "concolictracing"; -impl Named for ConcolicTracingStage<'_, EM, TE, S, Z> { +impl Named for ConcolicTracingStage<'_, EM, I, TE, S, Z> { fn name(&self) -> &Cow<'static, str> { &self.name } } -impl Stage for ConcolicTracingStage<'_, EM, TE, S, Z> +impl Stage for ConcolicTracingStage<'_, EM, I, TE, S, Z> where - TE: Executor::Input, S, Z> + HasObservers, - TE::Observers: ObserversTuple<::Input, S>, + TE: Executor + HasObservers, + TE::Observers: ObserversTuple, S: HasExecutions - + HasCorpus + + HasCorpus + HasNamedMetadata - + HasCurrentTestcase + + HasCurrentTestcase + HasCurrentCorpusId + MaybeHasClientPerfMonitor, { @@ -89,11 +89,11 @@ where } } -impl<'a, EM, TE, S, Z> ConcolicTracingStage<'a, EM, TE, S, Z> { +impl<'a, EM, I, TE, S, Z> ConcolicTracingStage<'a, EM, I, TE, S, Z> { /// Creates a new default tracing stage using the given [`Executor`], observing traces from a /// [`ConcolicObserver`] with the given name. pub fn new( - inner: TracingStage, + inner: TracingStage, observer_handle: Handle>, ) -> Self { let observer_name = observer_handle.name().clone(); @@ -353,9 +353,9 @@ fn generate_mutations(iter: impl Iterator) -> Vec< /// A mutational stage that uses Z3 to solve concolic constraints attached to the [`crate::corpus::Testcase`] by the [`ConcolicTracingStage`]. #[cfg(feature = "concolic_mutation")] #[derive(Clone, Debug, Default)] -pub struct SimpleConcolicMutationalStage { +pub struct SimpleConcolicMutationalStage { name: Cow<'static, str>, - phantom: PhantomData, + phantom: PhantomData<(I, Z)>, } #[cfg(feature = "concolic_mutation")] @@ -367,22 +367,22 @@ static mut SIMPLE_CONCOLIC_MUTATIONAL_ID: usize = 0; pub const SIMPLE_CONCOLIC_MUTATIONAL_NAME: &str = "concolicmutation"; #[cfg(feature = "concolic_mutation")] -impl Named for SimpleConcolicMutationalStage { +impl Named for SimpleConcolicMutationalStage { fn name(&self) -> &Cow<'static, str> { &self.name } } #[cfg(feature = "concolic_mutation")] -impl Stage for SimpleConcolicMutationalStage +impl Stage for SimpleConcolicMutationalStage where - Z: Evaluator::Input, S>, - ::Input: HasMutatorBytes + Clone, + Z: Evaluator, + I: HasMutatorBytes + Clone, S: HasExecutions - + HasCorpus + + HasCorpus + HasMetadata + HasNamedMetadata - + HasCurrentTestcase + + HasCurrentTestcase + MaybeHasClientPerfMonitor + HasCurrentCorpusId, { @@ -434,7 +434,7 @@ where } #[cfg(feature = "concolic_mutation")] -impl SimpleConcolicMutationalStage { +impl SimpleConcolicMutationalStage { #[must_use] /// Construct this stage pub fn new() -> Self { diff --git a/libafl/src/stages/dump.rs b/libafl/src/stages/dump.rs index 32d8365d88..97e043c89b 100644 --- a/libafl/src/stages/dump.rs +++ b/libafl/src/stages/dump.rs @@ -35,20 +35,19 @@ impl_serdeany!(DumpToDiskMetadata); /// The [`DumpToDiskStage`] is a stage that dumps the corpus and the solutions to disk #[derive(Debug)] -pub struct DumpToDiskStage { +pub struct DumpToDiskStage { solutions_dir: PathBuf, corpus_dir: PathBuf, to_bytes: CB1, generate_filename: CB2, - phantom: PhantomData<(EM, S, Z)>, + phantom: PhantomData<(EM, I, S, Z)>, } -impl Stage for DumpToDiskStage +impl Stage for DumpToDiskStage where - CB1: FnMut(&Testcase<::Input>, &S) -> Vec, - CB2: FnMut(&Testcase<::Input>, &CorpusId) -> P, - S: HasCorpus + HasSolutions + HasRand + HasMetadata, - S::Solutions: Corpus::Input>, + CB1: FnMut(&Testcase, &S) -> Vec, + CB2: FnMut(&Testcase, &CorpusId) -> P, + S: HasCorpus + HasSolutions + HasRand + HasMetadata, P: AsRef, { #[inline] @@ -76,12 +75,10 @@ where } /// Implementation for `DumpToDiskStage` with a default `generate_filename` function. -impl - DumpToDiskStage::Input>, &CorpusId) -> String, EM, S, Z> +impl DumpToDiskStage, &CorpusId) -> String, EM, I, S, Z> where - S: HasCorpus + HasSolutions + HasRand + HasMetadata, - S::Solutions: Corpus::Input>, - ::Input: Input, + S: HasSolutions + HasRand + HasMetadata, + I: Input, { /// Create a new [`DumpToDiskStage`] with a default `generate_filename` function. pub fn new(to_bytes: CB1, corpus_dir: A, solutions_dir: B) -> Result @@ -99,10 +96,7 @@ where /// Default `generate_filename` function. #[expect(clippy::trivially_copy_pass_by_ref)] - fn generate_filename( - testcase: &Testcase<::Input>, - id: &CorpusId, - ) -> String { + fn generate_filename(testcase: &Testcase, id: &CorpusId) -> String { [ Some(id.0.to_string()), testcase.filename().clone(), @@ -119,10 +113,9 @@ where } } -impl DumpToDiskStage +impl DumpToDiskStage where - S: HasCorpus + HasMetadata + HasSolutions, - S::Solutions: Corpus::Input>, + S: HasMetadata + HasSolutions, { /// Create a new [`DumpToDiskStage`] with a custom `generate_filename` function. pub fn new_with_custom_filenames( @@ -165,8 +158,9 @@ where #[inline] fn dump_state_to_disk>(&mut self, state: &mut S) -> Result<(), Error> where - CB1: FnMut(&Testcase<::Input>, &S) -> Vec, - CB2: FnMut(&Testcase<::Input>, &CorpusId) -> P, + S: HasCorpus, + CB1: FnMut(&Testcase, &S) -> Vec, + CB2: FnMut(&Testcase, &CorpusId) -> P, { let (mut corpus_id, mut solutions_id) = if let Some(meta) = state.metadata_map().get::() { diff --git a/libafl/src/stages/generalization.rs b/libafl/src/stages/generalization.rs index 88d14c7f5a..75f101bf3a 100644 --- a/libafl/src/stages/generalization.rs +++ b/libafl/src/stages/generalization.rs @@ -51,32 +51,44 @@ pub static GENERALIZATION_STAGE_NAME: &str = "generalization"; /// A stage that runs a tracer executor #[derive(Clone, Debug)] -pub struct GeneralizationStage { +pub struct GeneralizationStage { name: Cow<'static, str>, map_observer_handle: Handle, - phantom: PhantomData<(EM, O, OT, S, Z)>, + phantom: PhantomData<(EM, I, O, OT, S, Z)>, } -impl Named for GeneralizationStage { +impl Named for GeneralizationStage { fn name(&self) -> &Cow<'static, str> { &self.name } } -impl Stage for GeneralizationStage +impl Stage + for GeneralizationStage where - O: MapObserver, C: CanTrack + AsRef + Named, E: Executor + HasObservers, E::Observers: ObserversTuple, + O: MapObserver, S: HasExecutions + HasMetadata - + HasCorpus + + HasCorpus + HasNamedMetadata + HasCurrentCorpusId + MaybeHasClientPerfMonitor, - S::Corpus: Corpus, { + #[inline] + fn should_restart(&mut self, state: &mut S) -> Result { + // TODO: We need to be able to resume better if something crashes or times out + RetryCountRestartHelper::should_restart::(state, &self.name, 3) + } + + #[inline] + fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { + // TODO: We need to be able to resume better if something crashes or times out + RetryCountRestartHelper::clear_progress::(state, &self.name) + } + #[inline] #[expect(clippy::too_many_lines)] fn perform( @@ -326,26 +338,13 @@ where Ok(()) } - - #[inline] - fn should_restart(&mut self, state: &mut S) -> Result { - // TODO: We need to be able to resume better if something crashes or times out - RetryCountRestartHelper::should_restart(state, &self.name, 3) - } - - #[inline] - fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { - // TODO: We need to be able to resume better if something crashes or times out - RetryCountRestartHelper::clear_progress(state, &self.name) - } } -impl GeneralizationStage +impl GeneralizationStage where O: MapObserver, C: CanTrack + AsRef + Named, - S: HasExecutions + HasMetadata + HasCorpus + MaybeHasClientPerfMonitor, - S::Corpus: Corpus, + S: HasExecutions + HasMetadata + HasCorpus + MaybeHasClientPerfMonitor, OT: ObserversTuple, { /// Create a new [`GeneralizationStage`]. @@ -372,7 +371,7 @@ where input: &BytesInput, ) -> Result where - E: Executor::Input, S, Z> + HasObservers, + E: Executor + HasObservers, E::Observers: ObserversTuple, { start_timer!(state); @@ -414,7 +413,7 @@ where split_char: u8, ) -> Result<(), Error> where - E: Executor::Input, S, Z> + HasObservers, + E: Executor + HasObservers, { let mut start = 0; while start < payload.len() { @@ -452,7 +451,7 @@ where closing_char: u8, ) -> Result<(), Error> where - E: Executor::Input, S, Z> + HasObservers, + E: Executor + HasObservers, { let mut index = 0; while index < payload.len() { diff --git a/libafl/src/stages/generation.rs b/libafl/src/stages/generation.rs index 336b0aff54..bdcf3c656f 100644 --- a/libafl/src/stages/generation.rs +++ b/libafl/src/stages/generation.rs @@ -6,33 +6,27 @@ use core::marker::PhantomData; -use crate::{ - corpus::Corpus, - generators::Generator, - stages::Stage, - state::{HasCorpus, HasRand}, - Error, Evaluator, -}; +use crate::{generators::Generator, stages::Stage, state::HasRand, Error, Evaluator}; /// A [`Stage`] that generates a single input via a [`Generator`] and evaluates /// it using the fuzzer, possibly adding it to the corpus. /// /// This stage can be used to construct black-box (e.g., grammar-based) fuzzers. #[derive(Debug)] -pub struct GenStage(G, PhantomData<(S, Z)>); +pub struct GenStage(G, PhantomData<(I, S, Z)>); -impl GenStage { +impl GenStage { /// Create a new [`GenStage`]. pub fn new(g: G) -> Self { Self(g, PhantomData) } } -impl Stage for GenStage +impl Stage for GenStage where - Z: Evaluator::Input, S>, - S: HasCorpus + HasRand, - G: Generator<::Input, S>, + G: Generator, + S: HasRand, + Z: Evaluator, { #[inline] fn perform( diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 43bc885ddf..79c9f99a08 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -27,11 +27,10 @@ use crate::{ // TODO multi mutators stage /// Action performed after the un-transformed input is executed (e.g., updating metadata) -#[expect(unused_variables)] pub trait MutatedTransformPost: Sized { /// Perform any post-execution steps necessary for the transformed input (e.g., updating metadata) #[inline] - fn post_exec(self, state: &mut S, new_corpus_id: Option) -> Result<(), Error> { + fn post_exec(self, _state: &mut S, _new_corpus_id: Option) -> Result<(), Error> { Ok(()) } } @@ -43,10 +42,7 @@ impl MutatedTransformPost for () {} /// /// This trait is implemented such that all testcases inherently transform to their inputs, should /// the input be cloneable. -pub trait MutatedTransform: Sized -where - I: Input, -{ +pub trait MutatedTransform: Sized { /// Type indicating actions to be taken after the post-transformation input is executed type Post: MutatedTransformPost; @@ -60,9 +56,8 @@ where // reflexive definition impl MutatedTransform for I where - I: Input + Clone, - S: HasCorpus, - S::Corpus: Corpus, + I: Clone, + S: HasCorpus, { type Post = (); @@ -101,17 +96,17 @@ pub const DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128; /// The default mutational stage #[derive(Clone, Debug)] -pub struct StdMutationalStage { +pub struct StdMutationalStage { /// The name name: Cow<'static, str>, /// The mutator(s) to use mutator: M, /// The maximum amount of iterations we should do each round max_iterations: NonZeroUsize, - phantom: PhantomData<(E, EM, I, S, Z)>, + phantom: PhantomData<(E, EM, I1, I2, S, Z)>, } -impl MutationalStage for StdMutationalStage +impl MutationalStage for StdMutationalStage where S: HasRand, { @@ -140,25 +135,25 @@ static mut MUTATIONAL_STAGE_ID: usize = 0; /// The name for mutational stage pub static MUTATIONAL_STAGE_NAME: &str = "mutational"; -impl Named for StdMutationalStage { +impl Named for StdMutationalStage { fn name(&self) -> &Cow<'static, str> { &self.name } } -impl Stage for StdMutationalStage +impl Stage for StdMutationalStage where - M: Mutator, - Z: Evaluator::Input, S>, - S: HasCorpus - + HasRand + I1: Clone + MutatedTransform, + I2: Input, + M: Mutator, + S: HasRand + + HasCorpus + HasMetadata + HasExecutions + HasNamedMetadata + HasCurrentCorpusId + MaybeHasClientPerfMonitor, - I: MutatedTransform<::Input, S> + Clone, - ::Input: Input, + Z: Evaluator, { #[inline] fn perform( @@ -185,12 +180,12 @@ where } } -impl StdMutationalStage::Input, M, S, Z> +impl StdMutationalStage where - M: Mutator<::Input, S>, - Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + HasCurrentCorpusId + MaybeHasClientPerfMonitor, - ::Input: Input + Clone, + M: Mutator, + I: MutatedTransform + Input + Clone, + S: HasCorpus + HasRand + HasCurrentCorpusId + MaybeHasClientPerfMonitor, + Z: Evaluator, { /// Creates a new default mutational stage pub fn new(mutator: M) -> Self { @@ -205,13 +200,13 @@ where } } -impl StdMutationalStage +impl StdMutationalStage where - M: Mutator, - Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor, - I: MutatedTransform<::Input, S> + Clone, - ::Input: Input, + I1: MutatedTransform + Clone, + I2: Input, + M: Mutator, + S: HasCorpus + HasRand + HasCurrentCorpusId + MaybeHasClientPerfMonitor, + Z: Evaluator, { /// Creates a new transforming mutational stage with the default max iterations pub fn transforming(mutator: M) -> Self { @@ -236,7 +231,16 @@ where phantom: PhantomData, } } +} +impl StdMutationalStage +where + I1: MutatedTransform + Clone, + I2: Input, + M: Mutator, + S: HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor, + Z: Evaluator, +{ /// Runs this (mutational) stage for the given testcase fn perform_mutational( &mut self, @@ -256,7 +260,7 @@ where let num = self.iterations(state)?; let mut testcase = state.current_testcase_mut()?; - let Ok(input) = I::try_transform_from(&mut testcase, state) else { + let Ok(input) = I1::try_transform_from(&mut testcase, state) else { return Ok(()); }; drop(testcase); @@ -307,11 +311,10 @@ impl Named for MultiMutationalStage { impl Stage for MultiMutationalStage where + I: Clone + MutatedTransform, M: MultiMutator, - Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + HasNamedMetadata + HasCurrentTestcase + HasCurrentCorpusId, - I: MutatedTransform<::Input, S> + Clone, - ::Input: Input, + S: HasRand + HasNamedMetadata + HasCurrentTestcase + HasCurrentCorpusId, + Z: Evaluator, { #[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 9fb2ab8e9a..ea1ba45d77 100644 --- a/libafl/src/stages/power.rs +++ b/libafl/src/stages/power.rs @@ -11,10 +11,9 @@ use libafl_bolts::Named; #[cfg(feature = "introspection")] use crate::monitors::PerfFeature; use crate::{ - corpus::{Corpus, HasCurrentCorpusId}, + corpus::HasCurrentCorpusId, executors::{Executor, HasObservers}, fuzzer::Evaluator, - inputs::Input, mark_feature_time, mutators::{MutationResult, Mutator}, schedulers::{testcase_score::CorpusPowerTestcaseScore, TestcaseScore}, @@ -23,7 +22,7 @@ use crate::{ MutationalStage, RetryCountRestartHelper, Stage, }, start_timer, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor}, + state::{HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor}, Error, HasMetadata, HasNamedMetadata, }; @@ -48,8 +47,8 @@ impl Named for PowerMutationalStage impl MutationalStage for PowerMutationalStage where - S: HasCurrentTestcase, - F: TestcaseScore, + S: HasCurrentTestcase, + F: TestcaseScore, { type Mutator = M; /// The mutator, added to this stage @@ -77,20 +76,18 @@ where impl Stage for PowerMutationalStage where - E: Executor::Input, S, Z> + HasObservers, - F: TestcaseScore, + E: Executor + HasObservers, + F: TestcaseScore, M: Mutator, - S: HasCorpus - + HasMetadata + S: HasMetadata + HasRand + HasExecutions + HasNamedMetadata - + HasCurrentTestcase + + HasCurrentTestcase + HasCurrentCorpusId + MaybeHasClientPerfMonitor, - Z: Evaluator::Input, S>, - I: MutatedTransform<::Input, S> + Clone + Input, - ::Input: Input, + Z: Evaluator, + I: MutatedTransform + Clone, { #[inline] #[expect(clippy::let_and_return)] @@ -117,14 +114,12 @@ where impl PowerMutationalStage where - E: Executor::Input, S, Z> + HasObservers, - F: TestcaseScore, - I: Input, + E: Executor + HasObservers, + F: TestcaseScore, M: Mutator, - S: HasCorpus + HasMetadata + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor, - I: MutatedTransform<::Input, S> + Clone + Input, - Z: Evaluator::Input, S>, - ::Input: Input, + S: HasMetadata + HasRand + HasCurrentTestcase + MaybeHasClientPerfMonitor, + I: MutatedTransform + Clone, + Z: Evaluator, { /// Creates a new [`PowerMutationalStage`] pub fn new(mutator: M) -> Self { diff --git a/libafl/src/stages/push/mod.rs b/libafl/src/stages/push/mod.rs index 9837bad736..5ad8b6115b 100644 --- a/libafl/src/stages/push/mod.rs +++ b/libafl/src/stages/push/mod.rs @@ -23,7 +23,7 @@ pub use mutational::StdMutationalPushStage; use crate::{ common::HasNamedMetadata, - corpus::{Corpus, CorpusId, HasCurrentCorpusId}, + corpus::{CorpusId, HasCurrentCorpusId}, events::{EventFirer, EventRestarter, HasEventManagerId, ProgressReporter}, executors::{Executor, ExitKind, HasObservers}, observers::ObserversTuple, @@ -43,7 +43,7 @@ pub struct PushStageSharedState { pub fuzzer: Z, /// The event manager pub event_mgr: EM, - /// The [`crate::observers::ObserversTuple`] + /// The [`ObserversTuple`] pub observers: OT, phantom: PhantomData, } @@ -206,13 +206,13 @@ pub trait PushStage { /// Allows us to use a [`PushStage`] as a normal [`Stage`] #[derive(Debug)] -pub struct PushStageAdapter { +pub struct PushStageAdapter { name: Cow<'static, str>, push_stage: PS, - phantom: PhantomData<(CS, EM, OT, Z)>, + phantom: PhantomData<(CS, EM, I, OT, Z)>, } -impl PushStageAdapter { +impl PushStageAdapter { /// Create a new [`PushStageAdapter`], wrapping the given [`PushStage`] /// to be used as a normal [`Stage`] #[must_use] @@ -237,35 +237,43 @@ static mut PUSH_STAGE_ADAPTER_ID: usize = 0; /// The name for push stage adapter pub static PUSH_STAGE_ADAPTER_NAME: &str = "pushstageadapter"; -impl Named for PushStageAdapter { +impl Named for PushStageAdapter { #[must_use] fn name(&self) -> &Cow<'static, str> { &self.name } } -impl Stage for PushStageAdapter +impl Stage for PushStageAdapter where - CS: Scheduler<::Input, S>, + CS: Scheduler, S: HasExecutions + HasRand - + HasCorpus + + HasCorpus + HasLastReportTime + HasCurrentCorpusId + HasNamedMetadata + HasMetadata, - E: Executor::Input, S, Z> + HasObservers, - EM: EventFirer<::Input, S> - + EventRestarter - + HasEventManagerId - + ProgressReporter, - OT: ObserversTuple<::Input, S>, - PS: PushStage::Input, OT, S, Z>, - Z: ExecutesInput::Input, S> - + ExecutionProcessor::Input, OT, S> - + EvaluatorObservers::Input, OT> - + HasScheduler<::Input, S>, + E: Executor + HasObservers, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + OT: ObserversTuple, + PS: PushStage, + Z: ExecutesInput + + ExecutionProcessor + + EvaluatorObservers + + HasScheduler, { + #[inline] + fn should_restart(&mut self, state: &mut S) -> Result { + // TODO: Proper restart handling - call post_exec at the right time, etc... + RetryCountRestartHelper::no_retry(state, &self.name) + } + + #[inline] + fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { + RetryCountRestartHelper::clear_progress(state, &self.name) + } + fn perform( &mut self, fuzzer: &mut Z, @@ -309,15 +317,4 @@ where self.push_stage .deinit(fuzzer, state, event_mgr, &mut *executor.observers_mut()) } - - #[inline] - fn should_restart(&mut self, state: &mut S) -> Result { - // TODO: Proper restart handling - call post_exec at the right time, etc... - RetryCountRestartHelper::no_retry(state, &self.name) - } - - #[inline] - fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { - RetryCountRestartHelper::clear_progress(state, &self.name) - } } diff --git a/libafl/src/stages/push/mutational.rs b/libafl/src/stages/push/mutational.rs index a9aa086bd0..f38dcb2458 100644 --- a/libafl/src/stages/push/mutational.rs +++ b/libafl/src/stages/push/mutational.rs @@ -43,10 +43,10 @@ pub const DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128; /// /// The default mutational push stage #[derive(Clone, Debug)] -pub struct StdMutationalPushStage +pub struct StdMutationalPushStage where - S: HasCorpus, - ::Input: Clone + Debug, + S: HasCorpus, + I: Clone + Debug, { current_corpus_id: Option, testcases_to_do: usize, @@ -54,13 +54,13 @@ where mutator: M, - psh: PushStageHelper::Input, OT, S, Z>, + psh: PushStageHelper, } -impl StdMutationalPushStage +impl StdMutationalPushStage where - S: HasCorpus + HasRand, - ::Input: Clone + Debug, + S: HasCorpus + HasRand, + I: Clone + Debug, { /// Gets the number of iterations as a random number #[expect(clippy::unused_self, clippy::unnecessary_wraps)] // TODO: we should put this function into a trait later @@ -76,26 +76,22 @@ where } } -impl PushStage::Input, OT, S, Z> - for StdMutationalPushStage +impl PushStage for StdMutationalPushStage where - EM: EventFirer<::Input, S>, - Z: HasScheduler<::Input, S> - + ExecutionProcessor::Input, OT, S>, - S: HasCorpus + HasRand + MaybeHasClientPerfMonitor, - M: Mutator<::Input, S>, - OT: ObserversTuple<::Input, S> + Serialize, - ::Input: Input + Clone, + EM: EventFirer, + Z: HasScheduler + ExecutionProcessor, + S: HasCorpus + HasRand + MaybeHasClientPerfMonitor, + M: Mutator, + OT: ObserversTuple + Serialize, + I: Input + Clone, { #[inline] - fn push_stage_helper(&self) -> &PushStageHelper::Input, OT, S, Z> { + fn push_stage_helper(&self) -> &PushStageHelper { &self.psh } #[inline] - fn push_stage_helper_mut( - &mut self, - ) -> &mut PushStageHelper::Input, OT, S, Z> { + fn push_stage_helper_mut(&mut self) -> &mut PushStageHelper { &mut self.psh } @@ -125,7 +121,7 @@ where state: &mut S, _event_mgr: &mut EM, _observers: &mut OT, - ) -> Option::Input, Error>> { + ) -> Option> { if self.testcases_done >= self.testcases_to_do { // finished with this cicle. return None; @@ -160,7 +156,7 @@ where state: &mut S, event_mgr: &mut EM, observers: &mut OT, - last_input: ::Input, + last_input: I, exit_kind: ExitKind, ) -> Result<(), Error> { // todo: is_interesting, etc. @@ -188,51 +184,47 @@ where } } -impl Iterator for StdMutationalPushStage +impl Iterator for StdMutationalPushStage where - EM: ProgressReporter + EventFirer<::Input, S>, - S: HasCorpus + EM: ProgressReporter + EventFirer, + S: HasCorpus + HasMetadata + HasExecutions + HasLastReportTime + HasRand + MaybeHasClientPerfMonitor, - OT: ObserversTuple<::Input, S> + Serialize, - M: Mutator<::Input, S>, - ::Input: Clone + Debug + Input, - Z: HasScheduler<::Input, S> - + ExecutionProcessor::Input, OT, S>, + OT: ObserversTuple + Serialize, + M: Mutator, + I: Clone + Debug + Input, + Z: HasScheduler + ExecutionProcessor, { - type Item = Result<::Input, Error>; + type Item = Result; - fn next(&mut self) -> Option::Input, Error>> { + fn next(&mut self) -> Option> { self.next_std() } } -impl StdMutationalPushStage +impl StdMutationalPushStage where - EM: ProgressReporter + EventFirer<::Input, S>, - S: HasCorpus + EM: ProgressReporter + EventFirer, + S: HasCorpus + HasMetadata + HasExecutions + HasLastReportTime + HasRand + MaybeHasClientPerfMonitor, - OT: ObserversTuple<::Input, S> + Serialize, - M: Mutator<::Input, S>, - ::Input: Clone + Debug + Input, - Z: HasScheduler<::Input, S> - + ExecutionProcessor::Input, OT, S>, + OT: ObserversTuple + Serialize, + M: Mutator, + I: Clone + Debug + Input, + Z: HasScheduler + ExecutionProcessor, { /// Creates a new default mutational stage #[must_use] #[expect(clippy::type_complexity)] pub fn new( mutator: M, - shared_state: Rc< - RefCell::Input, OT, S, Z>>>, - >, + shared_state: Rc>>>, exit_kind: Rc>>, ) -> Self { Self { @@ -245,7 +237,7 @@ where } /// This is the implementation for `next` for this stage - pub fn next_std(&mut self) -> Option::Input, Error>> { + pub fn next_std(&mut self) -> Option> { let mut shared_state = { let shared_state_ref = &mut (*self.push_stage_helper_mut().shared_state).borrow_mut(); shared_state_ref.take().unwrap() diff --git a/libafl/src/stages/sync.rs b/libafl/src/stages/sync.rs index ed62544377..9d5c7033d0 100644 --- a/libafl/src/stages/sync.rs +++ b/libafl/src/stages/sync.rs @@ -52,31 +52,43 @@ impl SyncFromDiskMetadata { /// A stage that loads testcases from disk to sync with other fuzzers such as AFL++ #[derive(Debug)] -pub struct SyncFromDiskStage { +pub struct SyncFromDiskStage { name: Cow<'static, str>, sync_dirs: Vec, load_callback: CB, interval: Duration, - phantom: PhantomData<(E, EM, S, Z)>, + phantom: PhantomData<(E, EM, I, S, Z)>, } -impl Named for SyncFromDiskStage { +impl Named for SyncFromDiskStage { fn name(&self) -> &Cow<'static, str> { &self.name } } -impl Stage for SyncFromDiskStage +impl Stage for SyncFromDiskStage where - CB: FnMut(&mut Z, &mut S, &Path) -> Result<::Input, Error>, - Z: Evaluator::Input, S>, - S: HasCorpus + CB: FnMut(&mut Z, &mut S, &Path) -> Result, + Z: Evaluator, + S: HasCorpus + HasRand + HasMetadata + HasNamedMetadata + HasCurrentCorpusId + MaybeHasClientPerfMonitor, { + #[inline] + fn should_restart(&mut self, state: &mut S) -> Result { + // TODO: Needs proper crash handling for when an imported testcase crashes + // For now, Make sure we don't get stuck crashing on this testcase + RetryCountRestartHelper::no_retry(state, &self.name) + } + + #[inline] + fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { + RetryCountRestartHelper::clear_progress(state, &self.name) + } + #[inline] fn perform( &mut self, @@ -136,21 +148,9 @@ where Ok(()) } - - #[inline] - fn should_restart(&mut self, state: &mut S) -> Result { - // TODO: Needs proper crash handling for when an imported testcase crashes - // For now, Make sure we don't get stuck crashing on this testcase - RetryCountRestartHelper::no_retry(state, &self.name) - } - - #[inline] - fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { - RetryCountRestartHelper::clear_progress(state, &self.name) - } } -impl SyncFromDiskStage { +impl SyncFromDiskStage { /// Creates a new [`SyncFromDiskStage`] #[must_use] pub fn new(sync_dirs: Vec, load_callback: CB, interval: Duration, name: &str) -> Self { @@ -165,25 +165,21 @@ impl SyncFromDiskStage { } /// Function type when the callback in `SyncFromDiskStage` is not a lambda -pub type SyncFromDiskFunction = - fn(&mut Z, &mut S, &Path) -> Result<<::Corpus as Corpus>::Input, Error>; +pub type SyncFromDiskFunction = fn(&mut Z, &mut S, &Path) -> Result; -impl SyncFromDiskStage, E, EM, S, Z> +impl SyncFromDiskStage, E, EM, I, S, Z> where - S: HasCorpus, - ::Input: Input, - Z: Evaluator::Input, S>, + I: Input, + S: HasCorpus, + Z: Evaluator, { /// Creates a new [`SyncFromDiskStage`] invoking `Input::from_file` to load inputs #[must_use] pub fn with_from_file(sync_dirs: Vec, interval: Duration) -> Self { - fn load_callback( - _: &mut Z, - _: &mut S, - p: &Path, - ) -> Result<::Input, Error> + fn load_callback(_: &mut Z, _: &mut S, p: &Path) -> Result where - ::Input: Input, + I: Input, + S: HasCorpus, { Input::from_file(p) } @@ -191,7 +187,7 @@ where interval, name: Cow::Borrowed(SYNC_FROM_DISK_STAGE_NAME), sync_dirs, - load_callback: load_callback::<_, _>, + load_callback: load_callback::<_, _, _>, phantom: PhantomData, } } @@ -220,27 +216,38 @@ 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, { - client: LlmpEventConverter, + client: LlmpEventConverter, } -impl Stage for SyncFromBrokerStage +impl Stage for SyncFromBrokerStage where - 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>, - Z: EvaluatorObservers::Input, S> - + ExecutionProcessor::Input, E::Observers, S>, - IC: InputConverter::Input, To = DI>, - ICB: InputConverter::Input>, DI: Input, - <::Corpus as Corpus>::Input: Input + Clone, + EM: EventFirer, + E: HasObservers + Executor, + for<'a> E::Observers: Deserialize<'a>, + I: Input + Clone, + IC: InputConverter, + ICB: InputConverter, + S: HasExecutions + HasCorpus + HasRand + HasMetadata + Stoppable + MaybeHasClientPerfMonitor, + SP: ShMemProvider, + Z: EvaluatorObservers + ExecutionProcessor, { + #[inline] + fn should_restart(&mut self, _state: &mut S) -> Result { + // No restart handling needed - does not execute the target. + Ok(true) + } + + #[inline] + fn clear_progress(&mut self, _state: &mut S) -> Result<(), Error> { + // Not needed - does not execute the target. + Ok(()) + } + #[inline] fn perform( &mut self, @@ -298,27 +305,15 @@ where state.introspection_monitor_mut().finish_stage(); Ok(()) } - - #[inline] - fn should_restart(&mut self, _state: &mut S) -> Result { - // No restart handling needed - does not execute the target. - Ok(true) - } - - #[inline] - fn clear_progress(&mut self, _state: &mut S) -> Result<(), Error> { - // Not needed - does not execute the target. - Ok(()) - } } -impl SyncFromBrokerStage +impl SyncFromBrokerStage where 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 259149dbf3..5ee86acb1f 100644 --- a/libafl/src/stages/tmin.rs +++ b/libafl/src/stages/tmin.rs @@ -43,7 +43,7 @@ use crate::{ /// The default corpus entry minimising mutational stage #[derive(Clone, Debug)] -pub struct StdTMinMutationalStage { +pub struct StdTMinMutationalStage { /// The name name: Cow<'static, str>, /// The mutator(s) this stage uses @@ -54,39 +54,40 @@ pub struct StdTMinMutationalStage { runs: usize, /// The progress helper for this stage, keeping track of resumes after timeouts/crashes restart_helper: ExecutionCountRestartHelper, - phantom: PhantomData<(E, EM, F, S, Z)>, + phantom: PhantomData<(E, EM, F, I, S, Z)>, } -impl Stage for StdTMinMutationalStage +impl Stage + for StdTMinMutationalStage where - Z: HasScheduler<::Input, S> - + ExecutionProcessor::Input, E::Observers, S> - + ExecutesInput::Input, S> + Z: HasScheduler + + ExecutionProcessor + + ExecutesInput + HasFeedback, - Z::Scheduler: RemovableScheduler<::Input, S>, + Z::Scheduler: RemovableScheduler, E: HasObservers, - E::Observers: ObserversTuple<::Input, S> + Serialize, - EM: EventFirer<::Input, S>, + E::Observers: ObserversTuple + Serialize, + EM: EventFirer, FF: FeedbackFactory, - F: Feedback::Input, E::Observers, S>, + F: Feedback, S: HasMetadata + + HasCorpus + HasExecutions - + HasSolutions - + HasCorpus + + HasSolutions + HasMaxSize + HasNamedMetadata + HasCurrentCorpusId + MaybeHasClientPerfMonitor, - Z::Feedback: Feedback::Input, E::Observers, S>, - M: Mutator<::Input, S>, - <::Corpus as Corpus>::Input: Input + Hash + HasLen, + Z::Feedback: Feedback, + M: Mutator, + I: Input + Hash + HasLen, { fn should_restart(&mut self, state: &mut S) -> Result { self.restart_helper.should_restart(state, &self.name) } fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { - self.restart_helper.clear_progress(state, &self.name) + self.restart_helper.clear_progress::(state, &self.name) } fn perform( @@ -105,8 +106,8 @@ where } } -impl FeedbackFactory - for StdTMinMutationalStage +impl FeedbackFactory + for StdTMinMutationalStage where E: HasObservers, FF: FeedbackFactory, @@ -116,7 +117,7 @@ where } } -impl Named for StdTMinMutationalStage { +impl Named for StdTMinMutationalStage { fn name(&self) -> &Cow<'static, str> { &self.name } @@ -127,30 +128,30 @@ static mut TMIN_STAGE_ID: usize = 0; /// The name for tmin stage pub static TMIN_STAGE_NAME: &str = "tmin"; -impl StdTMinMutationalStage +impl StdTMinMutationalStage where - Z: HasScheduler<::Input, S> - + ExecutionProcessor::Input, E::Observers, S> - + ExecutesInput::Input, S> + Z: HasScheduler + + ExecutionProcessor + + ExecutesInput + HasFeedback, - Z::Scheduler: RemovableScheduler<::Input, S>, + Z::Scheduler: RemovableScheduler, E: HasObservers, - E::Observers: ObserversTuple<::Input, S> + Serialize, - EM: EventFirer<::Input, S>, + E::Observers: ObserversTuple + Serialize, + EM: EventFirer, FF: FeedbackFactory, - F: Feedback::Input, E::Observers, S>, + F: Feedback, S: HasMetadata + HasExecutions - + HasSolutions - + HasCorpus + + HasSolutions + + HasCorpus + HasMaxSize + HasNamedMetadata - + HasCurrentTestcase + + HasCurrentTestcase + HasCurrentCorpusId + MaybeHasClientPerfMonitor, - Z::Feedback: Feedback::Input, E::Observers, S>, - M: Mutator<::Input, S>, - ::Input: Hash + HasLen + Input, + Z::Feedback: Feedback, + M: Mutator, + I: Hash + HasLen + Input, { /// The list of mutators, added to this stage (as mutable ref) #[inline] @@ -189,10 +190,7 @@ where } start_timer!(state); - let transformed = ::Input::try_transform_from( - state.current_testcase_mut()?.borrow_mut(), - state, - )?; + let transformed = I::try_transform_from(state.current_testcase_mut()?.borrow_mut(), state)?; let mut base = state.current_input_cloned()?; // potential post operation if base is replaced by a shorter input let mut base_post = None; @@ -310,7 +308,7 @@ where } } -impl StdTMinMutationalStage { +impl StdTMinMutationalStage { /// Creates a new minimizing mutational stage that will minimize provided corpus entries pub fn new(mutator: M, factory: FF, runs: usize) -> Self { // unsafe but impossible that you create two threads both instantiating this instance @@ -391,12 +389,12 @@ where /// A feedback factory for ensuring that the values of the observers for minimized inputs are the same #[derive(Debug, Clone)] -pub struct ObserverEqualityFactory { +pub struct ObserverEqualityFactory { observer_handle: Handle, - phantom: PhantomData<(C, M, S)>, + phantom: PhantomData<(C, I, M, S)>, } -impl ObserverEqualityFactory +impl ObserverEqualityFactory where M: Hash, C: AsRef + Handled, @@ -410,7 +408,7 @@ where } } -impl HasObserverHandle for ObserverEqualityFactory { +impl HasObserverHandle for ObserverEqualityFactory { type Observer = C; fn observer_handle(&self) -> &Handle { @@ -418,13 +416,13 @@ impl HasObserverHandle for ObserverEqualityFactory { } } -impl FeedbackFactory, OT> - for ObserverEqualityFactory +impl FeedbackFactory, OT> + for ObserverEqualityFactory where M: Hash, C: AsRef + Handled, - OT: ObserversTuple<::Input, S>, - S: HasCorpus, + OT: ObserversTuple, + S: HasCorpus, { fn create_feedback(&self, observers: &OT) -> ObserverEqualityFeedback { let obs = observers diff --git a/libafl/src/stages/tracing.rs b/libafl/src/stages/tracing.rs index 149c96845d..7ab6116fd1 100644 --- a/libafl/src/stages/tracing.rs +++ b/libafl/src/stages/tracing.rs @@ -11,7 +11,7 @@ use libafl_bolts::Named; #[cfg(feature = "introspection")] use crate::monitors::PerfFeature; use crate::{ - corpus::{Corpus, HasCurrentCorpusId}, + corpus::HasCurrentCorpusId, executors::{Executor, HasObservers, ShadowExecutor}, inputs::Input, mark_feature_time, @@ -24,20 +24,20 @@ use crate::{ /// A stage that runs a tracer executor #[derive(Clone, Debug)] -pub struct TracingStage { +pub struct TracingStage { name: Cow<'static, str>, tracer_executor: TE, - phantom: PhantomData<(EM, TE, S, Z)>, + phantom: PhantomData<(EM, I, TE, S, Z)>, } -impl TracingStage +impl TracingStage where - TE: Executor::Input, S, Z> + HasObservers, - TE::Observers: ObserversTuple<::Input, S>, + TE: Executor + HasObservers, + TE::Observers: ObserversTuple, S: HasExecutions - + HasCorpus + + HasCorpus + HasNamedMetadata - + HasCurrentTestcase + + HasCurrentTestcase + MaybeHasClientPerfMonitor, { /// Perform tracing on the given `CorpusId`. Useful for if wrapping [`TracingStage`] with your @@ -72,16 +72,16 @@ where } } -impl Stage for TracingStage +impl Stage for TracingStage where - TE: Executor::Input, S, Z> + HasObservers, - TE::Observers: ObserversTuple<::Input, S>, + TE: Executor + HasObservers, + TE::Observers: ObserversTuple, S: HasExecutions - + HasCorpus + + HasCorpus + HasNamedMetadata + HasCurrentCorpusId + MaybeHasClientPerfMonitor, - ::Input: Input, + I: Input, { #[inline] fn perform( @@ -103,7 +103,7 @@ where } } -impl Named for TracingStage { +impl Named for TracingStage { fn name(&self) -> &Cow<'static, str> { &self.name } @@ -114,7 +114,7 @@ static mut TRACING_STAGE_ID: usize = 0; /// The name for tracing stage pub static TRACING_STAGE_NAME: &str = "tracing"; -impl TracingStage { +impl TracingStage { /// Creates a new default stage pub fn new(tracer_executor: TE) -> Self { // unsafe but impossible that you create two threads both instantiating this instance @@ -144,9 +144,9 @@ impl TracingStage { /// A stage that runs the shadow executor using also the shadow observers #[derive(Clone, Debug)] -pub struct ShadowTracingStage { +pub struct ShadowTracingStage { name: Cow<'static, str>, - phantom: PhantomData<(E, EM, SOT, S, Z)>, + phantom: PhantomData<(E, EM, I, SOT, S, Z)>, } /// The counter for giving this stage unique id @@ -154,31 +154,39 @@ static mut SHADOW_TRACING_STAGE_ID: usize = 0; /// Name for shadow tracing stage pub static SHADOW_TRACING_STAGE_NAME: &str = "shadow"; -impl Named for ShadowTracingStage { +impl Named for ShadowTracingStage { fn name(&self) -> &Cow<'static, str> { &self.name } } -impl Stage, EM, S, Z> - for ShadowTracingStage +impl Stage, EM, S, Z> + for ShadowTracingStage where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, - SOT: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, + SOT: ObserversTuple, S: HasExecutions - + HasCorpus + + HasCorpus + HasNamedMetadata + Debug - + HasCurrentTestcase + + HasCurrentTestcase + HasCurrentCorpusId + MaybeHasClientPerfMonitor, { + fn should_restart(&mut self, state: &mut S) -> Result { + RetryCountRestartHelper::no_retry(state, &self.name) + } + + fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { + RetryCountRestartHelper::clear_progress(state, &self.name) + } + #[inline] fn perform( &mut self, fuzzer: &mut Z, - executor: &mut ShadowExecutor, + executor: &mut ShadowExecutor, state: &mut S, manager: &mut EM, ) -> Result<(), Error> { @@ -209,24 +217,16 @@ where Ok(()) } - - fn should_restart(&mut self, state: &mut S) -> Result { - RetryCountRestartHelper::no_retry(state, &self.name) - } - - fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { - RetryCountRestartHelper::clear_progress(state, &self.name) - } } -impl ShadowTracingStage +impl ShadowTracingStage where - E: Executor::Input, S, Z> + HasObservers, - S: HasExecutions + HasCorpus, - SOT: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + S: HasExecutions + HasCorpus, + SOT: ObserversTuple, { /// Creates a new default stage - pub fn new(_executor: &mut ShadowExecutor) -> Self { + pub fn new(_executor: &mut ShadowExecutor) -> Self { // unsafe but impossible that you create two threads both instantiating this instance let stage_id = unsafe { let ret = SHADOW_TRACING_STAGE_ID; diff --git a/libafl/src/stages/tuneable.rs b/libafl/src/stages/tuneable.rs index 61677bd407..b72fbf412f 100644 --- a/libafl/src/stages/tuneable.rs +++ b/libafl/src/stages/tuneable.rs @@ -1,4 +1,4 @@ -//! A [`crate::stages::MutationalStage`] where the mutator iteration can be tuned at runtime +//! A [`MutationalStage`] where the mutator iteration can be tuned at runtime use alloc::string::{String, ToString}; use core::{marker::PhantomData, time::Duration}; @@ -9,8 +9,6 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "introspection")] use crate::monitors::PerfFeature; use crate::{ - corpus::Corpus, - inputs::Input, mark_feature_time, mutators::{MutationResult, Mutator}, nonzero, @@ -19,7 +17,7 @@ use crate::{ ExecutionCountRestartHelper, MutationalStage, Stage, }, start_timer, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor}, + state::{HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor}, Error, Evaluator, HasMetadata, HasNamedMetadata, }; @@ -149,7 +147,7 @@ where reset_by_name(state, STD_TUNEABLE_MUTATIONAL_STAGE_NAME) } -/// A [`crate::stages::MutationalStage`] where the mutator iteration can be tuned at runtime +/// A [`MutationalStage`] where the mutator iteration can be tuned at runtime #[derive(Clone, Debug)] pub struct TuneableMutationalStage { /// The mutator we use @@ -164,10 +162,9 @@ pub struct TuneableMutationalStage { impl MutationalStage for TuneableMutationalStage where M: Mutator, - Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + HasNamedMetadata + HasMetadata + HasExecutions + HasCurrentTestcase, - I: MutatedTransform<::Input, S> + Clone, - ::Input: Input, + Z: Evaluator, + S: HasRand + HasNamedMetadata + HasMetadata + HasExecutions + HasCurrentTestcase, + I: MutatedTransform + Clone, { type Mutator = M; /// The mutator, added to this stage @@ -196,16 +193,14 @@ where impl Stage for TuneableMutationalStage where M: Mutator, - Z: Evaluator::Input, S>, - S: HasCorpus - + HasRand + Z: Evaluator, + S: HasRand + HasNamedMetadata + HasMetadata + HasExecutions - + HasCurrentTestcase + + HasCurrentTestcase + MaybeHasClientPerfMonitor, - I: MutatedTransform<::Input, S> + Clone, - ::Input: Input, + I: MutatedTransform + Clone, { #[inline] fn perform( @@ -235,16 +230,14 @@ where impl TuneableMutationalStage where M: Mutator, - Z: Evaluator::Input, S>, - S: HasCorpus - + HasRand + Z: Evaluator, + S: HasRand + HasNamedMetadata + HasExecutions + HasMetadata - + HasCurrentTestcase + + HasCurrentTestcase + MaybeHasClientPerfMonitor, - I: MutatedTransform<::Input, S> + Clone, - ::Input: Input, + I: MutatedTransform + Clone, { /// Runs this (mutational) stage for the given `testcase` /// Exactly the same functionality as [`MutationalStage::perform_mutational`], but with added timeout support. @@ -466,8 +459,8 @@ where impl TuneableMutationalStage where M: Mutator, - Z: Evaluator::Input, S>, - S: HasCorpus + HasRand + HasNamedMetadata, + Z: Evaluator, + S: HasRand + HasNamedMetadata, { /// Creates a new transforming mutational stage #[must_use] diff --git a/libafl/src/stages/unicode.rs b/libafl/src/stages/unicode.rs index 873729230a..3f6247eae4 100644 --- a/libafl/src/stages/unicode.rs +++ b/libafl/src/stages/unicode.rs @@ -8,7 +8,6 @@ use libafl_bolts::{impl_serdeany, Error}; use serde::{Deserialize, Serialize}; use crate::{ - corpus::Corpus, inputs::{BytesInput, HasTargetBytes}, stages::Stage, state::{HasCorpus, HasCurrentTestcase}, @@ -71,17 +70,17 @@ pub(crate) fn extract_metadata(bytes: &[u8]) -> UnicodeIdentificationMetadata { /// Stage which identifies potential strings in the provided input #[derive(Debug)] -pub struct UnicodeIdentificationStage { - phantom: PhantomData, +pub struct UnicodeIdentificationStage { + phantom: PhantomData<(I, S)>, } -impl Default for UnicodeIdentificationStage { +impl Default for UnicodeIdentificationStage { fn default() -> Self { Self::new() } } -impl UnicodeIdentificationStage { +impl UnicodeIdentificationStage { /// Create a new instance of the string identification stage #[must_use] pub fn new() -> Self { @@ -91,8 +90,8 @@ impl UnicodeIdentificationStage { } fn identify_unicode_in_current_testcase(state: &mut S) -> Result<(), Error> where - S: HasCurrentTestcase, - ::Input: HasTargetBytes, + S: HasCurrentTestcase, + I: HasTargetBytes, { let mut tc = state.current_testcase_mut()?; if tc.has_metadata::() { @@ -109,21 +108,10 @@ impl UnicodeIdentificationStage { } } -impl Stage for UnicodeIdentificationStage +impl Stage for UnicodeIdentificationStage where - S: HasCorpus + HasCurrentTestcase, - S::Corpus: Corpus, + S: HasCorpus + HasCurrentTestcase, { - fn perform( - &mut self, - _fuzzer: &mut Z, - _executor: &mut E, - state: &mut S, - _manager: &mut EM, - ) -> Result<(), Error> { - UnicodeIdentificationStage::identify_unicode_in_current_testcase(state) - } - #[inline] fn should_restart(&mut self, _state: &mut S) -> Result { // Stage does not run the target. No reset helper needed. @@ -135,4 +123,14 @@ where // Stage does not run the target. No reset helper needed. Ok(()) } + + fn perform( + &mut self, + _fuzzer: &mut Z, + _executor: &mut E, + state: &mut S, + _manager: &mut EM, + ) -> Result<(), Error> { + UnicodeIdentificationStage::identify_unicode_in_current_testcase(state) + } } diff --git a/libafl/src/stages/verify_timeouts.rs b/libafl/src/stages/verify_timeouts.rs index ec2939cd59..281e479b22 100644 --- a/libafl/src/stages/verify_timeouts.rs +++ b/libafl/src/stages/verify_timeouts.rs @@ -10,12 +10,10 @@ use libafl_bolts::Error; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::{ - corpus::Corpus, executors::{Executor, HasObservers, HasTimeout}, inputs::BytesInput, observers::ObserversTuple, stages::Stage, - state::HasCorpus, Evaluator, HasMetadata, }; @@ -24,14 +22,14 @@ use crate::{ /// Note: Will NOT work with in process executors due to the potential for restarts/crashes when /// running inputs. #[derive(Debug)] -pub struct VerifyTimeoutsStage { +pub struct VerifyTimeoutsStage { doubled_timeout: Duration, original_timeout: Duration, capture_timeouts: Rc>, - phantom: PhantomData<(E, S)>, + phantom: PhantomData<(E, I, S)>, } -impl VerifyTimeoutsStage { +impl VerifyTimeoutsStage { /// Create a `VerifyTimeoutsStage` pub fn new(capture_timeouts: Rc>, configured_timeout: Duration) -> Self { Self { @@ -81,13 +79,13 @@ impl TimeoutsToVerify { } } -impl Stage for VerifyTimeoutsStage +impl Stage for VerifyTimeoutsStage where - E::Observers: ObserversTuple<::Input, S>, - E: Executor::Input, S, Z> + HasObservers + HasTimeout, - Z: Evaluator::Input, S>, - S: HasCorpus + HasMetadata, - ::Input: Debug + Serialize + DeserializeOwned + Default + 'static + Clone, + E::Observers: ObserversTuple, + E: Executor + HasObservers + HasTimeout, + Z: Evaluator, + S: HasMetadata, + I: Debug + Serialize + DeserializeOwned + Default + 'static + Clone, { fn perform( &mut self, @@ -97,7 +95,7 @@ where manager: &mut EM, ) -> Result<(), Error> { let mut timeouts = state - .metadata_or_insert_with(TimeoutsToVerify::<::Input>::new) + .metadata_or_insert_with(TimeoutsToVerify::::new) .clone(); if timeouts.count() == 0 { return Ok(()); @@ -109,10 +107,8 @@ where } executor.set_timeout(self.original_timeout); *self.capture_timeouts.borrow_mut() = true; - let res = state - .metadata_mut::::Input>>() - .unwrap(); - *res = TimeoutsToVerify::<::Input>::new(); + let res = state.metadata_mut::>().unwrap(); + *res = TimeoutsToVerify::::new(); Ok(()) } fn should_restart(&mut self, _state: &mut S) -> Result { diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index e9f9cbce39..0f61bae171 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -43,9 +43,9 @@ use crate::{ pub const DEFAULT_MAX_SIZE: usize = 1_048_576; /// Trait for elements offering a corpus -pub trait HasCorpus { +pub trait HasCorpus { /// The associated type implementing [`Corpus`]. - type Corpus: Corpus; + type Corpus: Corpus; /// The testcase corpus fn corpus(&self) -> &Self::Corpus; @@ -71,7 +71,7 @@ trait State: { } -impl State for StdState +impl State for StdState where C: Serialize + DeserializeOwned, R: Rand, @@ -79,22 +79,6 @@ where { } -// Reflexivity -impl HasCorpus for C -where - C: Corpus, -{ - type Corpus = Self; - - fn corpus(&self) -> &Self::Corpus { - self - } - - fn corpus_mut(&mut self) -> &mut Self::Corpus { - self - } -} - /// Interact with the maximum size pub trait HasMaxSize { /// The maximum size hint for items and mutations returned @@ -104,9 +88,9 @@ pub trait HasMaxSize { } /// Trait for elements offering a corpus of solutions -pub trait HasSolutions { +pub trait HasSolutions { /// The associated type implementing [`Corpus`] for solutions - type Solutions: Corpus; + type Solutions: Corpus; /// The solutions corpus fn solutions(&self) -> &Self::Solutions; @@ -220,7 +204,7 @@ impl Debug for LoadConfig<'_, I, S, Z> { SC: serde::Serialize + for<'a> serde::Deserialize<'a>, R: serde::Serialize + for<'a> serde::Deserialize<'a> ")] -pub struct StdState { +pub struct StdState { /// RNG instance rand: R, /// How many times the executor ran the harness/target @@ -266,7 +250,7 @@ pub struct StdState { phantom: PhantomData, } -impl HasRand for StdState +impl HasRand for StdState where R: Rand, { @@ -285,9 +269,9 @@ where } } -impl HasCorpus for StdState +impl HasCorpus for StdState where - C: Corpus, + C: Corpus, { type Corpus = C; @@ -304,26 +288,26 @@ where } } -impl HasTestcase for StdState +impl HasTestcase for StdState where - C: Corpus, + C: Corpus, { /// To get the testcase - fn testcase(&self, id: CorpusId) -> Result>, Error> { + fn testcase(&self, id: CorpusId) -> Result>, Error> { Ok(self.corpus().get(id)?.borrow()) } /// To get mutable testcase - fn testcase_mut(&self, id: CorpusId) -> Result>, Error> { + fn testcase_mut(&self, id: CorpusId) -> Result>, Error> { Ok(self.corpus().get(id)?.borrow_mut()) } } -impl HasSolutions for StdState +impl HasSolutions for StdState where + C: Corpus, I: Input, - C: Corpus, - SC: Corpus, + SC: Corpus, { type Solutions = SC; @@ -340,7 +324,7 @@ where } } -impl HasMetadata for StdState { +impl HasMetadata for StdState { /// Get all the metadata into an [`hashbrown::HashMap`] #[inline] fn metadata_map(&self) -> &SerdeAnyMap { @@ -354,7 +338,7 @@ impl HasMetadata for StdState { } } -impl HasNamedMetadata for StdState { +impl HasNamedMetadata for StdState { /// Get all the metadata into an [`hashbrown::HashMap`] #[inline] fn named_metadata_map(&self) -> &NamedSerdeAnyMap { @@ -368,7 +352,7 @@ impl HasNamedMetadata for StdState { } } -impl HasExecutions for StdState { +impl HasExecutions for StdState { /// The executions counter #[inline] fn executions(&self) -> &u64 { @@ -382,7 +366,7 @@ impl HasExecutions for StdState { } } -impl HasImported for StdState { +impl HasImported for StdState { /// Return the number of new paths that imported from other fuzzers #[inline] fn imported(&self) -> &usize { @@ -396,7 +380,7 @@ impl HasImported for StdState { } } -impl HasLastFoundTime for StdState { +impl HasLastFoundTime for StdState { /// Return the number of new paths that imported from other fuzzers #[inline] fn last_found_time(&self) -> &Duration { @@ -410,7 +394,7 @@ impl HasLastFoundTime for StdState { } } -impl HasLastReportTime for StdState { +impl HasLastReportTime for StdState { /// The last time we reported progress,if available/used. /// This information is used by fuzzer `maybe_report_progress`. fn last_report_time(&self) -> &Option { @@ -424,7 +408,7 @@ impl HasLastReportTime for StdState { } } -impl HasMaxSize for StdState { +impl HasMaxSize for StdState { fn max_size(&self) -> usize { self.max_size } @@ -434,7 +418,7 @@ impl HasMaxSize for StdState { } } -impl HasStartTime for StdState { +impl HasStartTime for StdState { /// The starting time #[inline] fn start_time(&self) -> &Duration { @@ -448,7 +432,7 @@ impl HasStartTime for StdState { } } -impl HasCurrentCorpusId for StdState { +impl HasCurrentCorpusId for StdState { fn set_corpus_id(&mut self, id: CorpusId) -> Result<(), Error> { self.corpus_id = Some(id); Ok(()) @@ -465,20 +449,17 @@ impl HasCurrentCorpusId for StdState { } /// Has information about the current [`Testcase`] we are fuzzing -pub trait HasCurrentTestcase: HasCorpus { +pub trait HasCurrentTestcase: HasCorpus { /// Gets the current [`Testcase`] we are fuzzing /// /// Will return [`Error::key_not_found`] if no `corpus_id` is currently set. - fn current_testcase(&self) - -> Result::Input>>, Error>; + fn current_testcase(&self) -> Result>, Error>; //fn current_testcase(&self) -> Result<&Testcase, Error>; /// Gets the current [`Testcase`] we are fuzzing (mut) /// /// Will return [`Error::key_not_found`] if no `corpus_id` is currently set. - fn current_testcase_mut( - &self, - ) -> Result::Input>>, Error>; + fn current_testcase_mut(&self) -> Result>, Error>; //fn current_testcase_mut(&self) -> Result<&mut Testcase, Error>; /// Gets a cloned representation of the current [`Testcase`]. @@ -488,17 +469,15 @@ pub trait HasCurrentTestcase: HasCorpus { /// # Note /// This allocates memory and copies the contents! /// For performance reasons, if you just need to access the testcase, use [`Self::current_testcase`] instead. - fn current_input_cloned(&self) -> Result<::Input, Error>; + fn current_input_cloned(&self) -> Result; } -impl HasCurrentTestcase for T +impl HasCurrentTestcase for T where - T: HasCorpus + HasCurrentCorpusId, - ::Input: Clone, + T: HasCorpus + HasCurrentCorpusId, + I: Clone, { - fn current_testcase( - &self, - ) -> Result::Input>>, Error> { + fn current_testcase(&self) -> Result>, Error> { let Some(corpus_id) = self.current_corpus_id()? else { return Err(Error::key_not_found( "We are not currently processing a testcase", @@ -508,9 +487,7 @@ where Ok(self.corpus().get(corpus_id)?.borrow()) } - fn current_testcase_mut( - &self, - ) -> Result::Input>>, Error> { + fn current_testcase_mut(&self) -> Result>, Error> { let Some(corpus_id) = self.current_corpus_id()? else { return Err(Error::illegal_state( "We are not currently processing a testcase", @@ -520,7 +497,7 @@ where Ok(self.corpus().get(corpus_id)?.borrow_mut()) } - fn current_input_cloned(&self) -> Result<::Input, Error> { + fn current_input_cloned(&self) -> Result { let mut testcase = self.current_testcase_mut()?; Ok(testcase.borrow_mut().load_input(self.corpus())?.clone()) } @@ -538,7 +515,7 @@ pub trait Stoppable { fn discard_stop_request(&mut self); } -impl Stoppable for StdState { +impl Stoppable for StdState { fn request_stop(&mut self) { self.stop_requested = true; } @@ -552,7 +529,7 @@ impl Stoppable for StdState { } } -impl HasCurrentStageId for StdState { +impl HasCurrentStageId for StdState { fn set_current_stage_id(&mut self, idx: StageId) -> Result<(), Error> { self.stage_stack.set_current_stage_id(idx) } @@ -570,7 +547,7 @@ impl HasCurrentStageId for StdState { } } -impl HasNestedStageStatus for StdState { +impl HasNestedStageStatus for StdState { fn enter_inner_stage(&mut self) -> Result<(), Error> { self.stage_stack.enter_inner_stage() } @@ -581,12 +558,12 @@ impl HasNestedStageStatus for StdState { } #[cfg(feature = "std")] -impl StdState +impl StdState where + C: Corpus, I: Input, R: Rand, - C: Corpus, - SC: Corpus, + SC: Corpus, { /// Decide if the state must load the inputs pub fn must_load_initial_inputs(&self) -> bool { @@ -1022,12 +999,12 @@ where } } -impl StdState +impl StdState where + C: Corpus, I: Input, - C: Corpus, R: Rand, - SC: Corpus, + SC: Corpus, { fn generate_initial_internal( &mut self, @@ -1040,7 +1017,7 @@ where ) -> Result<(), Error> where EM: EventFirer, - G: Generator, + G: Generator, Z: Evaluator, { let mut added = 0; @@ -1078,7 +1055,7 @@ where ) -> Result<(), Error> where EM: EventFirer, - G: Generator, + G: Generator, Z: Evaluator, { self.generate_initial_internal(fuzzer, executor, generator, manager, num, true) @@ -1095,7 +1072,7 @@ where ) -> Result<(), Error> where EM: EventFirer, - G: Generator, + G: Generator, Z: Evaluator, { self.generate_initial_internal(fuzzer, executor, generator, manager, num, false) @@ -1146,16 +1123,16 @@ where } } -impl StdState, StdRand, InMemoryCorpus> { +impl StdState, NopInput, StdRand, InMemoryCorpus> { /// Create an empty [`StdState`] that has very minimal uses. /// Potentially good for testing. - pub fn nop() -> Result, StdRand, InMemoryCorpus>, Error> - where - I: Input, - { + pub fn nop() -> Result< + StdState, NopInput, StdRand, InMemoryCorpus>, + Error, + > { StdState::new( StdRand::with_seed(0), - InMemoryCorpus::::new(), + InMemoryCorpus::::new(), InMemoryCorpus::new(), &mut (), &mut (), @@ -1164,7 +1141,7 @@ impl StdState, StdRand, InMemoryCorpus HasClientPerfMonitor for StdState { +impl HasClientPerfMonitor for StdState { fn introspection_monitor(&self) -> &ClientPerfMonitor { &self.introspection_monitor } @@ -1210,7 +1187,7 @@ impl HasMaxSize for NopState { } } -impl HasCorpus for NopState { +impl HasCorpus for NopState { type Corpus = InMemoryCorpus; fn corpus(&self) -> &Self::Corpus { @@ -1329,10 +1306,10 @@ impl HasClientPerfMonitor for NopState { #[cfg(test)] mod test { - use crate::{inputs::BytesInput, state::StdState}; + use crate::state::StdState; #[test] fn test_std_state() { - StdState::nop::().expect("couldn't instantiate the test state"); + StdState::nop().expect("couldn't instantiate the test state"); } } diff --git a/libafl_frida/src/asan/errors.rs b/libafl_frida/src/asan/errors.rs index 8fbc9fd969..1887a649c7 100644 --- a/libafl_frida/src/asan/errors.rs +++ b/libafl_frida/src/asan/errors.rs @@ -13,11 +13,10 @@ use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity}; use frida_gum::interceptor::Interceptor; use frida_gum::ModuleDetails; use libafl::{ - corpus::{Corpus, Testcase}, + corpus::Testcase, executors::ExitKind, feedbacks::{Feedback, StateInitializer}, observers::Observer, - state::HasCorpus, Error, HasMetadata, }; use libafl_bolts::{ @@ -648,16 +647,16 @@ pub struct AsanErrorsFeedback { impl StateInitializer for AsanErrorsFeedback {} -impl Feedback::Input, OT, S> for AsanErrorsFeedback +impl Feedback for AsanErrorsFeedback where - S: HasCorpus + Debug, + S: Debug, OT: MatchNameRef, { fn is_interesting( &mut self, _state: &mut S, _manager: &mut EM, - _input: &::Input, + _input: &I, observers: &OT, _exit_kind: &ExitKind, ) -> Result { @@ -678,7 +677,7 @@ where _state: &mut S, _manager: &mut EM, _observers: &OT, - testcase: &mut Testcase<::Input>, + testcase: &mut Testcase, ) -> Result<(), Error> { if let Some(errors) = &self.errors { testcase.add_metadata(errors.clone()); @@ -687,11 +686,7 @@ where Ok(()) } - fn discard_metadata( - &mut self, - _state: &mut S, - _input: &::Input, - ) -> Result<(), Error> { + fn discard_metadata(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { self.errors = None; Ok(()) } diff --git a/libafl_frida/src/executor.rs b/libafl_frida/src/executor.rs index f3a1cffee9..a2b9ee8e61 100644 --- a/libafl_frida/src/executor.rs +++ b/libafl_frida/src/executor.rs @@ -18,7 +18,7 @@ use libafl::{ executors::{Executor, ExitKind, HasObservers, InProcessExecutor}, inputs::{NopTargetBytesConverter, TargetBytesConverter}, observers::ObserversTuple, - state::{HasCorpus, HasExecutions}, + state::HasExecutions, Error, }; use libafl_bolts::{tuples::RefIndexable, AsSlice}; @@ -60,8 +60,8 @@ impl Executor for FridaInProcessExecutor<'_, '_, '_, H, I, OT, RT, S, TC> where H: FnMut(&I) -> ExitKind, - S: HasCorpus + HasExecutions, - TC: TargetBytesConverter, + S: HasExecutions, + TC: TargetBytesConverter, OT: ObserversTuple, RT: FridaRuntimeTuple, { @@ -128,7 +128,6 @@ impl HasObservers for FridaInProcessExecutor<'_, '_, '_, H, impl<'a, 'b, 'c, H, I, OT, RT, S> FridaInProcessExecutor<'a, 'b, 'c, H, I, OT, RT, S, NopTargetBytesConverter> where - S: HasCorpus, RT: FridaRuntimeTuple, { /// Creates a new [`FridaInProcessExecutor`]. @@ -225,10 +224,9 @@ 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, - S::Solutions: Corpus, + S: HasSolutions + HasCurrentTestcase + HasExecutions, I: Input, - TC: TargetBytesConverter, + TC: TargetBytesConverter, OT: ObserversTuple, RT: FridaRuntimeTuple, { diff --git a/libafl_libfuzzer/runtime/src/corpus.rs b/libafl_libfuzzer/runtime/src/corpus.rs index a5ec612193..b2c6125d63 100644 --- a/libafl_libfuzzer/runtime/src/corpus.rs +++ b/libafl_libfuzzer/runtime/src/corpus.rs @@ -88,7 +88,7 @@ where &'a self, id: CorpusId, corpus: &'a TestcaseStorageMap, - ) -> Result<&RefCell>, Error> { + ) -> Result<&'a RefCell>, Error> { self.touch(id, corpus)?; corpus.map.get(&id).map(|item| &item.testcase).ok_or_else(|| Error::illegal_state("Nonexistent corpus entry {id} requested (present in loaded entries, but not the mapping?)")) } @@ -140,12 +140,10 @@ where } } -impl Corpus for LibfuzzerCorpus +impl Corpus for LibfuzzerCorpus where I: Input + Serialize + for<'de> Deserialize<'de>, { - type Input = I; - #[inline] fn count(&self) -> usize { self.mapping.enabled.map.len() @@ -158,30 +156,26 @@ where fn count_all(&self) -> usize { self.count_disabled().saturating_add(self.count_disabled()) } - fn add(&mut self, testcase: Testcase) -> Result { + fn add(&mut self, testcase: Testcase) -> Result { self._add(RefCell::new(testcase), false) } - fn add_disabled(&mut self, testcase: Testcase) -> Result { + fn add_disabled(&mut self, testcase: Testcase) -> Result { self._add(RefCell::new(testcase), true) } - fn replace( - &mut self, - _id: CorpusId, - _testcase: Testcase, - ) -> Result, Error> { + fn replace(&mut self, _id: CorpusId, _testcase: Testcase) -> Result, Error> { unimplemented!("It is unsafe to use this corpus variant with replace!"); } - fn remove(&mut self, _id: CorpusId) -> Result, Error> { + fn remove(&mut self, _id: CorpusId) -> Result, Error> { unimplemented!("It is unsafe to use this corpus variant with replace!"); } - fn get(&self, id: CorpusId) -> Result<&RefCell>, Error> { + fn get(&self, id: CorpusId) -> Result<&RefCell>, Error> { self._get(id, &self.mapping.enabled) } - fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error> { + fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error> { match self._get(id, &self.mapping.enabled) { Ok(input) => Ok(input), Err(Error::KeyNotFound(..)) => return self._get(id, &self.mapping.disabled), @@ -225,7 +219,7 @@ where self.mapping.enabled.keys[nth] } - fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error> { + fn load_input_into(&self, testcase: &mut Testcase) -> Result<(), Error> { // we don't need to update the loaded testcases because it must have already been loaded if testcase.input().is_none() { let path = testcase.file_path().as_ref().ok_or_else(|| { @@ -237,7 +231,7 @@ where Ok(()) } - fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error> { + fn store_input_from(&self, testcase: &Testcase) -> Result<(), Error> { let input = testcase.input().as_ref().ok_or_else(|| { Error::empty("The testcase, when being saved, must have an input present!") })?; @@ -277,12 +271,10 @@ where } } -impl Corpus for ArtifactCorpus +impl Corpus for ArtifactCorpus where I: Input + Serialize + for<'de> Deserialize<'de>, { - type Input = I; - fn count(&self) -> usize { self.count } @@ -297,7 +289,7 @@ where self.count() + self.count_disabled() } - fn add(&mut self, testcase: Testcase) -> Result { + fn add(&mut self, testcase: Testcase) -> Result { let idx = self.count; self.count += 1; @@ -320,23 +312,19 @@ where Ok(CorpusId::from(idx)) } - fn add_disabled(&mut self, _testcase: Testcase) -> Result { + fn add_disabled(&mut self, _testcase: Testcase) -> Result { unimplemented!("ArtifactCorpus disregards disabled inputs") } - fn replace( - &mut self, - _id: CorpusId, - _testcase: Testcase, - ) -> Result, Error> { + fn replace(&mut self, _id: CorpusId, _testcase: Testcase) -> Result, Error> { unimplemented!("Artifact prefix is thin and cannot get, replace, or remove.") } - fn remove(&mut self, _id: CorpusId) -> Result, Error> { + fn remove(&mut self, _id: CorpusId) -> Result, Error> { unimplemented!("Artifact prefix is thin and cannot get, replace, or remove.") } - fn get(&self, id: CorpusId) -> Result<&RefCell>, Error> { + fn get(&self, id: CorpusId) -> Result<&RefCell>, Error> { let maybe_last = if self .count .checked_sub(1) @@ -355,7 +343,7 @@ where } // This just calls Self::get as ArtifactCorpus disregards disabled entries - fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error> { + fn get_from_all(&self, id: CorpusId) -> Result<&RefCell>, Error> { self.get(id) } @@ -388,11 +376,11 @@ where self.count.checked_sub(1).map(CorpusId::from) } - fn load_input_into(&self, _testcase: &mut Testcase) -> Result<(), Error> { + fn load_input_into(&self, _testcase: &mut Testcase) -> Result<(), Error> { unimplemented!("Artifact prefix is thin and cannot get, replace, or remove.") } - fn store_input_from(&self, _testcase: &Testcase) -> Result<(), Error> { + fn store_input_from(&self, _testcase: &Testcase) -> Result<(), Error> { unimplemented!("Artifact prefix is thin and cannot get, replace, or remove.") } } diff --git a/libafl_libfuzzer/runtime/src/feedbacks.rs b/libafl_libfuzzer/runtime/src/feedbacks.rs index 12ed1eb195..c0b018db98 100644 --- a/libafl_libfuzzer/runtime/src/feedbacks.rs +++ b/libafl_libfuzzer/runtime/src/feedbacks.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use libafl::{ alloc, - corpus::{Corpus, Testcase}, + corpus::Testcase, executors::ExitKind, feedbacks::{Feedback, MinMapFeedback, StateInitializer}, inputs::{BytesInput, Input}, @@ -43,15 +43,15 @@ impl Named for LibfuzzerKeepFeedback { impl StateInitializer for LibfuzzerKeepFeedback {} -impl Feedback::Input, OT, S> for LibfuzzerKeepFeedback +impl Feedback for LibfuzzerKeepFeedback where - S: HasCorpus, + S: HasCorpus, { fn is_interesting( &mut self, _state: &mut S, _manager: &mut EM, - _input: &::Input, + _input: &I, _observers: &OT, _exit_kind: &ExitKind, ) -> Result { diff --git a/libafl_libfuzzer/runtime/src/fuzz.rs b/libafl_libfuzzer/runtime/src/fuzz.rs index 86c773a30e..3950cd8eb5 100644 --- a/libafl_libfuzzer/runtime/src/fuzz.rs +++ b/libafl_libfuzzer/runtime/src/fuzz.rs @@ -52,7 +52,7 @@ fn destroy_output_fds(options: &LibfuzzerOptions) { } } -fn do_fuzz( +fn do_fuzz( options: &LibfuzzerOptions, fuzzer: &mut F, stages: &mut ST, @@ -61,10 +61,10 @@ fn do_fuzz( mgr: &mut EM, ) -> Result<(), Error> where - F: Fuzzer, + F: Fuzzer, S: HasMetadata + HasExecutions - + HasSolutions + + HasSolutions + HasLastReportTime + HasCurrentStageId + Stoppable, diff --git a/libafl_libfuzzer/runtime/src/lib.rs b/libafl_libfuzzer/runtime/src/lib.rs index e7331d660b..10b38916ba 100644 --- a/libafl_libfuzzer/runtime/src/lib.rs +++ b/libafl_libfuzzer/runtime/src/lib.rs @@ -151,12 +151,13 @@ macro_rules! fuzz_with { feedback_and_fast, feedback_not, feedback_or, feedback_or_fast, feedbacks::{ConstFeedback, CrashFeedback, MaxMapFeedback, NewHashFeedback, TimeFeedback, TimeoutFeedback}, generators::RandBytesGenerator, - inputs::{BytesInput, HasTargetBytes}, + inputs::{BytesInput, HasTargetBytes, GeneralizedInputMetadata}, mutators::{ GrimoireExtensionMutator, GrimoireRecursiveReplacementMutator, GrimoireRandomDeleteMutator, GrimoireStringReplacementMutator, havoc_crossover, havoc_mutations, havoc_mutations_no_crossover, I2SRandReplace, StdScheduledMutator, UnicodeCategoryRandMutator, UnicodeSubcategoryRandMutator, - UnicodeCategoryTokenReplaceMutator, UnicodeSubcategoryTokenReplaceMutator, Tokens, tokens_mutations + UnicodeCategoryTokenReplaceMutator, UnicodeSubcategoryTokenReplaceMutator, Tokens, tokens_mutations, + UnicodeInput, }, observers::{stacktrace::BacktraceObserver, TimeObserver, CanTrack}, schedulers::{ @@ -173,7 +174,6 @@ macro_rules! fuzz_with { use libafl_bolts::nonzero; use rand::{thread_rng, RngCore}; use std::{env::temp_dir, fs::create_dir, path::PathBuf}; - use core::num::NonZeroUsize; use crate::{ CustomMutationStatus, corpus::{ArtifactCorpus, LibfuzzerCorpus}, @@ -319,8 +319,8 @@ macro_rules! fuzz_with { UnicodeSubcategoryTokenReplaceMutator, ) ); - let unicode_power = StdMutationalStage::transforming(unicode_mutator); - let unicode_replace_power = StdMutationalStage::transforming(unicode_replace_mutator); + let unicode_power = StdMutationalStage::<_, _, UnicodeInput, BytesInput, _, _, _>::transforming(unicode_mutator); + let unicode_replace_power = StdMutationalStage::<_, _, UnicodeInput, BytesInput, _, _, _>::transforming(unicode_replace_mutator); let unicode_analysis = UnicodeIdentificationStage::new(); let unicode_analysis = IfStage::new(|_, _, _, _| Ok((unicode_used && mutator_status.std_mutational).into()), tuple_list!(unicode_analysis, unicode_power, unicode_replace_power)); @@ -414,7 +414,7 @@ macro_rules! fuzz_with { ), 3, ); - let grimoire = IfStage::new(|_, _, _, _| Ok(grimoire.into()), (StdMutationalStage::transforming(grimoire_mutator), ())); + let grimoire = IfStage::new(|_, _, _, _| Ok(grimoire.into()), (StdMutationalStage::<_, _, GeneralizedInputMetadata, BytesInput, _, _, _>::transforming(grimoire_mutator), ())); // A minimization+queue policy to get testcasess from the corpus let scheduler = IndexesLenTimeMinimizerScheduler::new(&edges_observer, PowerQueueScheduler::new(&mut state, &edges_observer, PowerSchedule::fast())); diff --git a/libafl_libfuzzer/runtime/src/merge.rs b/libafl_libfuzzer/runtime/src/merge.rs index 5af3fb4824..31c42f1b2b 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, ManagerExit, SimpleRestartingEventManager}, + events::{ManagerExit, SimpleRestartingEventManager}, executors::{ExitKind, InProcessExecutor}, feedback_and_fast, feedback_or_fast, feedbacks::{CrashFeedback, MinMapFeedback, TimeoutFeedback}, diff --git a/libafl_libfuzzer/runtime/src/observers.rs b/libafl_libfuzzer/runtime/src/observers.rs index bd054330e2..43f9ee5a9a 100644 --- a/libafl_libfuzzer/runtime/src/observers.rs +++ b/libafl_libfuzzer/runtime/src/observers.rs @@ -5,7 +5,6 @@ use std::{ ops::Deref, }; -use ahash::AHasher; use libafl::{ corpus::Corpus, executors::ExitKind, @@ -129,12 +128,6 @@ where self.inner.count_bytes() } - fn hash_simple(&self) -> u64 { - let mut hasher = AHasher::default(); - self.hash(&mut hasher); - hasher.finish() - } - fn initial(&self) -> Self::Entry { *self.value_observer.default_value() } @@ -158,27 +151,18 @@ where } } -impl Observer<::Input, S> for MappedEdgeMapObserver +impl Observer for MappedEdgeMapObserver where - S: HasCorpus, - M: Observer<::Input, S> + Debug, - O: Observer<::Input, S> + Debug, + M: Observer + Debug, + O: Observer + Debug, + S: HasCorpus, { - fn pre_exec( - &mut self, - state: &mut S, - input: &::Input, - ) -> Result<(), Error> { + fn pre_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> { self.inner.pre_exec(state, input)?; self.value_observer.pre_exec(state, input) } - fn post_exec( - &mut self, - state: &mut S, - input: &::Input, - exit_kind: &ExitKind, - ) -> Result<(), Error> { + fn post_exec(&mut self, state: &mut S, input: &I, exit_kind: &ExitKind) -> Result<(), Error> { self.inner.post_exec(state, input, exit_kind)?; self.value_observer.post_exec(state, input, exit_kind) } @@ -259,16 +243,12 @@ impl Named for SizeValueObserver { } } -impl Observer<::Input, S> for SizeValueObserver +impl Observer for SizeValueObserver where - S: HasCorpus, - ::Input: HasLen, + I: HasLen, + S: HasCorpus, { - fn pre_exec( - &mut self, - _state: &mut S, - input: &::Input, - ) -> Result<(), Error> { + fn pre_exec(&mut self, _state: &mut S, input: &I) -> Result<(), Error> { self.size = input.len(); Ok(()) } @@ -307,24 +287,15 @@ impl Named for TimeValueObserver { } } -impl Observer<::Input, S> for TimeValueObserver +impl Observer for TimeValueObserver where - S: HasCorpus, + S: HasCorpus, { - fn pre_exec( - &mut self, - state: &mut S, - input: &::Input, - ) -> Result<(), Error> { + fn pre_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> { self.time_obs.pre_exec(state, input) } - fn post_exec( - &mut self, - state: &mut S, - input: &::Input, - exit_kind: &ExitKind, - ) -> Result<(), Error> { + fn post_exec(&mut self, state: &mut S, input: &I, exit_kind: &ExitKind) -> Result<(), Error> { self.time_obs.post_exec(state, input, exit_kind)?; self.time = self .time_obs @@ -373,26 +344,17 @@ impl Named for SizeTimeValueObserver { } } -impl Observer<::Input, S> for SizeTimeValueObserver +impl Observer for SizeTimeValueObserver where - S: HasCorpus, - ::Input: HasLen, + S: HasCorpus, + I: HasLen, { - fn pre_exec( - &mut self, - state: &mut S, - input: &::Input, - ) -> Result<(), Error> { + fn pre_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> { self.size_obs.pre_exec(state, input)?; self.time_obs.pre_exec(state, input) } - fn post_exec( - &mut self, - state: &mut S, - input: &::Input, - exit_kind: &ExitKind, - ) -> Result<(), Error> { + fn post_exec(&mut self, state: &mut S, input: &I, exit_kind: &ExitKind) -> Result<(), Error> { self.time_obs.post_exec(state, input, exit_kind)?; self.size_obs.post_exec(state, input, exit_kind)?; self.value = self diff --git a/libafl_libfuzzer/runtime/src/report.rs b/libafl_libfuzzer/runtime/src/report.rs index 0afc49ef89..edf6e7c531 100644 --- a/libafl_libfuzzer/runtime/src/report.rs +++ b/libafl_libfuzzer/runtime/src/report.rs @@ -13,7 +13,7 @@ use libafl::{ use crate::{fuzz_with, options::LibfuzzerOptions}; #[expect(clippy::unnecessary_wraps, clippy::cast_precision_loss)] -fn do_report( +fn do_report( _options: &LibfuzzerOptions, _fuzzer: &mut F, _stages: &mut ST, @@ -22,7 +22,7 @@ fn do_report( _mgr: &mut EM, ) -> Result<(), Error> where - F: Fuzzer, + F: Fuzzer, S: HasMetadata + HasNamedMetadata + HasExecutions diff --git a/libafl_libfuzzer/runtime/src/schedulers.rs b/libafl_libfuzzer/runtime/src/schedulers.rs index d14d8c0c77..220cd738f6 100644 --- a/libafl_libfuzzer/runtime/src/schedulers.rs +++ b/libafl_libfuzzer/runtime/src/schedulers.rs @@ -20,7 +20,7 @@ pub struct MergeScheduler { impl RemovableScheduler for MergeScheduler where I: Input, - S: HasCorpus, + S: HasCorpus, { fn on_remove( &mut self, @@ -35,7 +35,7 @@ where impl Scheduler for MergeScheduler where - S: HasCorpus, + S: HasCorpus, { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { self.all.insert(id); diff --git a/libafl_libfuzzer/runtime/src/tmin.rs b/libafl_libfuzzer/runtime/src/tmin.rs index 44ff647796..a53a3c5db9 100644 --- a/libafl_libfuzzer/runtime/src/tmin.rs +++ b/libafl_libfuzzer/runtime/src/tmin.rs @@ -26,7 +26,7 @@ use libafl_targets::LLVMCustomMutator; use crate::{options::LibfuzzerOptions, CustomMutationStatus}; type TMinState = - StdState, RomuDuoJrRand, InMemoryCorpus>; + StdState, BytesInput, RomuDuoJrRand, InMemoryCorpus>; fn minimize_crash_with_mutator>( options: &LibfuzzerOptions, diff --git a/libafl_nyx/src/executor.rs b/libafl_nyx/src/executor.rs index 36029e2d27..f3330c638d 100644 --- a/libafl_nyx/src/executor.rs +++ b/libafl_nyx/src/executor.rs @@ -5,11 +5,10 @@ use std::{ }; use libafl::{ - corpus::Corpus, executors::{Executor, ExitKind, HasObservers, HasTimeout}, inputs::HasTargetBytes, observers::{ObserversTuple, StdOutObserver}, - state::{HasCorpus, HasExecutions}, + state::HasExecutions, Error, }; use libafl_bolts::{tuples::RefIndexable, AsSlice}; @@ -39,18 +38,18 @@ impl NyxExecutor<(), ()> { } } -impl Executor::Input, S, Z> for NyxExecutor +impl Executor for NyxExecutor where - S: HasCorpus + HasExecutions, - ::Input: HasTargetBytes, - OT: ObserversTuple<::Input, S>, + S: HasExecutions, + I: HasTargetBytes, + OT: ObserversTuple, { fn run_target( &mut self, _fuzzer: &mut Z, state: &mut S, _mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { *state.executions_mut() += 1; diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index faf4abd164..08f133f279 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -10,7 +10,6 @@ use std::ptr; use std::sync::atomic::{AtomicBool, Ordering}; use libafl::{ - corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{ hooks::inprocess::InProcessExecutorHandlerData, @@ -22,7 +21,7 @@ use libafl::{ fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, + state::{HasCurrentTestcase, HasExecutions, HasSolutions}, Error, ExecutionProcessor, HasScheduler, }; #[cfg(feature = "fork")] @@ -96,9 +95,8 @@ pub unsafe fn inproc_qemu_timeout_handler( ET: EmulatorModuleTuple, I: Unpin, OF: Feedback, - S: HasExecutions + HasSolutions + HasCorpus + Unpin + HasCurrentTestcase, + S: HasExecutions + HasSolutions + Unpin + HasCurrentTestcase, I: Input, - S::Solutions: Corpus, Z: HasObjective, { #[cfg(feature = "systemmode")] @@ -152,8 +150,7 @@ where H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, I: Input + Unpin, OT: ObserversTuple, - S: HasCorpus + Unpin + HasExecutions + HasSolutions + HasCurrentTestcase, - S::Solutions: Corpus, + S: Unpin + HasExecutions + HasSolutions + HasCurrentTestcase, { pub fn new( emulator: Emulator, @@ -171,7 +168,6 @@ where EM: EventFirer + EventRestarter, OF: Feedback, Z: HasObjective + HasScheduler + ExecutionProcessor, - ::Corpus: Corpus, { let mut inner = StatefulInProcessExecutor::with_timeout( harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout, @@ -252,7 +248,7 @@ where H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, I: Unpin, OT: ObserversTuple, - S: HasExecutions + Unpin + HasCorpus, + S: HasExecutions + Unpin, { fn run_target( &mut self, @@ -289,7 +285,6 @@ where ET: EmulatorModuleTuple, H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, OT: ObserversTuple, - S: HasCorpus, { type Observers = OT; #[inline] @@ -340,7 +335,7 @@ where EM: EventFirer + EventRestarter, ET: EmulatorModuleTuple, OT: ObserversTuple, - S: HasSolutions + HasCorpus, + S: HasSolutions, SP: ShMemProvider, Z: HasObjective, Z::Objective: Feedback, @@ -408,7 +403,7 @@ where OF: Feedback, OT: ObserversTuple + Debug, I: Input + Unpin, - S: HasExecutions + Unpin + HasCorpus, + S: HasExecutions + Unpin, SP: ShMemProvider, Z: HasObjective, { diff --git a/libafl_qemu/src/qemu/mod.rs b/libafl_qemu/src/qemu/mod.rs index 512dd9d460..925c424e14 100644 --- a/libafl_qemu/src/qemu/mod.rs +++ b/libafl_qemu/src/qemu/mod.rs @@ -10,10 +10,10 @@ use core::{ use std::{ ffi::{c_void, CString}, fmt::{Display, Formatter}, - intrinsics::{copy_nonoverlapping, transmute}, - mem::MaybeUninit, + mem::{transmute, MaybeUninit}, ops::Range, pin::Pin, + ptr::copy_nonoverlapping, sync::OnceLock, }; diff --git a/libafl_qemu/src/qemu/usermode.rs b/libafl_qemu/src/qemu/usermode.rs index 7353eb4a53..0c8e73d7ac 100644 --- a/libafl_qemu/src/qemu/usermode.rs +++ b/libafl_qemu/src/qemu/usermode.rs @@ -1,5 +1,5 @@ use std::{ - intrinsics::copy_nonoverlapping, mem::MaybeUninit, slice::from_raw_parts_mut, + mem::MaybeUninit, ptr::copy_nonoverlapping, slice::from_raw_parts_mut, str::from_utf8_unchecked_mut, }; diff --git a/libafl_sugar/src/forkserver.rs b/libafl_sugar/src/forkserver.rs index 59e62f0651..e21a78d9c5 100644 --- a/libafl_sugar/src/forkserver.rs +++ b/libafl_sugar/src/forkserver.rs @@ -119,7 +119,7 @@ impl ForkserverBytesCoverageSugar<'_> { let time_ref = time_observer.handle(); let mut run_client = |state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| { let time_observer = time_observer.clone(); diff --git a/libafl_sugar/src/inmemory.rs b/libafl_sugar/src/inmemory.rs index d1eb465d2d..2a9b41ad7b 100644 --- a/libafl_sugar/src/inmemory.rs +++ b/libafl_sugar/src/inmemory.rs @@ -147,7 +147,7 @@ where let time_ref = time_observer.handle(); let mut run_client = |state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| { let time_observer = time_observer.clone(); diff --git a/libafl_sugar/src/qemu.rs b/libafl_sugar/src/qemu.rs index 9fd46972da..fa4be32f8a 100644 --- a/libafl_sugar/src/qemu.rs +++ b/libafl_sugar/src/qemu.rs @@ -150,7 +150,7 @@ where let time_ref = time_observer.handle(); let mut run_client = |state: Option<_>, - mut mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| { let time_observer = time_observer.clone(); diff --git a/libafl_targets/src/cmps/stages/aflpptracing.rs b/libafl_targets/src/cmps/stages/aflpptracing.rs index b3edfd81bd..24440a1f5c 100644 --- a/libafl_targets/src/cmps/stages/aflpptracing.rs +++ b/libafl_targets/src/cmps/stages/aflpptracing.rs @@ -2,7 +2,7 @@ use alloc::borrow::{Cow, ToOwned}; use core::marker::PhantomData; use libafl::{ - corpus::{Corpus, HasCurrentCorpusId}, + corpus::HasCurrentCorpusId, executors::{Executor, HasObservers}, inputs::BytesInput, observers::ObserversTuple, @@ -38,8 +38,7 @@ impl Stage for AFLppCmplogTracingStage<'_, EM, TE, where TE: HasObservers + Executor, TE::Observers: MatchNameRef + ObserversTuple, - S: HasCorpus + HasCurrentTestcase + HasMetadata + HasNamedMetadata + HasCurrentCorpusId, - S::Corpus: Corpus, + S: HasCorpus + HasCurrentTestcase + HasMetadata + HasNamedMetadata + HasCurrentCorpusId, { #[inline] fn perform( diff --git a/libafl_targets/src/libfuzzer/mutators.rs b/libafl_targets/src/libfuzzer/mutators.rs index ed47616c5f..c35a038d09 100644 --- a/libafl_targets/src/libfuzzer/mutators.rs +++ b/libafl_targets/src/libfuzzer/mutators.rs @@ -367,9 +367,8 @@ impl Named for LLVMCustomMutator { impl Mutator for LLVMCustomMutator where - S: HasRand + HasMaxSize + HasCorpus + 'static, + S: HasRand + HasMaxSize + HasCorpus + 'static, SM: ScheduledMutator + 'static, - S::Corpus: Corpus, SM::Mutations: MutatorsTuple, { #[inline] @@ -381,8 +380,7 @@ where impl ScheduledMutator for LLVMCustomMutator where SM: ScheduledMutator + 'static, - S: HasRand + HasMaxSize + HasCorpus + 'static, - S::Corpus: Corpus, + S: HasRand + HasMaxSize + HasCorpus + 'static, SM::Mutations: MutatorsTuple, { fn iterations(&self, state: &mut S, input: &BytesInput) -> u64 { diff --git a/libafl_targets/src/windows_asan.rs b/libafl_targets/src/windows_asan.rs index 40d3d4bf1b..561d90ea7c 100644 --- a/libafl_targets/src/windows_asan.rs +++ b/libafl_targets/src/windows_asan.rs @@ -1,13 +1,12 @@ //! Setup asan death callbback use libafl::{ - corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{hooks::windows::windows_asan_handler::asan_death_handler, Executor, HasObservers}, feedbacks::Feedback, inputs::Input, observers::ObserversTuple, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, + state::{HasCurrentTestcase, HasExecutions, HasSolutions}, HasObjective, }; @@ -36,8 +35,7 @@ where E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, OF: Feedback, - S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus, - S::Solutions: Corpus, + S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, I: Input + Clone, { diff --git a/libafl_tinyinst/src/executor.rs b/libafl_tinyinst/src/executor.rs index 19296148c8..03381bd172 100644 --- a/libafl_tinyinst/src/executor.rs +++ b/libafl_tinyinst/src/executor.rs @@ -1,10 +1,9 @@ use core::{marker::PhantomData, ptr, time::Duration}; use libafl::{ - corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, inputs::HasTargetBytes, - state::{HasCorpus, HasExecutions}, + state::HasExecutions, Error, }; use libafl_bolts::{ @@ -48,11 +47,10 @@ where } } -impl Executor::Input, S, Z> - for TinyInstExecutor +impl Executor for TinyInstExecutor where - S: HasCorpus + HasExecutions, - ::Input: HasTargetBytes, + S: HasExecutions, + I: HasTargetBytes, SP: ShMemProvider, { #[inline] @@ -61,7 +59,7 @@ where _fuzzer: &mut Z, state: &mut S, _mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { *state.executions_mut() += 1; match &self.map {