diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 5fa33cf098..d3013dff2b 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -209,21 +209,15 @@ jobs: run: ./scripts/fmt_all.sh check check-md-links: - runs-on: ubuntu-latest + # fixme: use ubuntu-latest once this gets fixed https://github.com/UmbrellaDocs/action-linkspector/issues/32 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - name: Install linkspector - shell: bash - run: sudo apt-get update && sudo apt-get install -y npm && npm install -g @umbrelladocs/linkspector - name: Run linkspector - shell: bash - run: ./scripts/check_md_links.sh - # TODO: Use github action once it's fixed (https://github.com/UmbrellaDocs/action-linkspector/issues/20) - # - name: Run linkspector - # uses: umbrelladocs/action-linkspector@v1 - # with: - # fail_on_error: 'true' - # config_file: '.github/.linkspector.yml' + uses: umbrelladocs/action-linkspector@v1 + with: + fail_on_error: 'true' + config_file: '.github/.linkspector.yml' msrv: runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 6a834b6bd7..66cd22bc30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,7 +121,7 @@ toml = "0.8.19" # For parsing the injections toml file typed-builder = "0.20.0" # Implement the builder pattern at compiletime uuid = { version = "1.10.0", features = ["serde", "v4"] } which = "6.0.3" -windows = "0.58.0" +windows = "0.59.0" z3 = "0.12.1" diff --git a/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs index adeae32832..55f22c8558 100644 --- a/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_executor/src/main.rs @@ -7,19 +7,19 @@ use libafl::monitors::tui::TuiMonitor; #[cfg(not(feature = "tui"))] use libafl::monitors::SimpleMonitor; use libafl::{ - corpus::{InMemoryCorpus, OnDiskCorpus}, + corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::SimpleEventManager, executors::{Executor, ExitKind, WithObservers}, feedback_and_fast, feedbacks::{CrashFeedback, MaxMapFeedback}, fuzzer::{Fuzzer, StdFuzzer}, generators::RandPrintablesGenerator, - inputs::HasTargetBytes, + inputs::{HasTargetBytes, UsesInput}, mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, - state::{HasExecutions, State, StdState, UsesState}, + state::{HasCorpus, HasExecutions, StdState, UsesState}, }; use libafl_bolts::{current_nanos, nonzero, rands::StdRand, tuples::tuple_list, AsSlice}; @@ -35,11 +35,11 @@ fn signals_set(idx: usize) { unsafe { write(SIGNALS_PTR.add(idx), 1) }; } -struct CustomExecutor { +struct CustomExecutor { phantom: PhantomData, } -impl CustomExecutor { +impl CustomExecutor { pub fn new(_state: &S) -> Self { Self { phantom: PhantomData, @@ -47,22 +47,18 @@ impl CustomExecutor { } } -impl UsesState for CustomExecutor { - type State = S; -} - -impl Executor for CustomExecutor +impl Executor::Input, S, Z> for CustomExecutor where EM: UsesState, - S: State + HasExecutions, - Self::Input: HasTargetBytes, + S: HasCorpus + HasExecutions + UsesInput::Input>, + ::Input: HasTargetBytes, { fn run_target( &mut self, _fuzzer: &mut Z, state: &mut S, _mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { // We need to keep track of the exec count. *state.executions_mut() += 1; diff --git a/fuzzers/baby/baby_fuzzer_swap_differential/Cargo.toml b/fuzzers/baby/baby_fuzzer_swap_differential/Cargo.toml index 89da0f1292..5eb8198964 100644 --- a/fuzzers/baby/baby_fuzzer_swap_differential/Cargo.toml +++ b/fuzzers/baby/baby_fuzzer_swap_differential/Cargo.toml @@ -22,7 +22,7 @@ debug = true [build-dependencies] anyhow = "1.0.89" bindgen = "0.70.1" -cc = "1.1.21" +cc = "=1.2.7" # fix me later [dependencies] libafl = { path = "../../../libafl", features = ["tui_monitor"] } diff --git a/fuzzers/binary_only/intel_pt_command_executor/src/main.rs b/fuzzers/binary_only/intel_pt_command_executor/src/main.rs index b8b110ca14..f2e8f54d18 100644 --- a/fuzzers/binary_only/intel_pt_command_executor/src/main.rs +++ b/fuzzers/binary_only/intel_pt_command_executor/src/main.rs @@ -12,6 +12,7 @@ use libafl::{ feedbacks::{CrashFeedback, MaxMapFeedback}, fuzzer::{Fuzzer, StdFuzzer}, generators::RandPrintablesGenerator, + inputs::BytesInput, monitors::SimpleMonitor, mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, @@ -131,7 +132,11 @@ pub fn main() { .timeout(Duration::from_secs(2)) .build(); let mut executor = - command_configurator.into_executor_with_hooks(tuple_list!(observer), tuple_list!(hook)); + >::into_executor_with_hooks( + command_configurator, + tuple_list!(observer), + tuple_list!(hook), + ); // Generator of printable bytearrays of max size 32 let mut generator = RandPrintablesGenerator::new(NonZero::new(32).unwrap()); diff --git a/fuzzers/binary_only/qemu_launcher/src/instance.rs b/fuzzers/binary_only/qemu_launcher/src/instance.rs index 6475562429..24d2c056fe 100644 --- a/fuzzers/binary_only/qemu_launcher/src/instance.rs +++ b/fuzzers/binary_only/qemu_launcher/src/instance.rs @@ -323,7 +323,6 @@ impl Instance<'_, M> { where Z: Fuzzer, ClientState, ST> + Evaluator, BytesInput, ClientState>, - E: UsesState, ST: StagesTuple, ClientState, Z>, { let corpus_dirs = [self.options.input_dir()]; diff --git a/fuzzers/forkserver/libafl-fuzz/src/executor.rs b/fuzzers/forkserver/libafl-fuzz/src/executor.rs index aa60fe982d..3cf24c97ce 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/executor.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/executor.rs @@ -6,9 +6,10 @@ use std::{ }; use libafl::{ + corpus::Corpus, executors::{Executor, ExitKind, HasObservers, HasTimeout}, - observers::ObserversTuple, - state::{State, UsesState}, + inputs::UsesInput, + state::{HasCorpus, UsesState}, Error, }; use libafl_bolts::tuples::RefIndexable; @@ -259,28 +260,20 @@ pub enum SupportedExecutors { } #[cfg(feature = "nyx")] -impl UsesState for SupportedExecutors +impl Executor::Input, S, Z> + for SupportedExecutors where - S: State, -{ - type State = S; -} - -#[cfg(feature = "nyx")] -impl Executor for SupportedExecutors -where - S: State, - Z: UsesState, + S: HasCorpus + UsesInput::Input>, EM: UsesState, - FSV: Executor, - NYX: Executor, + NYX: Executor::Input, S, Z>, + FSV: Executor::Input, S, Z>, { fn run_target( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &S::Input, + input: &::Input, ) -> Result { match self { Self::Forkserver(fsrv, _) => fsrv.run_target(fuzzer, state, mgr, input), @@ -293,10 +286,8 @@ where #[cfg(feature = "nyx")] impl HasObservers for SupportedExecutors where - OT: ObserversTuple, - S: State, - FSV: HasObservers, NYX: HasObservers, + FSV: HasObservers, { type Observers = OT; #[inline] @@ -340,25 +331,18 @@ where } } -#[cfg(not(feature = "nyx"))] -impl UsesState for SupportedExecutors -where - S: State, -{ - type State = S; -} - #[cfg(not(feature = "nyx"))] pub enum SupportedExecutors { Forkserver(FSV, PhantomData<(S, OT)>), } #[cfg(not(feature = "nyx"))] -impl Executor for SupportedExecutors +impl Executor::Input, S, Z> + for SupportedExecutors where - S: State, + S: HasCorpus + UsesInput::Input>, EM: UsesState, - FSV: Executor, + FSV: Executor::Input, S, Z>, { fn run_target( &mut self, @@ -376,8 +360,6 @@ where #[cfg(not(feature = "nyx"))] impl HasObservers for SupportedExecutors where - OT: ObserversTuple, - S: State, FSV: HasObservers, { type Observers = OT; diff --git a/libafl/Cargo.toml b/libafl/Cargo.toml index a990e9f0c7..cc929939a1 100644 --- a/libafl/Cargo.toml +++ b/libafl/Cargo.toml @@ -250,7 +250,7 @@ ratatui = { version = "0.29.0", default-features = false, features = [ ], optional = true } # Commandline rendering, for TUI Monitor crossterm = { version = "0.28.1", optional = true } -prometheus-client = { version = "0.22.3", optional = true } # For the prometheus monitor +prometheus-client = { version = "0.23.0", optional = true } # For the prometheus monitor tide = { version = "0.16.0", optional = true } async-std = { version = "1.13.0", features = ["attributes"], optional = true } futures = { version = "0.3.30", optional = true } diff --git a/libafl/src/corpus/minimizer.rs b/libafl/src/corpus/minimizer.rs index 0e513863df..56767c6775 100644 --- a/libafl/src/corpus/minimizer.rs +++ b/libafl/src/corpus/minimizer.rs @@ -17,10 +17,11 @@ use crate::{ corpus::Corpus, events::{Event, EventFirer, LogSeverity}, executors::{Executor, HasObservers}, + inputs::{Input, UsesInput}, monitors::{AggregatorOps, UserStats, UserStatsValue}, observers::{MapObserver, ObserversTuple}, schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, - state::{HasCorpus, HasExecutions, UsesState}, + state::{HasCorpus, HasExecutions}, Error, HasMetadata, HasScheduler, }; @@ -28,19 +29,17 @@ use crate::{ /// /// Algorithm based on WMOPT: #[derive(Debug)] -pub struct MapCorpusMinimizer { +pub struct MapCorpusMinimizer { observer_handle: Handle, - phantom: PhantomData<(E, O, T, TS)>, + phantom: PhantomData<(E, O, S, T, TS)>, } /// Standard corpus minimizer, which weights inputs by length and time. -pub type StdCorpusMinimizer = MapCorpusMinimizer; +pub type StdCorpusMinimizer = + MapCorpusMinimizer; -impl MapCorpusMinimizer +impl MapCorpusMinimizer where - E: UsesState, - E::State: HasCorpus + HasMetadata, - TS: TestcaseScore, C: Named, { /// Constructs a new `MapCorpusMinimizer` from a provided observer. This observer will be used @@ -53,15 +52,14 @@ where } } -impl MapCorpusMinimizer +impl MapCorpusMinimizer where - E: UsesState, for<'a> O: MapObserver + AsIter<'a, Item = T>, C: AsRef, - E::State: HasMetadata + HasCorpus + HasExecutions, - <::State as HasCorpus>::Corpus: Corpus, + S: HasMetadata + HasCorpus + HasExecutions + UsesInput::Input>, + ::Input: Input, T: Copy + Hash + Eq, - TS: TestcaseScore, + TS: TestcaseScore, { /// Do the minimization #[expect(clippy::too_many_lines)] @@ -70,14 +68,15 @@ where fuzzer: &mut Z, executor: &mut E, manager: &mut EM, - state: &mut E::State, + state: &mut S, ) -> Result<(), Error> where - E: Executor + HasObservers, - E::Observers: ObserversTuple, - CS: Scheduler + RemovableScheduler, - EM: EventFirer, - Z: HasScheduler, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + CS: Scheduler<::Input, S> + + RemovableScheduler<::Input, S>, + EM: EventFirer, + Z: HasScheduler<::Input, S, Scheduler = CS>, { // don't delete this else it won't work after restart let current = *state.corpus().current(); diff --git a/libafl/src/events/centralized.rs b/libafl/src/events/centralized.rs index 9d818e8686..d61dc76172 100644 --- a/libafl/src/events/centralized.rs +++ b/libafl/src/events/centralized.rs @@ -367,7 +367,7 @@ impl EventProcessor for CentralizedEventManager + EventFirer + HasEventManagerId, EMH: EventManagerHooksTuple, - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, E::Observers: ObserversTuple<::Input, ::State> + Serialize, for<'a> E::Observers: Deserialize<'a>, @@ -402,7 +402,7 @@ where impl EventManager for CentralizedEventManager where - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, E::Observers: ObserversTuple<::Input, ::State> + Serialize, for<'a> E::Observers: Deserialize<'a>, @@ -532,7 +532,7 @@ where executor: &mut E, ) -> Result where - E: Executor::State> + HasObservers, + E: Executor::Input, S, Z> + HasObservers, E::Observers: ObserversTuple<::Input, ::State> + Serialize, ::State: UsesInput + HasExecutions + HasMetadata, @@ -582,7 +582,7 @@ where event: Event<<::State as UsesInput>::Input>, ) -> Result<(), Error> where - E: Executor::State> + HasObservers, + E: Executor::Input, S, Z> + HasObservers, E::Observers: ObserversTuple<::Input, ::State> + Serialize, ::State: UsesInput + HasExecutions + HasMetadata, diff --git a/libafl/src/events/llmp/mgr.rs b/libafl/src/events/llmp/mgr.rs index 5fac3c07e5..ef3d514ca5 100644 --- a/libafl/src/events/llmp/mgr.rs +++ b/libafl/src/events/llmp/mgr.rs @@ -410,7 +410,7 @@ where event: Event, ) -> Result<(), Error> where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, E::Observers: ObserversTuple + Serialize, for<'a> E::Observers: Deserialize<'a>, Z: ExecutionProcessor::Input, E::Observers, S> @@ -608,7 +608,7 @@ where S: State + HasExecutions + HasMetadata + HasImported + HasCorpus, S::Corpus: Corpus, SP: ShMemProvider, - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, E::Observers: ObserversTuple + Serialize, for<'a> E::Observers: Deserialize<'a>, Z: ExecutionProcessor::Input, E::Observers, S> @@ -666,7 +666,7 @@ where impl EventManager for LlmpEventManager where - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, E::Observers: ObserversTuple + Serialize, for<'a> E::Observers: Deserialize<'a>, EMH: EventManagerHooksTuple, diff --git a/libafl/src/events/llmp/mod.rs b/libafl/src/events/llmp/mod.rs index 629ff6006a..147a41ae65 100644 --- a/libafl/src/events/llmp/mod.rs +++ b/libafl/src/events/llmp/mod.rs @@ -294,7 +294,7 @@ where event: Event, ) -> Result<(), Error> where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, EM: UsesState + EventFirer, S::Corpus: Corpus, for<'a> E::Observers: Deserialize<'a>, @@ -349,7 +349,7 @@ where manager: &mut EM, ) -> Result where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, EM: UsesState + EventFirer, S::Corpus: Corpus, for<'a> E::Observers: Deserialize<'a>, diff --git a/libafl/src/events/llmp/restarting.rs b/libafl/src/events/llmp/restarting.rs index 361e979ac1..1a0734ebd1 100644 --- a/libafl/src/events/llmp/restarting.rs +++ b/libafl/src/events/llmp/restarting.rs @@ -191,7 +191,7 @@ where impl EventProcessor for LlmpRestartingEventManager where - E: HasObservers + Executor, Z, State = S>, + E: HasObservers + Executor, ::Input, S, Z>, E::Observers: ObserversTuple + Serialize, for<'a> E::Observers: Deserialize<'a>, EMH: EventManagerHooksTuple, @@ -219,7 +219,7 @@ where impl EventManager for LlmpRestartingEventManager where - E: HasObservers + Executor, Z, State = S>, + E: HasObservers + Executor, ::Input, S, Z>, E::Observers: ObserversTuple + Serialize, for<'a> E::Observers: Deserialize<'a>, EMH: EventManagerHooksTuple, diff --git a/libafl/src/events/tcp.rs b/libafl/src/events/tcp.rs index c16c3eaf93..53d1df1f00 100644 --- a/libafl/src/events/tcp.rs +++ b/libafl/src/events/tcp.rs @@ -601,7 +601,7 @@ where event: Event, ) -> Result<(), Error> where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, E::Observers: Serialize + ObserversTuple, for<'a> E::Observers: Deserialize<'a>, Z: ExecutionProcessor::Input, E::Observers, S> @@ -740,7 +740,7 @@ where impl EventProcessor for TcpEventManager where - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, E::Observers: Serialize + ObserversTuple, for<'a> E::Observers: Deserialize<'a>, EMH: EventManagerHooksTuple, @@ -815,7 +815,7 @@ where impl EventManager for TcpEventManager where - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, E::Observers: Serialize + ObserversTuple, for<'a> E::Observers: Deserialize<'a>, EMH: EventManagerHooksTuple, @@ -956,7 +956,7 @@ where impl EventProcessor for TcpRestartingEventManager where - E: HasObservers + Executor, Z, State = S>, + E: HasObservers + Executor, ::Input, S, Z>, for<'a> E::Observers: Deserialize<'a>, E::Observers: ObserversTuple + Serialize, EMH: EventManagerHooksTuple, @@ -977,7 +977,7 @@ where impl EventManager for TcpRestartingEventManager where - E: HasObservers + Executor, Z, State = S>, + E: HasObservers + Executor, ::Input, S, Z>, E::Observers: ObserversTuple + Serialize, for<'a> E::Observers: Deserialize<'a>, EMH: EventManagerHooksTuple, diff --git a/libafl/src/executors/combined.rs b/libafl/src/executors/combined.rs index 20c830ac39..36714fa646 100644 --- a/libafl/src/executors/combined.rs +++ b/libafl/src/executors/combined.rs @@ -8,7 +8,6 @@ use libafl_bolts::tuples::RefIndexable; use super::HasTimeout; use crate::{ executors::{Executor, ExitKind, HasObservers}, - state::{HasExecutions, UsesState}, Error, }; @@ -21,12 +20,7 @@ pub struct CombinedExecutor { impl CombinedExecutor { /// Create a new `CombinedExecutor`, wrapping the given `executor`s. - pub fn new(primary: A, secondary: B) -> Self - where - A: Executor, - B: Executor::State>, - EM: UsesState::State>, - { + pub fn new(primary: A, secondary: B) -> Self { Self { primary, secondary } } @@ -41,19 +35,17 @@ impl CombinedExecutor { } } -impl Executor for CombinedExecutor +impl Executor for CombinedExecutor where - A: Executor, - B: Executor::State>, - Self::State: HasExecutions, - EM: UsesState::State>, + A: Executor, + B: Executor, { fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &I, ) -> Result { self.primary.run_target(fuzzer, state, mgr, input) } @@ -80,13 +72,6 @@ where } } -impl UsesState for CombinedExecutor -where - A: UsesState, -{ - type State = A::State; -} - impl HasObservers for CombinedExecutor where A: HasObservers, diff --git a/libafl/src/executors/command.rs b/libafl/src/executors/command.rs index 2749d6aef2..968b717926 100644 --- a/libafl/src/executors/command.rs +++ b/libafl/src/executors/command.rs @@ -46,12 +46,14 @@ use nix::{ use typed_builder::TypedBuilder; use super::HasTimeout; +#[cfg(target_os = "linux")] +use crate::executors::hooks::ExecutorHooksTuple; use crate::{ corpus::Corpus, - executors::{hooks::ExecutorHooksTuple, Executor, ExitKind, HasObservers}, - inputs::{HasTargetBytes, Input, UsesInput}, + executors::{Executor, ExitKind, HasObservers}, + inputs::HasTargetBytes, observers::{ObserversTuple, StdErrObserver, StdOutObserver}, - state::{HasCorpus, HasExecutions, State, UsesState}, + state::{HasCorpus, HasExecutions}, std::borrow::ToOwned, Error, }; @@ -321,11 +323,7 @@ where } } -impl CommandExecutor -where - T: Debug, - OT: Debug, -{ +impl CommandExecutor { /// Accesses the inner value pub fn inner(&mut self) -> &mut T { &mut self.configurer @@ -333,13 +331,17 @@ where } // this only works on unix because of the reliance on checking the process signal for detecting OOM -impl CommandExecutor +impl CommandExecutor where - S: State + HasExecutions + UsesInput, - T: CommandConfigurator + Debug, - OT: Debug + ObserversTuple, + S: HasExecutions + HasCorpus, + T: CommandConfigurator<::Input> + Debug, + OT: ObserversTuple<::Input, S>, { - fn execute_input_with_command(&mut self, state: &mut S, input: &I) -> Result { + fn execute_input_with_command( + &mut self, + state: &mut S, + input: &::Input, + ) -> Result { use wait_timeout::ChildExt; *state.executions_mut() += 1; @@ -389,19 +391,18 @@ where } } -impl Executor for CommandExecutor +impl Executor::Input, S, Z> for CommandExecutor where - EM: UsesState, - S: State + HasExecutions + UsesInput, - T: CommandConfigurator + Debug, - OT: Debug + MatchName + ObserversTuple, + S: HasExecutions + HasCorpus, + T: CommandConfigurator<::Input> + Debug, + OT: MatchName + ObserversTuple<::Input, S>, { fn run_target( &mut self, _fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, _mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { self.execute_input_with_command(state, input) } @@ -425,13 +426,13 @@ where } #[cfg(target_os = "linux")] -impl Executor for CommandExecutor +impl Executor::Input, S, Z> + for CommandExecutor where - EM: UsesState, - S: State + HasExecutions + UsesInput, - T: CommandConfigurator + Debug, - OT: Debug + MatchName + ObserversTuple, - HT: ExecutorHooksTuple, + S: HasCorpus + HasExecutions, + T: CommandConfigurator<::Input, Pid> + Debug, + OT: MatchName + ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple<::Input, S>, { /// Linux specific low level implementation, to directly handle `fork`, `exec` and use linux /// `ptrace` @@ -441,9 +442,9 @@ where fn run_target( &mut self, _fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, _mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { *state.executions_mut() += 1; @@ -471,7 +472,7 @@ where self.observers.pre_exec_child_all(state, input)?; if *state.executions() == 1 { - self.hooks.init_all::(state); + self.hooks.init_all(state); } self.hooks.pre_exec_all(state, input); @@ -501,18 +502,10 @@ where } } -impl UsesState for CommandExecutor -where - S: State, -{ - type State = S; -} - impl HasObservers for CommandExecutor where - S: State, - T: Debug, - OT: ObserversTuple, + S: HasCorpus, + OT: ObserversTuple<::Input, S>, { type Observers = OT; @@ -695,9 +688,9 @@ impl CommandExecutorBuilder { observers: OT, ) -> Result, Error> where - OT: MatchName + ObserversTuple, - S: UsesInput, - S::Input: Input + HasTargetBytes, + S: HasCorpus, + ::Input: HasTargetBytes, + OT: MatchName + ObserversTuple<::Input, S>, { let Some(program) = &self.program else { return Err(Error::illegal_argument( @@ -744,12 +737,9 @@ impl CommandExecutorBuilder { timeout: self.timeout, command, }; - Ok( - >::into_executor::( - configurator, - observers, - ), - ) + Ok(::Input, + >>::into_executor::(configurator, observers)) } } @@ -757,7 +747,7 @@ impl CommandExecutorBuilder { /// # Example /// ``` /// use std::{io::Write, process::{Stdio, Command, Child}, time::Duration}; -/// use libafl::{Error, inputs::{BytesInput, HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::{UsesState, HasExecutions}}; +/// use libafl::{Error, corpus::Corpus, inputs::{BytesInput, HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::{HasCorpus, UsesState, HasExecutions}}; /// use libafl_bolts::AsSlice; /// #[derive(Debug)] /// struct MyExecutor; @@ -787,10 +777,12 @@ impl CommandExecutorBuilder { /// } /// } /// -/// fn make_executor() -> impl Executor +/// fn make_executor() -> impl Executor /// where /// EM: UsesState, /// EM::State: UsesInput + HasExecutions, +/// S: HasCorpus + HasExecutions, +/// S::Corpus: Corpus, /// { /// MyExecutor.into_executor(()) /// } @@ -826,10 +818,7 @@ pub trait CommandConfigurator: Sized { } /// Create an `Executor` from this `CommandConfigurator`. - fn into_executor(self, observers: OT) -> CommandExecutor - where - OT: MatchName, - { + fn into_executor(self, observers: OT) -> CommandExecutor { CommandExecutor { configurer: self, observers, @@ -844,12 +833,7 @@ pub trait CommandConfigurator: Sized { self, observers: OT, hooks: HT, - ) -> CommandExecutor - where - OT: MatchName, - HT: ExecutorHooksTuple, - S: UsesInput, - { + ) -> CommandExecutor { CommandExecutor { configurer: self, observers, @@ -885,7 +869,7 @@ mod tests { Executor, }, fuzzer::NopFuzzer, - inputs::BytesInput, + inputs::{BytesInput, NopInput}, monitors::SimpleMonitor, state::NopState, }; @@ -893,9 +877,10 @@ mod tests { #[test] #[cfg_attr(miri, ignore)] fn test_builder() { - let mut mgr = SimpleEventManager::new(SimpleMonitor::new(|status| { - log::info!("{status}"); - })); + let mut mgr: SimpleEventManager<_, NopState> = + SimpleEventManager::new(SimpleMonitor::new(|status| { + log::info!("{status}"); + })); let mut executor = CommandExecutor::builder(); executor diff --git a/libafl/src/executors/differential.rs b/libafl/src/executors/differential.rs index 4c5ae3fb5a..b6a057def5 100644 --- a/libafl/src/executors/differential.rs +++ b/libafl/src/executors/differential.rs @@ -6,6 +6,7 @@ use core::{ cell::UnsafeCell, fmt::Debug, + marker::PhantomData, ops::{Deref, DerefMut}, ptr, }; @@ -20,28 +21,23 @@ use super::HasTimeout; use crate::{ corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, - inputs::UsesInput, observers::{DifferentialObserversTuple, ObserversTuple}, - state::{HasCorpus, UsesState}, + state::HasCorpus, Error, }; /// A [`DiffExecutor`] wraps a primary executor, forwarding its methods, and a secondary one #[derive(Debug)] -pub struct DiffExecutor { +pub struct DiffExecutor { primary: A, secondary: B, observers: UnsafeCell>, + phantom: PhantomData, } -impl DiffExecutor { +impl DiffExecutor { /// Create a new `DiffExecutor`, wrapping the given `executor`s. - pub fn new(primary: A, secondary: B, observers: DOT) -> Self - where - A: UsesState + HasObservers, - B: UsesState::State> + HasObservers, - DOT: DifferentialObserversTuple, - { + pub fn new(primary: A, secondary: B, observers: DOT) -> Self { Self { primary, secondary, @@ -50,6 +46,7 @@ impl DiffExecutor { secondary: OwnedMutPtr::Ptr(ptr::null_mut()), differential: observers, }), + phantom: PhantomData, } } @@ -64,23 +61,23 @@ impl DiffExecutor { } } -impl Executor for DiffExecutor +impl Executor::Input, S, Z> + for DiffExecutor where - A: Executor + HasObservers, - B: Executor::State> + HasObservers, - EM: UsesState::State>, - ::Observers: - ObserversTuple<<::State as UsesInput>::Input, ::State>, - ::Observers: - ObserversTuple<<::State as UsesInput>::Input, ::State>, - DOT: DifferentialObserversTuple + MatchName, + 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, { fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { self.observers(); // update in advance let observers = self.observers.get_mut(); @@ -120,7 +117,7 @@ where } } -impl HasTimeout for DiffExecutor +impl HasTimeout for DiffExecutor where A: HasTimeout, B: HasTimeout, @@ -154,11 +151,9 @@ pub struct ProxyObserversTuple { impl ObserversTuple for ProxyObserversTuple where - A: ObserversTuple, - B: ObserversTuple, + A: MatchName, + B: MatchName, DOT: DifferentialObserversTuple + MatchName, - S: HasCorpus, - S::Corpus: Corpus, { fn pre_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error> { self.differential.pre_exec_all(state, input) @@ -238,20 +233,14 @@ impl ProxyObserversTuple { } } -impl UsesState for DiffExecutor +impl HasObservers for DiffExecutor where - A: UsesState, -{ - type State = A::State; -} - -impl HasObservers for DiffExecutor -where - A: UsesState + HasObservers, - B: UsesState::State> + HasObservers, - DOT: DifferentialObserversTuple + MatchName, - OTA: ObserversTuple<::Input, ::State>, - OTB: ObserversTuple<::Input, ::State>, + A: HasObservers, + B: HasObservers, + DOT: DifferentialObserversTuple::Input, S> + MatchName, + OTA: ObserversTuple<::Input, S>, + OTB: ObserversTuple<::Input, S>, + S: HasCorpus, { type Observers = ProxyObserversTuple; diff --git a/libafl/src/executors/forkserver.rs b/libafl/src/executors/forkserver.rs index db8c0a8430..3d42c9e548 100644 --- a/libafl/src/executors/forkserver.rs +++ b/libafl/src/executors/forkserver.rs @@ -43,13 +43,12 @@ use crate::observers::{ get_asan_runtime_flags, get_asan_runtime_flags_with_log_path, AsanBacktraceObserver, }; use crate::{ + corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, - inputs::{ - BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter, UsesInput, - }, + inputs::{BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter}, mutators::Tokens, observers::{MapObserver, Observer, ObserversTuple}, - state::{HasExecutions, State, UsesState}, + state::{HasCorpus, HasExecutions}, Error, }; @@ -662,8 +661,8 @@ impl ForkserverExecutor<(), (), (), UnixShMemProvider> { impl ForkserverExecutor where - OT: ObserversTuple, - S: UsesInput, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, SP: ShMemProvider, TC: TargetBytesConverter, { @@ -842,9 +841,9 @@ where #[expect(clippy::pedantic)] pub fn build(mut self, observers: OT) -> Result, Error> where - OT: ObserversTuple, - S: UsesInput, - S::Input: Input, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, + ::Input: Input, TC: TargetBytesConverter, SP: ShMemProvider, { @@ -910,10 +909,10 @@ where ) -> Result, Error> where MO: MapObserver + Truncate, // TODO maybe enforce Entry = u8 for the cov map - A: Observer + AsMut, - OT: ObserversTuple + Prepend, - S: UsesInput, - S::Input: Input + HasTargetBytes, + A: Observer<::Input, S> + AsMut, + OT: ObserversTuple<::Input, S> + Prepend, + ::Input: Input + HasTargetBytes, + S: HasCorpus, SP: ShMemProvider, { let (forkserver, input_file, map) = self.build_helper()?; @@ -1580,21 +1579,21 @@ impl Default } } -impl Executor for ForkserverExecutor +impl Executor::Input, S, Z> + for ForkserverExecutor where - OT: ObserversTuple, + OT: ObserversTuple<::Input, S>, SP: ShMemProvider, - S: State + HasExecutions, - TC: TargetBytesConverter, - EM: UsesState, + S: HasCorpus + HasExecutions, + TC: TargetBytesConverter::Input>, { #[inline] fn run_target( &mut self, _fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, _mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { self.execute_input(state, input) } @@ -1615,18 +1614,10 @@ where } } -impl UsesState for ForkserverExecutor -where - S: State, - SP: ShMemProvider, -{ - type State = S; -} - impl HasObservers for ForkserverExecutor where - OT: ObserversTuple, - S: State, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, SP: ShMemProvider, { type Observers = OT; @@ -1654,7 +1645,9 @@ mod tests { use serial_test::serial; use crate::{ + corpus::NopCorpus, executors::forkserver::{ForkserverExecutor, FAILED_TO_START_FORKSERVER_MSG}, + inputs::BytesInput, observers::{ConstMapObserver, HitcountsMapObserver}, Error, }; @@ -1684,7 +1677,7 @@ mod tests { .coverage_map_size(MAP_SIZE) .debug_child(false) .shmem_provider(&mut shmem_provider) - .build::<_, ()>(tuple_list!(edges_observer)); + .build::<_, NopCorpus>(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 36ec47bbc5..e6cc114b73 100644 --- a/libafl/src/executors/hooks/inprocess.rs +++ b/libafl/src/executors/hooks/inprocess.rs @@ -23,16 +23,15 @@ use windows::Win32::System::Threading::{CRITICAL_SECTION, PTP_TIMER}; use crate::executors::hooks::timer::TimerStruct; #[cfg(all(unix, feature = "std"))] use crate::executors::hooks::unix::unix_signal_handler; -#[cfg(windows)] -use crate::state::State; #[cfg(any(unix, windows))] -use crate::{corpus::Corpus, observers::ObserversTuple, state::UsesState}; +use crate::observers::ObserversTuple; use crate::{ + corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers}, feedbacks::Feedback, - inputs::UsesInput, - state::{HasCorpus, HasExecutions, HasSolutions}, + inputs::{Input, UsesInput}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, Error, HasObjective, }; @@ -84,10 +83,7 @@ pub trait HasTimeout { fn handle_timeout(&mut self, data: &mut InProcessExecutorHandlerData) -> bool; } -impl HasTimeout for InProcessHooks -where - S: UsesInput, -{ +impl HasTimeout for InProcessHooks { #[cfg(feature = "std")] fn timer(&self) -> &TimerStruct { &self.timer @@ -191,14 +187,14 @@ where } } -impl ExecutorHook for InProcessHooks +impl ExecutorHook<::Input, S> for InProcessHooks where - S: UsesInput, + S: HasCorpus, { - fn init(&mut self, _state: &mut S) {} + fn init(&mut self, _state: &mut S) {} /// Call before running a target. #[expect(unused_variables)] - fn pre_exec(&mut self, state: &mut S, input: &S::Input) { + fn pre_exec(&mut self, state: &mut S, input: &::Input) { #[cfg(feature = "std")] unsafe { let data = &raw mut GLOBAL_STATE; @@ -211,7 +207,7 @@ where } /// Call after running a target. - fn post_exec(&mut self, _state: &mut S, _input: &S::Input) { + fn post_exec(&mut self, _state: &mut S, _input: &::Input) { // timeout stuff // # Safety // We're calling this only once per execution, in a single thread. @@ -220,23 +216,24 @@ where } } -impl InProcessHooks -where - S: UsesInput, -{ +impl InProcessHooks { /// Create new [`InProcessHooks`]. #[cfg(unix)] #[allow(unused_variables)] // for `exec_tmout` without `std` pub fn new(exec_tmout: Duration) -> Result where - E: Executor + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus, + E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + HasCurrentTestcase + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, + S::Solutions: Corpus::Input>, { // # Safety // We get a pointer to `GLOBAL_STATE` that will be initialized at this point in time. @@ -245,7 +242,7 @@ where #[cfg(all(not(miri), unix, feature = "std"))] let data = unsafe { &raw mut GLOBAL_STATE }; #[cfg(feature = "std")] - unix_signal_handler::setup_panic_hook::(); + unix_signal_handler::setup_panic_hook::(); // # Safety // Setting up the signal handlers with a pointer to the `GLOBAL_STATE` which should not be NULL at this point. // We are the sole users of `GLOBAL_STATE` right now, and only dereference it in case of Segfault/Panic. @@ -257,10 +254,10 @@ where compiler_fence(Ordering::SeqCst); Ok(Self { #[cfg(feature = "std")] - crash_handler: unix_signal_handler::inproc_crash_handler:: + crash_handler: unix_signal_handler::inproc_crash_handler:: as *const c_void, #[cfg(feature = "std")] - timeout_handler: unix_signal_handler::inproc_timeout_handler:: + timeout_handler: unix_signal_handler::inproc_timeout_handler:: as *const _, #[cfg(feature = "std")] timer: TimerStruct::new(exec_tmout), @@ -273,14 +270,18 @@ where #[allow(unused_variables)] // for `exec_tmout` without `std` pub fn new(exec_tmout: Duration) -> Result where - E: Executor + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: State + HasExecutions + HasSolutions + HasCorpus, + E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + HasCurrentTestcase + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, + S::Solutions: Corpus::Input>, { let ret; #[cfg(feature = "std")] @@ -290,6 +291,7 @@ where E, EM, OF, + S, Z, >(); setup_exception_handler(data)?; @@ -299,6 +301,7 @@ where E, EM, OF, + S, Z, > as *const _; let timeout_handler = @@ -306,6 +309,7 @@ where E, EM, OF, + S, Z, > as *const c_void; let timer = TimerStruct::new(exec_tmout, timeout_handler); @@ -331,10 +335,13 @@ where #[expect(unused_variables)] pub fn new(exec_tmout: Duration) -> Result where - E: Executor + HasObservers + HasInProcessHooks, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus, + E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + UsesInput::Input>, 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 16af31f8b2..6684189450 100644 --- a/libafl/src/executors/hooks/inprocess_fork.rs +++ b/libafl/src/executors/hooks/inprocess_fork.rs @@ -14,15 +14,15 @@ use libafl_bolts::os::unix_signals::{ucontext_t, Signal, SignalHandler}; use libc::siginfo_t; use crate::{ + corpus::Corpus, executors::{ common_signals, hooks::ExecutorHook, inprocess_fork::{child_signal_handlers, ForkHandlerFuncPtr}, HasObservers, }, - inputs::UsesInput, observers::ObserversTuple, - state::UsesState, + state::HasCorpus, Error, }; @@ -36,15 +36,15 @@ pub struct InChildProcessHooks { phantom: PhantomData, } -impl ExecutorHook for InChildProcessHooks +impl ExecutorHook<::Input, S> for InChildProcessHooks where - S: UsesInput, + S: HasCorpus, { /// Init this hook - fn init(&mut self, _state: &mut S) {} + fn init(&mut self, _state: &mut S) {} /// Call before running a target. - fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) { + fn pre_exec(&mut self, _state: &mut S, _input: &::Input) { unsafe { let data = &raw mut FORK_EXECUTOR_GLOBAL_DATA; (*data).crash_handler = self.crash_handler; @@ -53,15 +53,16 @@ where } } - fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {} + fn post_exec(&mut self, _state: &mut S, _input: &::Input) {} } impl InChildProcessHooks { /// Create new [`InChildProcessHooks`]. pub fn new() -> Result where - E: HasObservers + UsesState, - E::Observers: ObserversTuple<::Input, E::State>, + E: HasObservers, + E::Observers: ObserversTuple<::Input, S>, + S: HasCorpus, { #[cfg_attr(miri, allow(unused_variables, unused_unsafe))] unsafe { @@ -71,8 +72,16 @@ impl InChildProcessHooks { setup_signal_handler(data)?; compiler_fence(Ordering::SeqCst); Ok(Self { - crash_handler: child_signal_handlers::child_crash_handler:: as *const c_void, - timeout_handler: child_signal_handlers::child_timeout_handler:: as *const c_void, + crash_handler: child_signal_handlers::child_crash_handler::< + E, + ::Input, + S, + > as *const c_void, + timeout_handler: child_signal_handlers::child_timeout_handler::< + E, + ::Input, + S, + > as *const c_void, phantom: PhantomData, }) } diff --git a/libafl/src/executors/hooks/intel_pt.rs b/libafl/src/executors/hooks/intel_pt.rs index a712972e24..02889da393 100644 --- a/libafl/src/executors/hooks/intel_pt.rs +++ b/libafl/src/executors/hooks/intel_pt.rs @@ -10,11 +10,7 @@ use num_traits::SaturatingAdd; use serde::Serialize; use typed_builder::TypedBuilder; -use crate::{ - executors::{hooks::ExecutorHook, HasObservers}, - inputs::UsesInput, - Error, -}; +use crate::{corpus::Corpus, executors::hooks::ExecutorHook, state::HasCorpus, Error}; /// Info of a binary's section that can be used during `Intel PT` traces decoding #[derive(Debug, Clone, PartialEq, Eq)] @@ -40,18 +36,18 @@ pub struct IntelPTHook { map_len: usize, } -impl ExecutorHook for IntelPTHook +impl ExecutorHook<::Input, S> for IntelPTHook where - S: UsesInput + Serialize, + S: Serialize + HasCorpus, T: SaturatingAdd + From + Debug, { - fn init(&mut self, _state: &mut S) {} + fn init(&mut self, _state: &mut S) {} - fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) { + fn pre_exec(&mut self, _state: &mut S, _input: &::Input) { self.intel_pt.enable_tracing().unwrap(); } - fn post_exec(&mut self, _state: &mut S, _input: &S::Input) { + fn post_exec(&mut self, _state: &mut S, _input: &::Input) { let pt = &mut self.intel_pt; pt.disable_tracing().unwrap(); diff --git a/libafl/src/executors/hooks/mod.rs b/libafl/src/executors/hooks/mod.rs index 4296c3a16d..187704bca6 100644 --- a/libafl/src/executors/hooks/mod.rs +++ b/libafl/src/executors/hooks/mod.rs @@ -1,8 +1,6 @@ //! Hooks for the executors. //! These will be executed right before and after the executor's harness run. -use crate::{executors::HasObservers, inputs::UsesInput}; - /// windows crash/timeout handler and asan death callback #[cfg(windows)] pub mod windows; @@ -27,57 +25,47 @@ pub mod timer; pub mod intel_pt; /// The hook that runs before and after the executor runs the target -pub trait ExecutorHook -where - S: UsesInput, -{ +pub trait ExecutorHook { /// Init this hook - fn init(&mut self, state: &mut S); + fn init(&mut self, state: &mut S); /// The hook that runs before runs the target - fn pre_exec(&mut self, state: &mut S, input: &S::Input); + fn pre_exec(&mut self, state: &mut S, input: &I); /// The hook that runs before runs the target - fn post_exec(&mut self, state: &mut S, input: &S::Input); + fn post_exec(&mut self, state: &mut S, input: &I); } /// The hook that runs before and after the executor runs the target -pub trait ExecutorHooksTuple -where - S: UsesInput, -{ +pub trait ExecutorHooksTuple { /// Init these hooks - fn init_all(&mut self, state: &mut S); + fn init_all(&mut self, state: &mut S); /// The hooks that runs before runs the target - fn pre_exec_all(&mut self, state: &mut S, input: &S::Input); + fn pre_exec_all(&mut self, state: &mut S, input: &I); /// The hooks that runs after runs the target - fn post_exec_all(&mut self, state: &mut S, input: &S::Input); + fn post_exec_all(&mut self, state: &mut S, input: &I); } -impl ExecutorHooksTuple for () -where - S: UsesInput, -{ - fn init_all(&mut self, _state: &mut S) {} - fn pre_exec_all(&mut self, _state: &mut S, _input: &S::Input) {} - fn post_exec_all(&mut self, _state: &mut S, _input: &S::Input) {} +impl ExecutorHooksTuple for () { + fn init_all(&mut self, _state: &mut S) {} + fn pre_exec_all(&mut self, _state: &mut S, _input: &I) {} + fn post_exec_all(&mut self, _state: &mut S, _input: &I) {} } -impl ExecutorHooksTuple for (Head, Tail) +impl ExecutorHooksTuple for (Head, Tail) where - S: UsesInput, - Head: ExecutorHook, - Tail: ExecutorHooksTuple, + Head: ExecutorHook, + Tail: ExecutorHooksTuple, { - fn init_all(&mut self, state: &mut S) { - self.0.init::(state); - self.1.init_all::(state); + fn init_all(&mut self, state: &mut S) { + self.0.init(state); + self.1.init_all(state); } - fn pre_exec_all(&mut self, state: &mut S, input: &S::Input) { + fn pre_exec_all(&mut self, state: &mut S, input: &I) { self.0.pre_exec(state, input); self.1.pre_exec_all(state, input); } - fn post_exec_all(&mut self, state: &mut S, input: &S::Input) { + fn post_exec_all(&mut self, state: &mut S, input: &I) { self.0.post_exec(state, input); self.1.post_exec_all(state, input); } diff --git a/libafl/src/executors/hooks/timer.rs b/libafl/src/executors/hooks/timer.rs index 3f335848be..3fb7dd72e6 100644 --- a/libafl/src/executors/hooks/timer.rs +++ b/libafl/src/executors/hooks/timer.rs @@ -289,7 +289,7 @@ impl TimerStruct { LeaveCriticalSection(self.critical_mut()); compiler_fence(Ordering::SeqCst); - SetThreadpoolTimer(*self.ptp_timer(), Some(&ft), 0, 0); + SetThreadpoolTimer(*self.ptp_timer(), Some(&ft), 0, None); } } @@ -375,7 +375,7 @@ impl TimerStruct { compiler_fence(Ordering::SeqCst); // previously this wa post_run_reset - SetThreadpoolTimer(*self.ptp_timer(), None, 0, 0); + SetThreadpoolTimer(*self.ptp_timer(), None, 0, None); } } } diff --git a/libafl/src/executors/hooks/unix.rs b/libafl/src/executors/hooks/unix.rs index e0f63d91a8..20cb7d559f 100644 --- a/libafl/src/executors/hooks/unix.rs +++ b/libafl/src/executors/hooks/unix.rs @@ -21,7 +21,7 @@ pub mod unix_signal_handler { fuzzer::HasObjective, inputs::{Input, UsesInput}, observers::ObserversTuple, - state::{HasCorpus, HasExecutions, HasSolutions, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, }; pub(crate) type HandlerFuncPtr = unsafe fn( @@ -77,16 +77,20 @@ pub mod unix_signal_handler { } /// invokes the `post_exec` hook on all observer in case of panic - pub fn setup_panic_hook() + pub fn setup_panic_hook() where - E: Executor + HasObservers, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCurrentTestcase + + HasCorpus + + UsesInput::Input>, + S::Solutions: Corpus::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, { let old_hook = panic::take_hook(); panic::set_hook(Box::new(move |panic_info| unsafe { @@ -96,12 +100,12 @@ pub mod unix_signal_handler { if (*data).is_valid() { // We are fuzzing! let executor = (*data).executor_mut::(); - let state = (*data).state_mut::(); - let input = (*data).take_current_input::<::Input>(); + let state = (*data).state_mut::(); + let input = (*data).take_current_input::<::Input>(); let fuzzer = (*data).fuzzer_mut::(); let event_mgr = (*data).event_mgr_mut::(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -123,20 +127,24 @@ pub mod unix_signal_handler { /// Well, signal handling is not safe #[cfg(unix)] #[allow(clippy::needless_pass_by_value)] // nightly no longer requires this - pub unsafe fn inproc_timeout_handler( + pub unsafe fn inproc_timeout_handler( _signal: Signal, _info: &mut siginfo_t, _context: Option<&mut ucontext_t>, data: &mut InProcessExecutorHandlerData, ) where - E: Executor + HasInProcessHooks + HasObservers, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus, + E: Executor::Input, S, Z> + HasInProcessHooks + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCurrentTestcase + + HasCorpus + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, + S::Solutions: Corpus::Input>, { // this stuff is for batch timeout if !data.executor_ptr.is_null() @@ -154,14 +162,14 @@ pub mod unix_signal_handler { } let executor = data.executor_mut::(); - let state = data.state_mut::(); + let state = data.state_mut::(); let event_mgr = data.event_mgr_mut::(); let fuzzer = data.fuzzer_mut::(); - let input = data.take_current_input::<::Input>(); + let input = data.take_current_input::<::Input>(); log::error!("Timeout in fuzz run."); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -180,20 +188,24 @@ pub mod unix_signal_handler { /// # Safety /// Well, signal handling is not safe #[allow(clippy::needless_pass_by_value)] // nightly no longer requires this - pub unsafe fn inproc_crash_handler( + pub unsafe fn inproc_crash_handler( signal: Signal, _info: &mut siginfo_t, _context: Option<&mut ucontext_t>, data: &mut InProcessExecutorHandlerData, ) where - E: Executor + HasObservers, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + HasCurrentTestcase + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, + S::Solutions: Corpus::Input>, { #[cfg(all(target_os = "android", target_arch = "aarch64"))] let _context = _context.map(|p| { @@ -205,10 +217,10 @@ pub mod unix_signal_handler { if data.is_valid() { let executor = data.executor_mut::(); // disarms timeout in case of timeout - let state = data.state_mut::(); + let state = data.state_mut::(); let event_mgr = data.event_mgr_mut::(); let fuzzer = data.fuzzer_mut::(); - let input = data.take_current_input::<::Input>(); + let input = data.take_current_input::<::Input>(); log::error!("Child crashed!"); @@ -233,7 +245,7 @@ pub mod unix_signal_handler { } } - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, diff --git a/libafl/src/executors/hooks/windows.rs b/libafl/src/executors/hooks/windows.rs index f0554848e9..fdcf0b88f5 100644 --- a/libafl/src/executors/hooks/windows.rs +++ b/libafl/src/executors/hooks/windows.rs @@ -17,23 +17,27 @@ pub mod windows_asan_handler { }, feedbacks::Feedback, fuzzer::HasObjective, - inputs::UsesInput, + inputs::{Input, UsesInput}, observers::ObserversTuple, - state::{HasCorpus, HasExecutions, HasSolutions, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, }; /// # Safety /// ASAN deatch handler - pub unsafe extern "C" fn asan_death_handler() + pub unsafe extern "C" fn asan_death_handler() where - E: Executor + HasObservers, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus, - E::Observers: ObserversTuple<::Input, E::State>, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCurrentTestcase + + HasCorpus + + UsesInput::Input>, + S::Solutions: Corpus::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, { let data = &raw mut GLOBAL_STATE; (*data).set_in_handler(true); @@ -78,16 +82,16 @@ pub mod windows_asan_handler { (*data).ptp_timer = None; } - let state = (*data).state_mut::(); + let state = (*data).state_mut::(); let fuzzer = (*data).fuzzer_mut::(); let event_mgr = (*data).event_mgr_mut::(); log::error!("Child crashed!"); // Make sure we don't crash in the crash handler forever. - let input = (*data).take_current_input::<::Input>(); + let input = (*data).take_current_input::<::Input>(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -138,7 +142,7 @@ pub mod windows_exception_handler { fuzzer::HasObjective, inputs::{Input, UsesInput}, observers::ObserversTuple, - state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, }; pub(crate) type HandlerFuncPtr = @@ -182,16 +186,20 @@ pub mod windows_exception_handler { /// # Safety /// Well, exception handling is not safe #[cfg(feature = "std")] - pub fn setup_panic_hook() + pub fn setup_panic_hook() where - E: HasObservers + Executor, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus, - E::Observers: ObserversTuple<::Input, E::State>, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCurrentTestcase + + HasCorpus + + UsesInput::Input>, + S::Solutions: Corpus::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, { let old_hook = panic::take_hook(); panic::set_hook(Box::new(move |panic_info| unsafe { @@ -216,13 +224,13 @@ pub mod windows_exception_handler { if (*data).is_valid() { // We are fuzzing! let executor = (*data).executor_mut::(); - let state = (*data).state_mut::(); + let state = (*data).state_mut::(); let fuzzer = (*data).fuzzer_mut::(); let event_mgr = (*data).event_mgr_mut::(); - let input = (*data).take_current_input::<::Input>(); + let input = (*data).take_current_input::<::Input>(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -242,19 +250,23 @@ pub mod windows_exception_handler { /// /// # Safety /// Well, exception handling is not safe - pub unsafe extern "system" fn inproc_timeout_handler( + pub unsafe extern "system" fn inproc_timeout_handler( _p0: *mut u8, global_state: *mut c_void, _p1: *mut u8, ) where - E: HasObservers + HasInProcessHooks + Executor, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: State + HasExecutions + HasSolutions + HasCorpus, + E: Executor::Input, S, Z> + HasInProcessHooks + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCurrentTestcase + + HasCorpus + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, + S::Solutions: Corpus::Input>, { let data: &mut InProcessExecutorHandlerData = &mut *(global_state as *mut InProcessExecutorHandlerData); @@ -277,7 +289,7 @@ pub mod windows_exception_handler { if data.in_target == 1 { let executor = data.executor_mut::(); - let state = data.state_mut::(); + let state = data.state_mut::(); let fuzzer = data.fuzzer_mut::(); let event_mgr = data.event_mgr_mut::(); @@ -286,12 +298,12 @@ pub mod windows_exception_handler { } else { log::error!("Timeout in fuzz run."); - let input = (data.current_input_ptr as *const ::Input) + let input = (data.current_input_ptr as *const ::Input) .as_ref() .unwrap(); data.current_input_ptr = ptr::null_mut(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -315,18 +327,22 @@ pub mod windows_exception_handler { /// /// # Safety /// Well, exception handling is not safe - pub unsafe fn inproc_crash_handler( + pub unsafe fn inproc_crash_handler( exception_pointers: *mut EXCEPTION_POINTERS, data: &mut InProcessExecutorHandlerData, ) where - E: Executor + HasObservers, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + HasCurrentTestcase + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, + S::Solutions: Corpus::Input>, { // Have we set a timer_before? if data.ptp_timer.is_some() { @@ -400,7 +416,7 @@ pub mod windows_exception_handler { data.ptp_timer = None; } - let state = data.state_mut::(); + let state = data.state_mut::(); let fuzzer = data.fuzzer_mut::(); let event_mgr = data.event_mgr_mut::(); @@ -412,7 +428,7 @@ pub mod windows_exception_handler { // Make sure we don't crash in the crash handler forever. if is_crash { - let input = data.take_current_input::<::Input>(); + let input = data.take_current_input::<::Input>(); { let mut bsod = Vec::new(); { @@ -424,7 +440,7 @@ pub mod windows_exception_handler { } log::error!("{}", std::str::from_utf8(&bsod).unwrap()); } - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, diff --git a/libafl/src/executors/inprocess/inner.rs b/libafl/src/executors/inprocess/inner.rs index 08c4f79e1a..24a868ec39 100644 --- a/libafl/src/executors/inprocess/inner.rs +++ b/libafl/src/executors/inprocess/inner.rs @@ -28,9 +28,9 @@ use crate::{ }, feedbacks::Feedback, fuzzer::HasObjective, - inputs::UsesInput, + inputs::{Input, UsesInput}, observers::ObserversTuple, - state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, Error, }; @@ -54,18 +54,7 @@ where } } -impl UsesState for GenericInProcessExecutorInner -where - S: State, -{ - type State = S; -} - -impl HasObservers for GenericInProcessExecutorInner -where - OT: ObserversTuple, - S: State, -{ +impl HasObservers for GenericInProcessExecutorInner { type Observers = OT; #[inline] @@ -81,8 +70,8 @@ where impl GenericInProcessExecutorInner where - HT: ExecutorHooksTuple, - S: State, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, { /// This function marks the boundary between the fuzzer and the target /// @@ -93,9 +82,9 @@ where pub unsafe fn enter_target( &mut self, fuzzer: &mut Z, - state: &mut ::State, + state: &mut S, mgr: &mut EM, - input: &::Input, + input: &::Input, executor_ptr: *const c_void, ) { unsafe { @@ -128,9 +117,9 @@ where pub fn leave_target( &mut self, _fuzzer: &mut Z, - _state: &mut ::State, + _state: &mut S, _mgr: &mut EM, - _input: &::Input, + _input: &::Input, ) { unsafe { let data = &raw mut GLOBAL_STATE; @@ -143,9 +132,9 @@ where impl GenericInProcessExecutorInner where - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: HasCorpus + HasExecutions + HasSolutions + UsesInput, + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, + S: HasCorpus + HasExecutions + HasSolutions, { /// Create a new in mem executor with the default timeout (5 sec) pub fn generic( @@ -156,14 +145,17 @@ where event_mgr: &mut EM, ) -> Result where - E: Executor + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, E::State>, + E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple<::Input, S>, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, E::Observers, S>, + S: HasCurrentTestcase + + HasCorpus + + HasSolutions + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + S::Solutions: Corpus::Input>, + ::Input: Input + Clone, { Self::with_timeout_generic::( user_hooks, @@ -186,14 +178,17 @@ where exec_tmout: Duration, ) -> Result where - E: Executor + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, E::State>, + E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple<::Input, S>, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, E::Observers, S>, + S: HasCurrentTestcase + + HasCorpus + + HasSolutions + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + S::Solutions: Corpus::Input>, + ::Input: Input + Clone, { let mut me = Self::with_timeout_generic::( user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, @@ -219,18 +214,21 @@ where timeout: Duration, ) -> Result where - E: Executor + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, E::State>, + E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple<::Input, S>, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, E::Observers, S>, + S: HasCurrentTestcase + + HasCorpus + + HasSolutions + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + S::Solutions: Corpus::Input>, + ::Input: Input + Clone, { let default = InProcessHooks::new::(timeout)?; let mut hooks = tuple_list!(default).merge(user_hooks); - hooks.init_all::(state); + hooks.init_all(state); #[cfg(windows)] // Some initialization necessary for windows. @@ -275,10 +273,7 @@ where } } -impl HasInProcessHooks for GenericInProcessExecutorInner -where - S: UsesInput, -{ +impl HasInProcessHooks for GenericInProcessExecutorInner { /// the timeout handler #[inline] fn inprocess_hooks(&self) -> &InProcessHooks { diff --git a/libafl/src/executors/inprocess/mod.rs b/libafl/src/executors/inprocess/mod.rs index 0efb911448..d6644f0c1c 100644 --- a/libafl/src/executors/inprocess/mod.rs +++ b/libafl/src/executors/inprocess/mod.rs @@ -16,6 +16,8 @@ use libafl_bolts::tuples::{tuple_list, RefIndexable}; #[cfg(any(unix, feature = "std"))] use crate::executors::hooks::inprocess::GLOBAL_STATE; +#[cfg(any(unix, feature = "std"))] +use crate::ExecutionProcessor; use crate::{ corpus::{Corpus, Testcase}, events::{Event, EventFirer, EventRestarter}, @@ -26,13 +28,11 @@ use crate::{ }, feedbacks::Feedback, fuzzer::HasObjective, - inputs::UsesInput, + inputs::{Input, UsesInput}, observers::ObserversTuple, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions, State, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, Error, HasMetadata, }; -#[cfg(any(unix, feature = "std"))] -use crate::{ExecutionProcessor, HasScheduler}; /// The inner structure of `InProcessExecutor`. pub mod inner; @@ -55,14 +55,7 @@ pub type OwnedInProcessExecutor = GenericInProcessExecutor< >; /// The inmem executor simply calls a target function, then returns afterwards. -pub struct GenericInProcessExecutor -where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State, -{ +pub struct GenericInProcessExecutor { harness_fn: HB, inner: GenericInProcessExecutorInner, phantom: PhantomData<(*const H, HB)>, @@ -70,11 +63,7 @@ where impl Debug for GenericInProcessExecutor where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple + Debug, - S: State, + OT: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("GenericInProcessExecutor") @@ -84,32 +73,21 @@ where } } -impl UsesState for GenericInProcessExecutor -where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State, -{ - type State = S; -} - -impl Executor for GenericInProcessExecutor +impl Executor::Input, S, Z> + for GenericInProcessExecutor where - EM: UsesState, - H: FnMut(&S::Input) -> ExitKind + ?Sized, + S: HasCorpus + HasExecutions, + OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple<::Input, S>, HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State + HasExecutions, + H: FnMut(&::Input) -> ExitKind + Sized, { fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { *state.executions_mut() += 1; unsafe { @@ -127,14 +105,7 @@ where } } -impl HasObservers for GenericInProcessExecutor -where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State, -{ +impl HasObservers for GenericInProcessExecutor { type Observers = OT; #[inline] @@ -150,11 +121,15 @@ where impl<'a, H, OT, S> InProcessExecutor<'a, H, OT, S> where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - OT: ObserversTuple, - S: HasExecutions + HasSolutions + HasCorpus + State, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me + H: FnMut(&::Input) -> ExitKind + Sized, + OT: ObserversTuple<::Input, S>, + S: HasCorpus + + HasCurrentTestcase + + UsesInput::Input> + + HasExecutions + + HasSolutions, + S::Solutions: Corpus::Input>, + ::Input: Input, { /// Create a new in mem executor with the default timeout (5 sec) pub fn new( @@ -165,13 +140,11 @@ where event_mgr: &mut EM, ) -> Result where - Self: Executor + HasObservers, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, { - Self::with_timeout_generic( + Self::with_timeout_generic::( tuple_list!(), harness_fn, observers, @@ -193,13 +166,9 @@ where exec_tmout: Duration, ) -> Result where - Self: Executor, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { let inner = GenericInProcessExecutorInner::batched_timeout_generic::( tuple_list!(), @@ -234,13 +203,9 @@ where timeout: Duration, ) -> Result where - Self: Executor, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { let inner = GenericInProcessExecutorInner::with_timeout_generic::( tuple_list!(), @@ -261,13 +226,17 @@ where impl GenericInProcessExecutor where - H: FnMut(&S::Input) -> ExitKind + ?Sized, + H: FnMut(&::Input) -> ExitKind + Sized, HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State + HasExecutions + HasSolutions + HasCorpus, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, + S: HasCorpus + + HasCurrentTestcase + + UsesInput::Input> + + HasExecutions + + HasSolutions, + S::Solutions: Corpus::Input>, + ::Input: Input, { /// Create a new in mem executor with the default timeout (5 sec) pub fn generic( @@ -279,13 +248,11 @@ where event_mgr: &mut EM, ) -> Result where - Self: Executor, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, { - Self::with_timeout_generic( + Self::with_timeout_generic::( user_hooks, harness_fn, observers, @@ -308,13 +275,9 @@ where exec_tmout: Duration, ) -> Result where - Self: Executor, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { let inner = GenericInProcessExecutorInner::batched_timeout_generic::( user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, @@ -345,13 +308,9 @@ where timeout: Duration, ) -> Result where - Self: Executor, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { let inner = GenericInProcessExecutorInner::with_timeout_generic::( user_hooks, observers, fuzzer, state, event_mgr, timeout, @@ -390,10 +349,7 @@ where } /// The struct has [`InProcessHooks`]. -pub trait HasInProcessHooks -where - S: UsesInput, -{ +pub trait HasInProcessHooks { /// Get the in-process handlers. fn inprocess_hooks(&self) -> &InProcessHooks; @@ -401,14 +357,7 @@ where fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks; } -impl HasInProcessHooks for GenericInProcessExecutor -where - H: FnMut(&::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State + HasExecutions + HasSolutions + HasCorpus, -{ +impl HasInProcessHooks for GenericInProcessExecutor { /// the timeout handler #[inline] fn inprocess_hooks(&self) -> &InProcessHooks { @@ -424,21 +373,26 @@ where #[inline] /// Save state if it is an objective -pub fn run_observers_and_save_state( +pub fn run_observers_and_save_state( executor: &mut E, - state: &mut E::State, - input: &E::Input, + state: &mut S, + input: &::Input, fuzzer: &mut Z, event_mgr: &mut EM, exitkind: ExitKind, ) where - E: Executor + HasObservers, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + HasCurrentTestcase + + UsesInput::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me + ::Input: Input + Clone, + S::Solutions: Corpus::Input>, { let mut observers = executor.observers_mut(); @@ -491,29 +445,33 @@ pub fn run_observers_and_save_state( /// # Safety /// This will directly access `GLOBAL_STATE` and related data pointers #[cfg(any(unix, feature = "std"))] -pub unsafe fn generic_inproc_crash_handler() +pub unsafe fn generic_inproc_crash_handler() where - E: Executor + HasObservers, - E::Observers: ObserversTuple<::Input, E::State>, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + HasCurrentTestcase + + UsesInput::Input>, + ::Input: Input + Clone, + S::Solutions: Corpus::Input>, Z: HasObjective - + HasScheduler - + ExecutionProcessor, - <::State as HasSolutions>::Solutions: Corpus, //delete me + + ExecutionProcessor::Input, E::Observers, S>, { let data = &raw mut GLOBAL_STATE; let in_handler = (*data).set_in_handler(true); if (*data).is_valid() { let executor = (*data).executor_mut::(); - let state = (*data).state_mut::(); + let state = (*data).state_mut::(); let event_mgr = (*data).event_mgr_mut::(); let fuzzer = (*data).fuzzer_mut::(); - let input = (*data).take_current_input::<::Input>(); + let input = (*data).take_current_input::<::Input>(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, diff --git a/libafl/src/executors/inprocess/stateful.rs b/libafl/src/executors/inprocess/stateful.rs index b24d3b54b0..c47aec1e71 100644 --- a/libafl/src/executors/inprocess/stateful.rs +++ b/libafl/src/executors/inprocess/stateful.rs @@ -20,9 +20,9 @@ use crate::{ }, feedbacks::Feedback, fuzzer::HasObjective, - inputs::UsesInput, + inputs::{Input, UsesInput}, observers::ObserversTuple, - state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, Error, }; @@ -44,14 +44,7 @@ pub type OwnedInProcessExecutor = StatefulGenericInProcessExecutor< /// The inmem executor simply calls a target function, then returns afterwards. /// The harness can access the internal state of the executor. -pub struct StatefulGenericInProcessExecutor -where - H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State, -{ +pub struct StatefulGenericInProcessExecutor { /// The harness function, being executed for each fuzzing loop execution harness_fn: HB, /// The state used as argument of the harness @@ -63,11 +56,7 @@ where impl Debug for StatefulGenericInProcessExecutor where - H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple + Debug, - S: State, + OT: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("StatefulGenericInProcessExecutor") @@ -77,33 +66,21 @@ where } } -impl UsesState for StatefulGenericInProcessExecutor -where - H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State, -{ - type State = S; -} - -impl Executor +impl Executor::Input, S, Z> for StatefulGenericInProcessExecutor where - EM: UsesState, - H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + Sized, HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State + HasExecutions, + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, + S: HasCorpus + HasExecutions, { fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { *state.executions_mut() += 1; unsafe { @@ -123,11 +100,11 @@ where impl HasObservers for StatefulGenericInProcessExecutor where - H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + Sized, HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State, + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, { type Observers = OT; #[inline] @@ -143,11 +120,15 @@ where impl<'a, H, OT, S, ES> StatefulInProcessExecutor<'a, H, OT, S, ES> where - H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + ?Sized, - OT: ObserversTuple, - S: HasExecutions + HasSolutions + HasCorpus + State, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me + H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + Sized, + OT: ObserversTuple<::Input, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + HasCurrentTestcase + + UsesInput::Input>, + ::Input: Clone + Input, + S::Solutions: Corpus::Input>, { /// Create a new in mem executor with the default timeout (5 sec) pub fn new( @@ -159,10 +140,8 @@ where event_mgr: &mut EM, ) -> Result where - Self: Executor, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, { Self::with_timeout_generic( @@ -189,13 +168,9 @@ where exec_tmout: Duration, ) -> Result where - Self: Executor, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { let inner = GenericInProcessExecutorInner::batched_timeout_generic::( tuple_list!(), @@ -232,13 +207,9 @@ where timeout: Duration, ) -> Result where - Self: Executor, EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { let inner = GenericInProcessExecutorInner::with_timeout_generic::( tuple_list!(), @@ -258,14 +229,7 @@ where } } -impl StatefulGenericInProcessExecutor -where - H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State, -{ +impl StatefulGenericInProcessExecutor { /// The executor state given to the harness pub fn exposed_executor_state(&self) -> &ES { &self.exposed_executor_state @@ -279,13 +243,18 @@ where impl StatefulGenericInProcessExecutor where - H: FnMut(&mut ES, &mut S, &S::Input) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + Sized, HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State + HasExecutions + HasSolutions + HasCorpus, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, + S: HasCorpus + + HasExecutions + + HasSolutions + + HasCorpus + + HasCurrentTestcase + + UsesInput::Input>, + S::Solutions: Corpus::Input>, + ::Input: Input + Clone, { /// Create a new in mem executor with the default timeout (5 sec) pub fn generic( @@ -299,8 +268,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, { Self::with_timeout_generic( @@ -330,11 +298,8 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { let inner = GenericInProcessExecutorInner::batched_timeout_generic::( user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, @@ -369,11 +334,8 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback, - S: State, + OF: Feedback::Input, OT, S>, Z: HasObjective, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { let inner = GenericInProcessExecutorInner::with_timeout_generic::( user_hooks, observers, fuzzer, state, event_mgr, timeout, @@ -414,12 +376,6 @@ where impl HasInProcessHooks for StatefulGenericInProcessExecutor -where - H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + ?Sized, - HB: BorrowMut, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State + HasExecutions + HasSolutions + HasCorpus, { /// the timeout handler #[inline] diff --git a/libafl/src/executors/inprocess_fork/inner.rs b/libafl/src/executors/inprocess_fork/inner.rs index ad4b08b348..50b9bfa53a 100644 --- a/libafl/src/executors/inprocess_fork/inner.rs +++ b/libafl/src/executors/inprocess_fork/inner.rs @@ -20,7 +20,7 @@ use nix::{ #[cfg(all(unix, not(target_os = "linux")))] use crate::executors::hooks::timer::{setitimer, Itimerval, Timeval, ITIMER_REAL}; use crate::{ - events::{EventFirer, EventRestarter}, + corpus::Corpus, executors::{ hooks::{ inprocess_fork::{InChildProcessHooks, FORK_EXECUTOR_GLOBAL_DATA}, @@ -28,9 +28,8 @@ use crate::{ }, ExitKind, HasObservers, }, - inputs::UsesInput, observers::ObserversTuple, - state::{State, UsesState}, + state::HasCorpus, Error, }; @@ -73,13 +72,6 @@ where } } -impl UsesState for GenericInProcessForkExecutorInner -where - S: State, -{ - type State = S; -} - #[cfg(target_os = "linux")] fn parse_itimerspec(timeout: Duration) -> libc::itimerspec { let milli_sec = timeout.as_millis(); @@ -116,18 +108,17 @@ fn parse_itimerval(timeout: Duration) -> Itimerval { impl GenericInProcessForkExecutorInner where - OT: ObserversTuple + Debug, - S: State + UsesInput, + HT: ExecutorHooksTuple<::Input, S>, + S: HasCorpus, SP: ShMemProvider, - HT: ExecutorHooksTuple, - EM: EventFirer + EventRestarter, + OT: ObserversTuple<::Input, S>, { pub(super) unsafe fn pre_run_target_child( &mut self, fuzzer: &mut Z, - state: &mut as UsesState>::State, + state: &mut S, mgr: &mut EM, - input: & as UsesInput>::Input, + input: &::Input, ) -> Result<(), Error> { self.shmem_provider.post_fork(true)?; @@ -160,9 +151,9 @@ where pub(super) unsafe fn post_run_target_child( &mut self, fuzzer: &mut Z, - state: &mut as UsesState>::State, + state: &mut S, mgr: &mut EM, - input: & as UsesInput>::Input, + input: &::Input, ) { self.observers .post_exec_child_all(state, input, &ExitKind::Ok) @@ -209,18 +200,18 @@ where impl GenericInProcessForkExecutorInner where - HT: ExecutorHooksTuple, - S: State, - OT: ObserversTuple, + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, { #[inline] /// This function marks the boundary between the fuzzer and the target. pub fn enter_target( &mut self, _fuzzer: &mut Z, - state: &mut ::State, + state: &mut S, _event_mgr: &mut EM, - input: &::Input, + input: &::Input, ) { unsafe { let data = &raw mut FORK_EXECUTOR_GLOBAL_DATA; @@ -245,9 +236,9 @@ where pub fn leave_target( &mut self, _fuzzer: &mut Z, - _state: &mut ::State, + _state: &mut S, _event_mgr: &mut EM, - _input: &::Input, + _input: &::Input, ) { // do nothing } @@ -265,7 +256,7 @@ where ) -> Result { let default_hooks = InChildProcessHooks::new::()?; let mut hooks = tuple_list!(default_hooks).merge(userhooks); - hooks.init_all::(state); + hooks.init_all(state); let itimerspec = parse_itimerspec(timeout); Ok(Self { shmem_provider, @@ -289,7 +280,7 @@ where ) -> Result { let default_hooks = InChildProcessHooks::new::()?; let mut hooks = tuple_list!(default_hooks).merge(userhooks); - hooks.init_all::(state); + hooks.init_all(state); let itimerval = parse_itimerval(timeout); @@ -303,10 +294,8 @@ where } } -impl HasObservers for GenericInProcessForkExecutorInner -where - OT: ObserversTuple, - S: State, +impl HasObservers + for GenericInProcessForkExecutorInner { type Observers = OT; diff --git a/libafl/src/executors/inprocess_fork/mod.rs b/libafl/src/executors/inprocess_fork/mod.rs index 485f6cdfdf..56f21d1d64 100644 --- a/libafl/src/executors/inprocess_fork/mod.rs +++ b/libafl/src/executors/inprocess_fork/mod.rs @@ -14,16 +14,13 @@ use nix::unistd::{fork, ForkResult}; use super::hooks::ExecutorHooksTuple; use crate::{ - events::{EventFirer, EventRestarter}, + corpus::Corpus, executors::{ hooks::inprocess_fork::InProcessForkExecutorGlobalData, inprocess_fork::inner::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers, }, - feedbacks::Feedback, - fuzzer::HasObjective, - inputs::UsesInput, observers::ObserversTuple, - state::{HasExecutions, HasSolutions, State, UsesState}, + state::{HasCorpus, HasExecutions}, Error, }; @@ -46,16 +43,10 @@ pub mod stateful; pub type InProcessForkExecutor<'a, H, OT, S, SP, EM, Z> = GenericInProcessForkExecutor<'a, H, (), OT, S, SP, EM, Z>; -impl<'a, H, OT, S, SP, EM, Z, OF> InProcessForkExecutor<'a, H, OT, S, SP, EM, Z> +impl<'a, H, OT, S, SP, EM, Z> InProcessForkExecutor<'a, H, OT, S, SP, EM, Z> where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - S: State, - OT: ObserversTuple, - SP: ShMemProvider, - EM: EventFirer + EventRestarter, - OF: Feedback, - S: HasSolutions, - Z: HasObjective, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, { /// The constructor for `InProcessForkExecutor` pub fn new( @@ -84,27 +75,16 @@ where /// /// On Linux, when fuzzing a Rust target, set `panic = "abort"` in your `Cargo.toml` (see [Cargo documentation](https://doc.rust-lang.org/cargo/reference/profiles.html#panic)). /// Else panics can not be caught by `LibAFL`. -pub struct GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z> -where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - OT: ObserversTuple, - S: UsesInput, - SP: ShMemProvider, - HT: ExecutorHooksTuple, - EM: UsesState, -{ +pub struct GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z> { harness_fn: &'a mut H, inner: GenericInProcessForkExecutorInner, } impl Debug for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z> where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - OT: ObserversTuple + Debug, - S: UsesInput, - SP: ShMemProvider, - HT: ExecutorHooksTuple + Debug, - EM: UsesState, + HT: Debug, + OT: Debug, + SP: Debug, { #[cfg(target_os = "linux")] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -123,36 +103,22 @@ where } } -impl UsesState +impl Executor::Input, S, Z> for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z> where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - OT: ObserversTuple, - S: State, + H: FnMut(&::Input) -> ExitKind + Sized, + S: HasCorpus + HasExecutions, SP: ShMemProvider, - HT: ExecutorHooksTuple, - EM: UsesState, -{ - type State = S; -} - -impl Executor - for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z> -where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - OT: ObserversTuple + Debug, - S: State + HasExecutions, - SP: ShMemProvider, - HT: ExecutorHooksTuple, - EM: EventFirer + EventRestarter, + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, { #[inline] fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { *state.executions_mut() += 1; @@ -176,16 +142,11 @@ where } } -impl<'a, H, HT, OT, S, SP, EM, Z, OF> GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z> +impl<'a, H, HT, OT, S, SP, EM, Z> GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z> where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - SP: ShMemProvider, - EM: EventFirer + EventRestarter, - OF: Feedback, - S: State + HasSolutions, - Z: HasObjective, + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, { /// Creates a new [`GenericInProcessForkExecutor`] with custom hooks #[expect(clippy::too_many_arguments)] @@ -229,13 +190,6 @@ where { impl HasObservers for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z> -where - H: FnMut(&S::Input) -> ExitKind + ?Sized, - HT: ExecutorHooksTuple, - S: State, - OT: ObserversTuple, - SP: ShMemProvider, - EM: UsesState, { type Observers = OT; #[inline] @@ -262,16 +216,14 @@ pub mod child_signal_handlers { hooks::inprocess_fork::{InProcessForkExecutorGlobalData, FORK_EXECUTOR_GLOBAL_DATA}, ExitKind, HasObservers, }, - inputs::UsesInput, observers::ObserversTuple, - state::UsesState, }; /// invokes the `post_exec_child` hook on all observer in case the child process panics - pub fn setup_child_panic_hook() + pub fn setup_child_panic_hook() where - E: HasObservers + UsesState, - E::Observers: ObserversTuple<::Input, E::State>, + E: HasObservers, + E::Observers: ObserversTuple, { let old_hook = panic::take_hook(); panic::set_hook(Box::new(move |panic_info| unsafe { @@ -280,9 +232,9 @@ pub mod child_signal_handlers { if !data.is_null() && (*data).is_valid() { let executor = (*data).executor_mut::(); let mut observers = executor.observers_mut(); - let state = (*data).state_mut::(); + let state = (*data).state_mut::(); // Invalidate data to not execute again the observer hooks in the crash handler - let input = (*data).take_current_input::<::Input>(); + let input = (*data).take_current_input::(); observers .post_exec_child_all(state, input, &ExitKind::Crash) .expect("Failed to run post_exec on observers"); @@ -300,20 +252,20 @@ pub mod child_signal_handlers { /// It will dereference the `data` pointer and assume it's valid. #[cfg(unix)] #[allow(clippy::needless_pass_by_value)] // nightly no longer requires this - pub(crate) unsafe fn child_crash_handler( + pub(crate) unsafe fn child_crash_handler( _signal: Signal, _info: &mut siginfo_t, _context: Option<&mut ucontext_t>, data: &mut InProcessForkExecutorGlobalData, ) where - E: HasObservers + UsesState, - E::Observers: ObserversTuple<::Input, E::State>, + E: HasObservers, + E::Observers: ObserversTuple, { if data.is_valid() { let executor = data.executor_mut::(); let mut observers = executor.observers_mut(); - let state = data.state_mut::(); - let input = data.take_current_input::<::Input>(); + let state = data.state_mut::(); + let input = data.take_current_input::(); observers .post_exec_child_all(state, input, &ExitKind::Crash) .expect("Failed to run post_exec on observers"); @@ -324,20 +276,20 @@ pub mod child_signal_handlers { #[cfg(unix)] #[allow(clippy::needless_pass_by_value)] // nightly no longer requires this - pub(crate) unsafe fn child_timeout_handler( + pub(crate) unsafe fn child_timeout_handler( #[cfg(unix)] _signal: Signal, _info: &mut siginfo_t, _context: Option<&mut ucontext_t>, data: &mut InProcessForkExecutorGlobalData, ) where - E: HasObservers + UsesState, - E::Observers: ObserversTuple<::Input, E::State>, + E: HasObservers, + E::Observers: ObserversTuple, { if data.is_valid() { let executor = data.executor_mut::(); let mut observers = executor.observers_mut(); - let state = data.state_mut::(); - let input = data.take_current_input::<::Input>(); + let state = data.state_mut::(); + let input = data.take_current_input::(); observers .post_exec_child_all(state, input, &ExitKind::Timeout) .expect("Failed to run post_exec on observers"); @@ -430,7 +382,7 @@ mod tests { let input = NopInput {}; let mut fuzzer = NopFuzzer::new(); let mut state = NopState::new(); - let mut mgr = SimpleEventManager::printing(); + let mut mgr: SimpleEventManager<_, NopState> = SimpleEventManager::printing(); in_process_fork_executor .run_target(&mut fuzzer, &mut state, &mut mgr, &input) .unwrap(); diff --git a/libafl/src/executors/inprocess_fork/stateful.rs b/libafl/src/executors/inprocess_fork/stateful.rs index 82757511f7..547f5497b5 100644 --- a/libafl/src/executors/inprocess_fork/stateful.rs +++ b/libafl/src/executors/inprocess_fork/stateful.rs @@ -15,16 +15,13 @@ use libafl_bolts::{ use nix::unistd::{fork, ForkResult}; use crate::{ - events::{EventFirer, EventRestarter}, + corpus::Corpus, executors::{ hooks::ExecutorHooksTuple, inprocess_fork::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers, }, - feedbacks::Feedback, - fuzzer::HasObjective, - inputs::UsesInput, observers::ObserversTuple, - state::{HasExecutions, State, UsesState}, + state::{HasCorpus, HasExecutions}, Error, }; @@ -34,9 +31,8 @@ pub type StatefulInProcessForkExecutor<'a, H, OT, S, SP, ES, EM, Z> = impl<'a, H, OT, S, SP, ES, EM, Z> StatefulInProcessForkExecutor<'a, H, OT, S, SP, ES, EM, Z> where - H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, - OT: ObserversTuple, - S: State, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, { #[expect(clippy::too_many_arguments)] /// The constructor for `InProcessForkExecutor` @@ -65,11 +61,7 @@ where } /// [`StatefulGenericInProcessForkExecutor`] is an executor that forks the current process before each execution. Harness can access some internal state. -pub struct StatefulGenericInProcessForkExecutor<'a, H, HT, OT, S, SP, ES, EM, Z> -where - H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, - S: UsesInput, -{ +pub struct StatefulGenericInProcessForkExecutor<'a, H, HT, OT, S, SP, ES, EM, Z> { /// The harness function, being executed for each fuzzing loop execution harness_fn: &'a mut H, /// The state used as argument of the harness @@ -82,10 +74,8 @@ where impl Debug for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z> where - H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HT: Debug, OT: Debug, - S: UsesInput, SP: Debug, { #[cfg(target_os = "linux")] @@ -105,34 +95,22 @@ where } } -impl UsesState +impl Executor::Input, S, Z> for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z> where - H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, - S: State, -{ - type State = S; -} - -impl Executor - for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z> -where - EM: EventFirer + EventRestarter, - H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, - HT: ExecutorHooksTuple, - OF: Feedback, - OT: ObserversTuple + Debug, - S: State + HasExecutions, + H: FnMut(&mut ES, &::Input) -> ExitKind + Sized, + HT: ExecutorHooksTuple<<::Corpus as Corpus>::Input, S>, + S: HasCorpus + HasExecutions, SP: ShMemProvider, - Z: HasObjective, + OT: ObserversTuple<<::Corpus as Corpus>::Input, S>, { #[inline] fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { *state.executions_mut() += 1; @@ -159,10 +137,9 @@ where impl<'a, H, HT, OT, S, SP, ES, EM, Z> StatefulGenericInProcessForkExecutor<'a, H, HT, OT, S, SP, ES, EM, Z> where - H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, - HT: ExecutorHooksTuple, - OT: ObserversTuple, - S: State, + HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple<::Input, S>, + S: HasCorpus, { /// Creates a new [`StatefulGenericInProcessForkExecutor`] with custom hooks #[expect(clippy::too_many_arguments)] @@ -208,10 +185,6 @@ where impl HasObservers for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z> -where - H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, - OT: ObserversTuple, - S: State, { type Observers = OT; diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index ed4f3c6634..4a77191b93 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -20,7 +20,7 @@ use serde::{Deserialize, Serialize}; pub use shadow::ShadowExecutor; pub use with_observers::WithObservers; -use crate::{state::UsesState, Error}; +use crate::Error; pub mod combined; #[cfg(all(feature = "std", unix))] @@ -117,17 +117,14 @@ pub trait HasObservers { } /// An executor takes the given inputs, and runs the harness/target. -pub trait Executor: UsesState -where - EM: UsesState, -{ +pub trait Executor { /// Instruct the target about the input and run fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &I, ) -> Result; } @@ -170,7 +167,7 @@ mod test { executors::{Executor, ExitKind}, fuzzer::NopFuzzer, inputs::{BytesInput, HasTargetBytes}, - state::{HasExecutions, NopState, State, UsesState}, + state::{HasExecutions, NopState}, }; /// A simple executor that does nothing. @@ -196,25 +193,17 @@ mod test { } } - impl UsesState for NopExecutor + impl Executor for NopExecutor where - S: State, - { - type State = S; - } - - impl Executor for NopExecutor - where - EM: UsesState, - S: State + HasExecutions, - S::Input: HasTargetBytes, + S: HasExecutions, + I: HasTargetBytes, { fn run_target( &mut self, _fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, _mgr: &mut EM, - input: &Self::Input, + input: &I, ) -> Result { *state.executions_mut() += 1; @@ -232,24 +221,14 @@ mod test { let nonempty_input = BytesInput::new(vec![1u8]); let mut executor = NopExecutor::new(); let mut fuzzer = NopFuzzer::new(); - - let mut state = NopState::new(); + let mut mgr: NopEventManager> = NopEventManager::new(); + let mut state: NopState = NopState::new(); executor - .run_target( - &mut fuzzer, - &mut state, - &mut NopEventManager::new(), - &empty_input, - ) + .run_target(&mut fuzzer, &mut state, &mut mgr, &empty_input) .unwrap_err(); executor - .run_target( - &mut fuzzer, - &mut state, - &mut NopEventManager::new(), - &nonempty_input, - ) + .run_target(&mut fuzzer, &mut state, &mut mgr, &nonempty_input) .unwrap(); } } diff --git a/libafl/src/executors/shadow.rs b/libafl/src/executors/shadow.rs index 717822f900..7fd1a4ea25 100644 --- a/libafl/src/executors/shadow.rs +++ b/libafl/src/executors/shadow.rs @@ -2,6 +2,7 @@ use core::{ fmt::{self, Debug, Formatter}, + marker::PhantomData, time::Duration, }; @@ -9,22 +10,23 @@ use libafl_bolts::tuples::RefIndexable; use super::HasTimeout; use crate::{ + corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, - inputs::UsesInput, observers::ObserversTuple, - state::UsesState, + state::HasCorpus, Error, }; /// A [`ShadowExecutor`] wraps an executor and a set of shadow observers -pub struct ShadowExecutor { +pub struct ShadowExecutor { /// The wrapped executor executor: E, /// The shadow observers shadow_observers: SOT, + phantom: PhantomData, } -impl Debug for ShadowExecutor +impl Debug for ShadowExecutor where E: Debug, SOT: Debug, @@ -37,16 +39,18 @@ where } } -impl ShadowExecutor +impl ShadowExecutor where - E: HasObservers + UsesState, - SOT: ObserversTuple<::Input, ::State>, + E: HasObservers, + S: HasCorpus, + SOT: ObserversTuple<::Input, S>, { /// Create a new `ShadowExecutor`, wrapping the given `executor`. pub fn new(executor: E, shadow_observers: SOT) -> Self { Self { executor, shadow_observers, + phantom: PhantomData, } } @@ -63,24 +67,25 @@ where } } -impl Executor for ShadowExecutor +impl Executor::Input, S, Z> + for ShadowExecutor where - E: Executor + HasObservers, - SOT: ObserversTuple, - EM: UsesState, + E: Executor::Input, S, Z> + HasObservers, + S: HasCorpus, + SOT: ObserversTuple<::Input, S>, { fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { self.executor.run_target(fuzzer, state, mgr, input) } } -impl HasTimeout for ShadowExecutor +impl HasTimeout for ShadowExecutor where E: HasTimeout, { @@ -94,17 +99,11 @@ where } } -impl UsesState for ShadowExecutor +impl HasObservers for ShadowExecutor where - E: UsesState, -{ - type State = E::State; -} - -impl HasObservers for ShadowExecutor -where - E: HasObservers + UsesState, - SOT: ObserversTuple<::Input, ::State>, + E: HasObservers, + S: HasCorpus, + SOT: ObserversTuple<::Input, S>, { type Observers = E::Observers; #[inline] diff --git a/libafl/src/executors/with_observers.rs b/libafl/src/executors/with_observers.rs index e94a761ea2..37baeadee8 100644 --- a/libafl/src/executors/with_observers.rs +++ b/libafl/src/executors/with_observers.rs @@ -1,51 +1,45 @@ //! A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`]. -use core::fmt::Debug; +use core::{fmt::Debug, marker::PhantomData}; use libafl_bolts::tuples::RefIndexable; use crate::{ + corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, - inputs::UsesInput, observers::ObserversTuple, - state::UsesState, + state::HasCorpus, Error, }; /// A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`]. #[derive(Debug)] -pub struct WithObservers { +pub struct WithObservers { executor: E, observers: OT, + phantom: PhantomData, } -impl Executor for WithObservers +impl Executor::Input, S, Z> for WithObservers where - E: Executor, - EM: UsesState, + S: HasCorpus, + E: Executor::Input, S, Z>, { fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { self.executor.run_target(fuzzer, state, mgr, input) } } -impl UsesState for WithObservers +impl HasObservers for WithObservers where - E: UsesState, -{ - type State = E::State; -} - -impl HasObservers for WithObservers -where - E: UsesState, - OT: ObserversTuple<::Input, ::State>, + S: HasCorpus, + OT: ObserversTuple<::Input, S>, { type Observers = OT; fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> { @@ -57,7 +51,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 @@ -66,6 +60,7 @@ impl WithObservers { Self { executor, observers, + phantom: PhantomData, } } } diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index 1b8e41daa6..f60086d229 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -513,7 +513,7 @@ impl EvaluatorObservers::I for StdFuzzer where CS: Scheduler<::Input, S>, - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Self>, E::Observers: MatchName + ObserversTuple<::Input, S> + Serialize, EM: EventFirer, F: Feedback::Input, E::Observers, S>, @@ -591,7 +591,7 @@ impl Evaluator::Input, S> for StdFuzzer where CS: Scheduler<::Input, S>, - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Self>, E::Observers: MatchName + ObserversTuple<::Input, S> + Serialize, EM: EventFirer, F: Feedback::Input, E::Observers, S>, @@ -748,7 +748,6 @@ where impl Fuzzer for StdFuzzer where CS: Scheduler, - E: UsesState, EM: ProgressReporter + EventProcessor, S: HasExecutions + HasMetadata @@ -923,7 +922,7 @@ impl ExecutesInput::Input, for StdFuzzer where CS: Scheduler<::Input, S>, - E: Executor + HasObservers, + E: Executor::Input, S, Self> + HasObservers, E::Observers: ObserversTuple<::Input, S>, EM: UsesState, S: UsesInput::Input> @@ -977,7 +976,6 @@ impl Default for NopFuzzer { impl Fuzzer for NopFuzzer where - E: UsesState, EM: ProgressReporter + EventProcessor, ST: StagesTuple, S: HasMetadata + HasExecutions + HasLastReportTime + HasCurrentStageId + UsesInput, diff --git a/libafl/src/mutators/numeric.rs b/libafl/src/mutators/numeric.rs index 47b1513a88..998b894231 100644 --- a/libafl/src/mutators/numeric.rs +++ b/libafl/src/mutators/numeric.rs @@ -26,9 +26,15 @@ pub type IntMutatorsType = tuple_list_type!( RandMutator, CrossoverMutator ); -type IntMutatorsCrossoverType = tuple_list_type!(CrossoverMutator); -type MappedIntMutatorsCrossoverType = tuple_list_type!(MappedCrossoverMutator); -type IntMutatorsNoCrossoverType = tuple_list_type!( + +/// Mutators for integer-like inputs that implement some form of crossover +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); + +/// Mutators for integer-like inputs without crossover mutations +pub type IntMutatorsNoCrossoverType = tuple_list_type!( BitFlipMutator, NegateMutator, IncMutator, diff --git a/libafl/src/stages/calibrate.rs b/libafl/src/stages/calibrate.rs index 50c07aeb09..dea94d6551 100644 --- a/libafl/src/stages/calibrate.rs +++ b/libafl/src/stages/calibrate.rs @@ -88,7 +88,7 @@ const CAL_STAGE_MAX: usize = 8; // AFL++'s CAL_CYCLES + 1 impl Stage for CalibrationStage where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, EM: EventFirer, O: MapObserver, C: AsRef, diff --git a/libafl/src/stages/colorization.rs b/libafl/src/stages/colorization.rs index 5b97301439..a47b96f827 100644 --- a/libafl/src/stages/colorization.rs +++ b/libafl/src/stages/colorization.rs @@ -22,7 +22,7 @@ use crate::{ nonzero, observers::{MapObserver, ObserversTuple}, stages::{RetryCountRestartHelper, Stage}, - state::{HasCorpus, HasCurrentTestcase, HasRand, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasRand}, Error, HasMetadata, HasNamedMetadata, }; @@ -68,10 +68,7 @@ pub struct ColorizationStage { phantom: PhantomData<(E, EM, O, E, S, Z)>, } -impl Named for ColorizationStage -where - E: UsesState, -{ +impl Named for ColorizationStage { fn name(&self) -> &Cow<'static, str> { &self.name } @@ -80,7 +77,7 @@ where impl Stage for ColorizationStage where EM: EventFirer, - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, S: HasCorpus + HasMetadata + HasRand @@ -162,7 +159,7 @@ where EM: EventFirer, O: MapObserver, C: AsRef + Named, - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, E::Observers: ObserversTuple<::Input, S>, S: HasCorpus + HasMetadata diff --git a/libafl/src/stages/concolic.rs b/libafl/src/stages/concolic.rs index be5765f3c6..904bc524be 100644 --- a/libafl/src/stages/concolic.rs +++ b/libafl/src/stages/concolic.rs @@ -50,7 +50,7 @@ impl Named for ConcolicTracingStage<'_, EM, TE, S, Z> { impl Stage for ConcolicTracingStage<'_, EM, TE, S, Z> where - TE: Executor + HasObservers, + TE: Executor::Input, S, Z> + HasObservers, TE::Observers: ObserversTuple<::Input, S>, S: HasExecutions + HasCorpus diff --git a/libafl/src/stages/generalization.rs b/libafl/src/stages/generalization.rs index 00e1fbacf3..496a1bb49e 100644 --- a/libafl/src/stages/generalization.rs +++ b/libafl/src/stages/generalization.rs @@ -64,7 +64,7 @@ impl Stage for GeneralizationStage + Named, - E: Executor + HasObservers, + E: Executor + HasObservers, E::Observers: ObserversTuple, S: HasExecutions + HasMetadata @@ -348,6 +348,7 @@ where + HasCorpus + MaybeHasClientPerfMonitor + UsesInput, + S::Corpus: Corpus, OT: ObserversTuple, EM: UsesState, { @@ -375,7 +376,7 @@ where input: &BytesInput, ) -> Result where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, E::Observers: ObserversTuple, { start_timer!(state); @@ -417,7 +418,7 @@ where split_char: u8, ) -> Result<(), Error> where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, { let mut start = 0; while start < payload.len() { @@ -455,7 +456,7 @@ where closing_char: u8, ) -> Result<(), Error> where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, { let mut index = 0; while index < payload.len() { diff --git a/libafl/src/stages/power.rs b/libafl/src/stages/power.rs index 695d2c6038..ba81b38b5e 100644 --- a/libafl/src/stages/power.rs +++ b/libafl/src/stages/power.rs @@ -79,7 +79,7 @@ where impl Stage for PowerMutationalStage where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, EM: UsesState, F: TestcaseScore, M: Mutator, @@ -121,7 +121,7 @@ where impl PowerMutationalStage where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, EM: UsesState, F: TestcaseScore, I: Input, diff --git a/libafl/src/stages/push/mod.rs b/libafl/src/stages/push/mod.rs index eba9d9797e..76a2389d94 100644 --- a/libafl/src/stages/push/mod.rs +++ b/libafl/src/stages/push/mod.rs @@ -256,7 +256,7 @@ where + HasNamedMetadata + HasMetadata + UsesInput::Input>, - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, OT: ObserversTuple<::Input, S>, PS: PushStage::Input, OT, S, Z>, diff --git a/libafl/src/stages/sync.rs b/libafl/src/stages/sync.rs index 5d8ecd6c5b..57aee77461 100644 --- a/libafl/src/stages/sync.rs +++ b/libafl/src/stages/sync.rs @@ -243,7 +243,7 @@ where + UsesInput::Input> + State, SP: ShMemProvider, - E: HasObservers + Executor, + E: HasObservers + Executor::Input, S, Z>, for<'a> E::Observers: Deserialize<'a>, Z: EvaluatorObservers::Input, S> + ExecutionProcessor::Input, E::Observers, S>, diff --git a/libafl/src/stages/tmin.rs b/libafl/src/stages/tmin.rs index 2e3a2d4490..01f2e3837a 100644 --- a/libafl/src/stages/tmin.rs +++ b/libafl/src/stages/tmin.rs @@ -34,7 +34,7 @@ use crate::{ start_timer, state::{ HasCorpus, HasCurrentTestcase, HasExecutions, HasMaxSize, HasSolutions, - MaybeHasClientPerfMonitor, State, UsesState, + MaybeHasClientPerfMonitor, State, }, Error, ExecutesInput, ExecutionProcessor, HasFeedback, HasMetadata, HasNamedMetadata, HasScheduler, @@ -63,7 +63,7 @@ where + ExecutesInput::Input, S> + HasFeedback, Z::Scheduler: RemovableScheduler<::Input, S>, - E: HasObservers + UsesState, + E: HasObservers, E::Observers: ObserversTuple<::Input, S> + Serialize, EM: EventFirer, FF: FeedbackFactory, @@ -134,7 +134,7 @@ where + ExecutesInput::Input, S> + HasFeedback, Z::Scheduler: RemovableScheduler<::Input, S>, - E: HasObservers + UsesState, + E: HasObservers, E::Observers: ObserversTuple<::Input, S> + Serialize, EM: EventFirer, FF: FeedbackFactory, diff --git a/libafl/src/stages/tracing.rs b/libafl/src/stages/tracing.rs index 3ca29cefbc..13dfdec1c0 100644 --- a/libafl/src/stages/tracing.rs +++ b/libafl/src/stages/tracing.rs @@ -32,7 +32,7 @@ pub struct TracingStage { impl TracingStage where - TE: Executor + HasObservers, + TE: Executor::Input, S, Z> + HasObservers, TE::Observers: ObserversTuple<::Input, S>, S: HasExecutions + HasCorpus @@ -76,7 +76,7 @@ where impl Stage for TracingStage where - TE: Executor + HasObservers, + TE: Executor::Input, S, Z> + HasObservers, TE::Observers: ObserversTuple<::Input, S>, S: HasExecutions + HasCorpus @@ -164,10 +164,10 @@ impl Named for ShadowTracingStage { } } -impl Stage, EM, S, Z> +impl Stage, EM, S, Z> for ShadowTracingStage where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, E::Observers: ObserversTuple<::Input, S>, SOT: ObserversTuple<::Input, S>, S: HasExecutions @@ -184,7 +184,7 @@ where fn perform( &mut self, fuzzer: &mut Z, - executor: &mut ShadowExecutor, + executor: &mut ShadowExecutor, state: &mut S, manager: &mut EM, ) -> Result<(), Error> { @@ -227,13 +227,13 @@ where impl ShadowTracingStage where - E: Executor + HasObservers, + E: Executor::Input, S, Z> + HasObservers, S: HasExecutions + HasCorpus + UsesInput, SOT: ObserversTuple<::Input, S>, EM: UsesState, { /// 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/verify_timeouts.rs b/libafl/src/stages/verify_timeouts.rs index 74e3e88c16..560f014340 100644 --- a/libafl/src/stages/verify_timeouts.rs +++ b/libafl/src/stages/verify_timeouts.rs @@ -84,7 +84,7 @@ impl TimeoutsToVerify { impl Stage for VerifyTimeoutsStage where E::Observers: ObserversTuple<::Input, S>, - E: Executor + HasObservers + HasTimeout, + E: Executor::Input, S, Z> + HasObservers + HasTimeout, EM: UsesState, Z: Evaluator::Input, S>, S: HasCorpus + HasMetadata + UsesInput::Input>, diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index 35ffedba68..0f2aba2ea9 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -723,7 +723,6 @@ where load_config: LoadConfig, ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, Z: Evaluator, { @@ -748,12 +747,17 @@ where config: &mut LoadConfig, ) -> Result where - E: UsesState, EM: EventFirer, Z: Evaluator, { - log::info!("Loading file {:?} ...", &path); - let input = (config.loader)(fuzzer, self, path)?; + log::info!("Loading file {path:?} ..."); + let input = match (config.loader)(fuzzer, self, path) { + Ok(input) => input, + Err(err) => { + log::error!("Skipping input that we could not load from {path:?}: {err:?}"); + return Ok(ExecuteInputResult::None); + } + }; if config.forced { let _: CorpusId = fuzzer.add_input(self, executor, manager, input)?; Ok(ExecuteInputResult::Corpus) @@ -777,7 +781,6 @@ where mut config: LoadConfig, ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, Z: Evaluator, { @@ -842,7 +845,6 @@ where file_list: &[PathBuf], ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, Z: Evaluator, { @@ -870,7 +872,6 @@ where in_dirs: &[PathBuf], ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, Z: Evaluator, { @@ -897,7 +898,6 @@ where file_list: &[PathBuf], ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, Z: Evaluator, { @@ -923,7 +923,6 @@ where in_dirs: &[PathBuf], ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, Z: Evaluator, { @@ -950,7 +949,6 @@ where in_dirs: &[PathBuf], ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, Z: Evaluator, { @@ -992,7 +990,6 @@ where cores: &Cores, ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, Z: Evaluator, { @@ -1087,7 +1084,6 @@ where forced: bool, ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, G: Generator<::Input, Self>, Z: Evaluator, @@ -1126,7 +1122,6 @@ where num: usize, ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, G: Generator<::Input, Self>, Z: Evaluator, @@ -1144,7 +1139,6 @@ where num: usize, ) -> Result<(), Error> where - E: UsesState, EM: EventFirer, G: Generator<::Input, Self>, Z: Evaluator, @@ -1274,6 +1268,18 @@ impl HasMaxSize for NopState { } } +impl HasCorpus for NopState { + type Corpus = InMemoryCorpus; + + fn corpus(&self) -> &Self::Corpus { + unimplemented!("Unimplemented for NopState!"); + } + + fn corpus_mut(&mut self) -> &mut Self::Corpus { + unimplemented!("Unimplemented for No[State!"); + } +} + impl UsesInput for NopState where I: Input, diff --git a/libafl_bolts/Cargo.toml b/libafl_bolts/Cargo.toml index 897c6f1394..4a5be81404 100644 --- a/libafl_bolts/Cargo.toml +++ b/libafl_bolts/Cargo.toml @@ -184,7 +184,7 @@ windows = { workspace = true, features = [ "Win32_System_SystemInformation", "Win32_System_Console", ] } -windows-result = "0.2.0" +windows-result = "0.3.0" [target.'cfg(windows)'.build-dependencies] windows = { workspace = true } diff --git a/libafl_bolts/src/llmp.rs b/libafl_bolts/src/llmp.rs index d191e02b6c..acf3ef28ac 100644 --- a/libafl_bolts/src/llmp.rs +++ b/libafl_bolts/src/llmp.rs @@ -3429,9 +3429,7 @@ where &broker_shmem_description, ); } - ListenerStream::Empty() => { - continue; - } + ListenerStream::Empty() => {} }; } }); diff --git a/libafl_bolts/src/os/unix_shmem_server.rs b/libafl_bolts/src/os/unix_shmem_server.rs index 831b729d37..2fef01ab84 100644 --- a/libafl_bolts/src/os/unix_shmem_server.rs +++ b/libafl_bolts/src/os/unix_shmem_server.rs @@ -702,7 +702,6 @@ where Ok(()) => (), Err(e) => { log::info!("Ignoring failed read from client {e:?} {poll_fd:?}"); - continue; } }; } else { diff --git a/libafl_bolts/src/os/windows_exceptions.rs b/libafl_bolts/src/os/windows_exceptions.rs index d1098c98e8..ca147f03d1 100644 --- a/libafl_bolts/src/os/windows_exceptions.rs +++ b/libafl_bolts/src/os/windows_exceptions.rs @@ -600,7 +600,7 @@ pub(crate) unsafe fn setup_ctrl_handler( compiler_fence(Ordering::SeqCst); // Log the result of SetConsoleCtrlHandler - let result = SetConsoleCtrlHandler(Some(ctrl_handler), true); + let result = SetConsoleCtrlHandler(Some(Some(ctrl_handler)), true); match result { Ok(()) => { log::info!("SetConsoleCtrlHandler succeeded"); diff --git a/libafl_bolts/src/shmem.rs b/libafl_bolts/src/shmem.rs index d3b0d8b7c6..55a587b0ab 100644 --- a/libafl_bolts/src/shmem.rs +++ b/libafl_bolts/src/shmem.rs @@ -1546,7 +1546,7 @@ pub mod win32_shmem { use windows::{ core::PCSTR, Win32::{ - Foundation::{CloseHandle, BOOL, HANDLE}, + Foundation::{CloseHandle, HANDLE}, System::Memory::{ CreateFileMappingA, MapViewOfFile, OpenFileMappingA, UnmapViewOfFile, FILE_MAP_ALL_ACCESS, MEMORY_MAPPED_VIEW_ADDRESS, PAGE_READWRITE, @@ -1621,7 +1621,7 @@ pub mod win32_shmem { // Unlike MapViewOfFile this one needs u32 let handle = OpenFileMappingA( FILE_MAP_ALL_ACCESS.0, - BOOL(0), + false, PCSTR(map_str_bytes.as_ptr().cast_mut()), )?; diff --git a/libafl_frida/src/executor.rs b/libafl_frida/src/executor.rs index 1f80d2bac0..1a74b3acb0 100644 --- a/libafl_frida/src/executor.rs +++ b/libafl_frida/src/executor.rs @@ -7,19 +7,20 @@ use frida_gum::{ stalker::{NoneEventSink, Stalker}, Gum, MemoryRange, NativePointer, }; -#[cfg(windows)] use libafl::{ corpus::Corpus, - executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks}, - state::{HasCorpus, HasSolutions}, -}; -use libafl::{ executors::{Executor, ExitKind, HasObservers, InProcessExecutor}, - inputs::{HasTargetBytes, NopTargetBytesConverter, TargetBytesConverter}, + inputs::{NopTargetBytesConverter, TargetBytesConverter, UsesInput}, observers::ObserversTuple, - state::{HasExecutions, State, UsesState}, + state::{HasCorpus, HasExecutions, UsesState}, Error, }; +#[cfg(windows)] +use libafl::{ + executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks}, + inputs::Input, + state::{HasCurrentTestcase, HasSolutions}, +}; use libafl_bolts::{tuples::RefIndexable, AsSlice}; #[cfg(not(test))] @@ -29,14 +30,7 @@ use crate::helper::{FridaInstrumentationHelper, FridaRuntimeTuple}; use crate::windows_hooks::initialize; /// The [`FridaInProcessExecutor`] is an [`Executor`] that executes the target in the same process, usinig [`frida`](https://frida.re/) for binary-only instrumentation. -pub struct FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> -where - H: FnMut(&S::Input) -> ExitKind, - TC: TargetBytesConverter, - S: State, - OT: ObserversTuple, - 'b: 'a, -{ +pub struct FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> { base: InProcessExecutor<'a, H, OT, S>, /// `thread_id` for the Stalker thread_id: Option, @@ -51,10 +45,7 @@ where impl Debug for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> where - H: FnMut(&S::Input) -> ExitKind, - S: State, - TC: TargetBytesConverter, - OT: ObserversTuple + Debug, + OT: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("FridaInProcessExecutor") @@ -65,14 +56,14 @@ where } } -impl Executor +impl Executor::Input, S, Z> for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> where EM: UsesState, - H: FnMut(&S::Input) -> ExitKind, - S: State + HasExecutions, - TC: TargetBytesConverter, - OT: ObserversTuple, + H: FnMut(&::Input) -> ExitKind, + S: HasCorpus + HasExecutions + UsesInput::Input>, + TC: TargetBytesConverter::Input>, + OT: ObserversTuple<::Input, S>, RT: FridaRuntimeTuple, { /// Instruct the target about the input and run @@ -80,9 +71,9 @@ where fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { let target_bytes = self.target_bytes_converter.to_target_bytes(input); self.helper.pre_exec(target_bytes.as_slice())?; @@ -122,23 +113,7 @@ where } } -impl UsesState for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> -where - H: FnMut(&S::Input) -> ExitKind, - OT: ObserversTuple, - S: State, - TC: TargetBytesConverter, -{ - type State = S; -} - -impl HasObservers for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> -where - H: FnMut(&S::Input) -> ExitKind, - TC: TargetBytesConverter, - S: State, - OT: ObserversTuple, -{ +impl HasObservers for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> { type Observers = OT; #[inline] fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> { @@ -152,12 +127,18 @@ where } impl<'a, 'b, 'c, H, OT, RT, S> - FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, NopTargetBytesConverter> + FridaInProcessExecutor< + 'a, + 'b, + 'c, + H, + OT, + RT, + S, + NopTargetBytesConverter<::Input>, + > where - H: FnMut(&S::Input) -> ExitKind, - S: State, - S::Input: HasTargetBytes, - OT: ObserversTuple, + S: HasCorpus, RT: FridaRuntimeTuple, { /// Creates a new [`FridaInProcessExecutor`]. @@ -194,10 +175,6 @@ where impl<'a, 'b, 'c, H, OT, RT, S, TC> FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> where - H: FnMut(&S::Input) -> ExitKind, - S: State, - TC: TargetBytesConverter, - OT: ObserversTuple, RT: FridaRuntimeTuple, { /// Creates a new [`FridaInProcessExecutor`]. @@ -257,13 +234,17 @@ where impl<'a, 'b, 'c, H, OT, RT, S, TC> HasInProcessHooks for FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> where - H: FnMut(&S::Input) -> ExitKind, - S: State + HasSolutions + HasCorpus + HasExecutions, - TC: TargetBytesConverter, - OT: ObserversTuple, + H: FnMut(&::Input) -> ExitKind, + S: HasSolutions + + HasCorpus + + HasCurrentTestcase + + HasExecutions + + UsesInput::Input>, + S::Solutions: Corpus::Input>, + ::Input: Input, + TC: TargetBytesConverter::Input>, + OT: ObserversTuple<::Input, S>, RT: FridaRuntimeTuple, - ::Solutions: Corpus, //delete me - <::Corpus as Corpus>::Input: Clone, //delete me { /// the timeout handler #[inline] diff --git a/libafl_libfuzzer/runtime/src/fuzz.rs b/libafl_libfuzzer/runtime/src/fuzz.rs index 17827c9c14..fddcf0bb59 100644 --- a/libafl_libfuzzer/runtime/src/fuzz.rs +++ b/libafl_libfuzzer/runtime/src/fuzz.rs @@ -70,7 +70,6 @@ where + HasLastReportTime + HasCurrentStageId + Stoppable, - E: UsesState, EM: ProgressReporter + EventProcessor, ST: StagesTuple, { diff --git a/libafl_libfuzzer/runtime/src/observers.rs b/libafl_libfuzzer/runtime/src/observers.rs index a4d90c7ec3..c92a8ecf16 100644 --- a/libafl_libfuzzer/runtime/src/observers.rs +++ b/libafl_libfuzzer/runtime/src/observers.rs @@ -158,13 +158,6 @@ where } } -impl UsesState for MappedEdgeMapObserver -where - M: UsesState, -{ - type State = M::State; -} - impl Observer for MappedEdgeMapObserver where M: Observer + Debug, diff --git a/libafl_libfuzzer/runtime/src/report.rs b/libafl_libfuzzer/runtime/src/report.rs index e196fcd267..642ad0cb09 100644 --- a/libafl_libfuzzer/runtime/src/report.rs +++ b/libafl_libfuzzer/runtime/src/report.rs @@ -31,7 +31,7 @@ where + HasLastReportTime + HasCurrentStageId + Stoppable, - E: HasObservers + UsesState, + E: HasObservers, EM: ProgressReporter + EventProcessor, ST: StagesTuple, { diff --git a/libafl_nyx/src/executor.rs b/libafl_nyx/src/executor.rs index c83e35ade2..8fcc555137 100644 --- a/libafl_nyx/src/executor.rs +++ b/libafl_nyx/src/executor.rs @@ -5,10 +5,11 @@ use std::{ }; use libafl::{ + corpus::Corpus, executors::{Executor, ExitKind, HasObservers, HasTimeout}, - inputs::HasTargetBytes, + inputs::{HasTargetBytes, UsesInput}, observers::{ObserversTuple, StdOutObserver}, - state::{HasExecutions, State, UsesState}, + state::{HasCorpus, HasExecutions, UsesState}, Error, }; use libafl_bolts::{tuples::RefIndexable, AsSlice}; @@ -38,26 +39,19 @@ impl NyxExecutor<(), ()> { } } -impl UsesState for NyxExecutor -where - S: State, -{ - type State = S; -} - -impl Executor for NyxExecutor +impl Executor::Input, S, Z> for NyxExecutor where EM: UsesState, - S: State + HasExecutions, - S::Input: HasTargetBytes, - OT: ObserversTuple, + S: HasCorpus + HasExecutions + UsesInput::Input>, + ::Input: HasTargetBytes, + OT: ObserversTuple<::Input, S>, { fn run_target( &mut self, _fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, _mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { *state.executions_mut() += 1; @@ -205,11 +199,7 @@ impl NyxExecutorBuilder { } } -impl HasObservers for NyxExecutor -where - S: State, - OT: ObserversTuple, -{ +impl HasObservers for NyxExecutor { type Observers = OT; fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> { diff --git a/libafl_qemu/libafl_qemu_build/src/lib.rs b/libafl_qemu/libafl_qemu_build/src/lib.rs index b51076c9b1..a86ea5249f 100644 --- a/libafl_qemu/libafl_qemu_build/src/lib.rs +++ b/libafl_qemu/libafl_qemu_build/src/lib.rs @@ -144,7 +144,7 @@ fn exec_rustc(args: &[&str]) -> String { fn find_rustc_llvm_version() -> Option { let output = exec_rustc(&["--verbose", "--version"]); - let ver = output.split(':').last().unwrap().trim(); + let ver = output.split(':').next_back().unwrap().trim(); if let Some(major) = ver.split('.').collect::>().first() { if let Ok(res) = major.parse::() { return Some(res); diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index 349644ff4f..fcbb0e1e0a 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -9,8 +9,6 @@ use std::ptr; #[cfg(feature = "systemmode")] use std::sync::atomic::{AtomicBool, Ordering}; -#[cfg(any(feature = "usermode", feature = "fork"))] -use libafl::inputs::UsesInput; use libafl::{ corpus::Corpus, events::{EventFirer, EventRestarter}, @@ -22,8 +20,9 @@ use libafl::{ }, feedbacks::Feedback, fuzzer::HasObjective, + inputs::{Input, UsesInput}, observers::ObserversTuple, - state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions, State, UsesState}, Error, ExecutionProcessor, HasScheduler, }; #[cfg(feature = "fork")] @@ -94,16 +93,20 @@ pub unsafe fn inproc_qemu_timeout_handler( context: Option<&mut ucontext_t>, data: &mut InProcessExecutorHandlerData, ) where - E: HasObservers + HasInProcessHooks + Executor, - E::Observers: ObserversTuple, - E::State: HasExecutions + HasSolutions + HasCorpus, - EM: EventFirer + EventRestarter, + E: HasObservers + HasInProcessHooks + Executor::Input, S, Z>, + E::Observers: ObserversTuple<::Input, S>, + S: HasExecutions + + HasSolutions + + HasCorpus + + Unpin + + HasCurrentTestcase + + UsesInput::Input>, + ::Input: Input, + S::Solutions: Corpus::Input>, + EM: EventFirer + EventRestarter, ET: EmulatorModuleTuple, - OF: Feedback, - S: State + Unpin, + OF: Feedback::Input, E::Observers, S>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me { #[cfg(feature = "systemmode")] { @@ -114,6 +117,7 @@ pub unsafe fn inproc_qemu_timeout_handler( E, EM, OF, + S, Z, >(signal, info, context, data); } @@ -126,9 +130,13 @@ pub unsafe fn inproc_qemu_timeout_handler( emulator_modules.modules_mut().on_timeout_all(); } - libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::( - signal, info, context, data, - ); + libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::< + E, + EM, + OF, + S, + Z, + >(signal, info, context, data); } } @@ -151,9 +159,16 @@ impl<'a, CM, ED, ET, H, OT, S, SM> QemuExecutor<'a, CM, ED, ET, H, OT, S, SM> where CM: CommandManager, ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &mut S, &S::Input) -> ExitKind, - OT: ObserversTuple, - S: State, + H: FnMut(&mut Emulator, &mut S, &::Input) -> ExitKind, + OT: ObserversTuple<::Input, S>, + S: HasCorpus + + Unpin + + HasExecutions + + HasSolutions + + UsesInput::Input> + + State, + S::Solutions: Corpus::Input>, + ::Input: Input, { pub fn new( emulator: Emulator, @@ -168,13 +183,9 @@ where ED: EmulatorDriver, EM: EventFirer + EventRestarter, OF: Feedback, - S: Unpin + State + HasExecutions + HasCorpus + HasSolutions, - S::Corpus: Corpus, Z: HasObjective + HasScheduler<::Input, S> + ExecutionProcessor::Input, OT, S>, - S::Solutions: Corpus, //delete me - ::Input: Clone, //delete me { let mut inner = StatefulInProcessExecutor::with_timeout( harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout, @@ -188,7 +199,8 @@ where let handler = |qemu: Qemu, _emulator_modules: &mut EmulatorModules, host_sig| { eprintln!("Crashed with signal {host_sig}"); unsafe { - libafl::executors::inprocess::generic_inproc_crash_handler::(); + libafl::executors::inprocess::generic_inproc_crash_handler::( + ); } if let Some(cpu) = qemu.current_cpu() { eprint!("Context:\n{}", cpu.display_context()); @@ -236,22 +248,23 @@ where } } -impl Executor for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM> +impl Executor::Input, S, Z> + for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM> where CM: CommandManager, ED: EmulatorDriver, EM: UsesState, ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &mut S, &S::Input) -> ExitKind, - OT: ObserversTuple, - S: State + HasExecutions + Unpin, + H: FnMut(&mut Emulator, &mut S, &::Input) -> ExitKind, + OT: ObserversTuple<::Input, S>, + S: State + HasExecutions + Unpin + HasCorpus + UsesInput::Input>, { fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { if self.first_exec { self.inner.exposed_executor_state_mut().first_exec(state); @@ -275,24 +288,13 @@ where } } -impl UsesState for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM> -where - CM: CommandManager, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &mut S, &S::Input) -> ExitKind, - OT: ObserversTuple, - S: State, -{ - type State = S; -} - impl HasObservers for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM> where CM: CommandManager, ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &mut S, &S::Input) -> ExitKind, - OT: ObserversTuple, - S: State, + H: FnMut(&mut Emulator, &mut S, &::Input) -> ExitKind, + OT: ObserversTuple<::Input, S>, + S: State + HasCorpus + UsesInput::Input>, { type Observers = OT; #[inline] @@ -314,7 +316,7 @@ pub struct QemuForkExecutor<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z> where CM: CommandManager, ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + ?Sized, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind + Sized, OT: ObserversTuple, S: UsesInput, SP: ShMemProvider, @@ -330,7 +332,7 @@ where EM: UsesState, ED: Debug, ET: EmulatorModuleTuple + Debug, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + ?Sized, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind + Sized, OT: ObserversTuple + Debug, S: UsesInput + Debug, SM: Debug, @@ -351,12 +353,12 @@ where CM: CommandManager, EM: EventFirer + EventRestarter, ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + ?Sized, - OT: ObserversTuple, - S: State + HasSolutions, + H: FnMut(&mut Emulator, &::Input) -> ExitKind + Sized, + OT: ObserversTuple<::Input, S>, + S: State + HasSolutions + HasCorpus + UsesInput::Input>, SP: ShMemProvider, Z: HasObjective, - Z::Objective: Feedback, + Z::Objective: Feedback::Input, OT, S>, { #[expect(clippy::too_many_arguments)] pub fn new( @@ -405,7 +407,7 @@ where } #[cfg(feature = "fork")] -impl Executor +impl Executor::Input, S, Z> for QemuForkExecutor<'_, CM, ED, EM, ET, H, OT, S, SM, SP, Z> where CM: CommandManager, @@ -415,16 +417,16 @@ where H: FnMut(&mut Emulator, &S::Input) -> ExitKind, OF: Feedback, OT: ObserversTuple + Debug, - S: State + HasExecutions + Unpin, + S: State + HasExecutions + Unpin + HasCorpus + UsesInput::Input>, SP: ShMemProvider, Z: HasObjective, { fn run_target( &mut self, fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { self.inner.exposed_executor_state.first_exec(state); @@ -449,7 +451,7 @@ impl UsesState where CM: CommandManager, ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + ?Sized, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind + Sized, OT: ObserversTuple, S: State, SP: ShMemProvider, @@ -464,7 +466,7 @@ where CM: CommandManager, EM: UsesState, ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + ?Sized, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind + Sized, OT: ObserversTuple, S: State, SP: ShMemProvider, diff --git a/libafl_qemu/src/modules/usermode/snapshot.rs b/libafl_qemu/src/modules/usermode/snapshot.rs index 0e9c7e447f..00c1fdfe3c 100644 --- a/libafl_qemu/src/modules/usermode/snapshot.rs +++ b/libafl_qemu/src/modules/usermode/snapshot.rs @@ -393,6 +393,20 @@ impl SnapshotModule { log::debug!("Start restore"); + let new_brk = qemu.get_brk(); + if new_brk < self.brk { + // The heap has shrunk below the snapshotted brk value. We need to remap those pages in the target. + // The next for loop will restore their content if needed. + let aligned_new_brk = (new_brk + ((SNAPSHOT_PAGE_SIZE - 1) as GuestAddr)) + & (!(SNAPSHOT_PAGE_SIZE - 1) as GuestAddr); + log::debug!("New brk ({:#x?}) < snapshotted brk ({:#x?})! Mapping back in the target {:#x?} - {:#x?}", new_brk, self.brk, aligned_new_brk, aligned_new_brk + (self.brk - aligned_new_brk)); + drop(qemu.map_fixed( + aligned_new_brk, + (self.brk - aligned_new_brk) as usize, + MmapPerms::ReadWrite, + )); + } + for acc in &mut self.accesses { unsafe { &mut (*acc.get()) }.dirty.retain(|page| { if let Some(info) = self.pages.get_mut(page) { @@ -524,7 +538,12 @@ impl SnapshotModule { } } - pub fn change_mapped(&mut self, start: GuestAddr, mut size: usize, perms: Option) { + pub fn change_mapped_perms( + &mut self, + start: GuestAddr, + mut size: usize, + perms: Option, + ) { if size % SNAPSHOT_PAGE_SIZE != 0 { size = size + (SNAPSHOT_PAGE_SIZE - size % SNAPSHOT_PAGE_SIZE); } @@ -851,18 +870,8 @@ where h.access(a0, a1 as usize); } SYS_brk => { - let h = emulator_modules.get_mut::().unwrap(); - if h.brk != result && result != 0 && result > h.initial_brk { - /* brk has changed, and it doesn't shrink below initial_brk. We change mapping from the snapshotted initial brk address to the new target_brk - * If no brk mapping has been made until now, change_mapped won't change anything and just create a new mapping. - * It is safe to assume RW perms here - */ - h.change_mapped( - h.initial_brk, - (result - h.initial_brk) as usize, - Some(MmapPerms::ReadWrite), - ); - } + // We don't handle brk here. It is handled in the reset function only when it's needed. + log::debug!("New brk ({:#x?}) received.", result); } // mmap syscalls sys_const => { @@ -898,7 +907,7 @@ where } else if sys_const == SYS_mprotect { if let Ok(prot) = MmapPerms::try_from(a2 as i32) { let h = emulator_modules.get_mut::().unwrap(); - h.change_mapped(a0, a1 as usize, Some(prot)); + h.change_mapped_perms(a0, a1 as usize, Some(prot)); } } else if sys_const == SYS_munmap { let h = emulator_modules.get_mut::().unwrap(); diff --git a/libafl_targets/src/call.rs b/libafl_targets/src/call.rs index c3fcc38892..8b4253af07 100644 --- a/libafl_targets/src/call.rs +++ b/libafl_targets/src/call.rs @@ -1,10 +1,7 @@ use core::marker::PhantomData; use hashbrown::HashMap; -use libafl::{ - executors::{hooks::ExecutorHook, HasObservers}, - inputs::UsesInput, -}; +use libafl::executors::hooks::ExecutorHook; use once_cell::sync::Lazy; /// The list of functions that this execution has observed pub static mut FUNCTION_LIST: Lazy> = Lazy::new(HashMap::new); @@ -22,11 +19,11 @@ pub unsafe extern "C" fn __libafl_target_call_hook(id: usize) { /// The empty struct to clear the `FUNCTION_LIST` before the execution #[derive(Debug, Clone, Copy, Default)] -pub struct CallHook { - phantom: PhantomData, +pub struct CallHook { + phantom: PhantomData<(I, S)>, } -impl CallHook { +impl CallHook { /// The constructor #[must_use] pub fn new() -> Self { @@ -36,13 +33,10 @@ impl CallHook { } } -impl ExecutorHook for CallHook -where - S: UsesInput, -{ - fn init(&mut self, _state: &mut S) {} +impl ExecutorHook for CallHook { + 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) { // clear it before the execution // # Safety // This typically happens while no other execution happens. @@ -54,5 +48,5 @@ where } } - fn post_exec(&mut self, _state: &mut S, _input: &::Input) {} + fn post_exec(&mut self, _state: &mut S, _input: &I) {} } diff --git a/libafl_targets/src/cmps/stages/aflpptracing.rs b/libafl_targets/src/cmps/stages/aflpptracing.rs index 7d20d04e3f..308978c0f4 100644 --- a/libafl_targets/src/cmps/stages/aflpptracing.rs +++ b/libafl_targets/src/cmps/stages/aflpptracing.rs @@ -37,7 +37,7 @@ impl Named for AFLppCmplogTracingStage<'_, EM, TE, S, Z> { impl Stage for AFLppCmplogTracingStage<'_, EM, TE, S, Z> where EM: UsesState, - TE: HasObservers + Executor, + TE: HasObservers + Executor, TE::Observers: MatchNameRef + ObserversTuple, S: HasCorpus + HasCurrentTestcase diff --git a/libafl_targets/src/sancov_pcguard.rs b/libafl_targets/src/sancov_pcguard.rs index cb7aa2a142..a65e73cb55 100644 --- a/libafl_targets/src/sancov_pcguard.rs +++ b/libafl_targets/src/sancov_pcguard.rs @@ -10,7 +10,7 @@ use core::{mem::align_of, slice}; feature = "sancov_ctx", feature = "sancov_ngram8" ))] -use libafl::executors::{hooks::ExecutorHook, HasObservers}; +use libafl::executors::hooks::ExecutorHook; #[cfg(any( feature = "pointer_maps", @@ -80,25 +80,19 @@ use core::marker::PhantomData; #[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] #[rustversion::nightly] #[derive(Debug, Clone, Copy)] -pub struct NgramHook -where - S: libafl::inputs::UsesInput, -{ - phantom: PhantomData, +pub struct NgramHook { + phantom: PhantomData<(I, S)>, } /// The hook to initialize ctx everytime we run the harness #[cfg(feature = "sancov_ctx")] #[derive(Debug, Clone, Copy)] -pub struct CtxHook { - phantom: PhantomData, +pub struct CtxHook { + phantom: PhantomData<(I, S)>, } #[cfg(feature = "sancov_ctx")] -impl CtxHook -where - S: libafl::inputs::UsesInput, -{ +impl CtxHook { /// The constructor for this struct #[must_use] pub fn new() -> Self { @@ -109,10 +103,7 @@ where } #[cfg(feature = "sancov_ctx")] -impl Default for CtxHook -where - S: libafl::inputs::UsesInput, -{ +impl Default for CtxHook { fn default() -> Self { Self::new() } @@ -120,12 +111,9 @@ where #[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] #[rustversion::nightly] -impl ExecutorHook for NgramHook -where - S: libafl::inputs::UsesInput, -{ - fn init(&mut self, _state: &mut S) {} - fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) { +impl ExecutorHook for NgramHook { + fn init(&mut self, _state: &mut S) {} + fn pre_exec(&mut self, _state: &mut S, _input: &I) { #[cfg(feature = "sancov_ngram4")] unsafe { PREV_ARRAY_4 = Ngram4::from_array([0, 0, 0, 0]); @@ -136,15 +124,12 @@ where PREV_ARRAY_8 = Ngram8::from_array([0, 0, 0, 0, 0, 0, 0, 0]); } } - fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {} + fn post_exec(&mut self, _state: &mut S, _input: &I) {} } #[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] #[rustversion::nightly] -impl NgramHook -where - S: libafl::inputs::UsesInput, -{ +impl NgramHook { /// The constructor for this struct #[must_use] pub fn new() -> Self { @@ -156,27 +141,21 @@ where #[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] #[rustversion::nightly] -impl Default for NgramHook -where - S: libafl::inputs::UsesInput, -{ +impl Default for NgramHook { fn default() -> Self { Self::new() } } #[cfg(feature = "sancov_ctx")] -impl ExecutorHook for CtxHook -where - S: libafl::inputs::UsesInput, -{ - fn init(&mut self, _state: &mut S) {} - fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) { +impl ExecutorHook for CtxHook { + fn init(&mut self, _state: &mut S) {} + fn pre_exec(&mut self, _state: &mut S, _input: &I) { unsafe { __afl_prev_ctx = 0; } } - fn post_exec(&mut self, _state: &mut S, _input: &S::Input) {} + fn post_exec(&mut self, _state: &mut S, _input: &I) {} } #[rustversion::nightly] diff --git a/libafl_targets/src/windows_asan.rs b/libafl_targets/src/windows_asan.rs index 1f23c63132..4f97431444 100644 --- a/libafl_targets/src/windows_asan.rs +++ b/libafl_targets/src/windows_asan.rs @@ -5,9 +5,9 @@ use libafl::{ events::{EventFirer, EventRestarter}, executors::{hooks::windows::windows_asan_handler::asan_death_handler, Executor, HasObservers}, feedbacks::Feedback, - inputs::UsesInput, + inputs::{Input, UsesInput}, observers::ObserversTuple, - state::{HasCorpus, HasExecutions, HasSolutions, UsesState}, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, HasObjective, }; @@ -30,16 +30,20 @@ extern "C" { /// /// # Safety /// Calls the unsafe `__sanitizer_set_death_callback` symbol, but should be safe to call otherwise. -pub unsafe fn setup_asan_callback(_executor: &E, _event_mgr: &EM, _fuzzer: &Z) +pub unsafe fn setup_asan_callback(_executor: &E, _event_mgr: &EM, _fuzzer: &Z) where - E: Executor + HasObservers, - EM: EventFirer + EventRestarter, - OF: Feedback, - E::State: HasSolutions + HasCorpus + HasExecutions, - E::Observers: ObserversTuple<::Input, E::State>, + E: Executor::Input, S, Z> + HasObservers, + E::Observers: ObserversTuple<::Input, S>, + EM: EventFirer + EventRestarter, + OF: Feedback::Input, E::Observers, S>, + S: HasExecutions + + HasSolutions + + HasCurrentTestcase + + HasCorpus + + UsesInput::Input>, + S::Solutions: Corpus::Input>, Z: HasObjective, - <::State as HasSolutions>::Solutions: Corpus, //delete me - <<::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me + ::Input: Input + Clone, { - __sanitizer_set_death_callback(Some(asan_death_handler::)); + __sanitizer_set_death_callback(Some(asan_death_handler::)); } diff --git a/libafl_tinyinst/src/executor.rs b/libafl_tinyinst/src/executor.rs index f699ab337d..7a6c8cd693 100644 --- a/libafl_tinyinst/src/executor.rs +++ b/libafl_tinyinst/src/executor.rs @@ -1,10 +1,10 @@ use core::{marker::PhantomData, ptr, time::Duration}; use libafl::{ + corpus::Corpus, executors::{Executor, ExitKind, HasObservers}, - inputs::HasTargetBytes, - observers::ObserversTuple, - state::{HasExecutions, State, UsesState}, + inputs::{HasTargetBytes, UsesInput}, + state::{HasCorpus, HasExecutions, UsesState}, Error, }; use libafl_bolts::{ @@ -48,20 +48,21 @@ where } } -impl Executor for TinyInstExecutor +impl Executor::Input, S, Z> + for TinyInstExecutor where EM: UsesState, - S: State + HasExecutions, - S::Input: HasTargetBytes, + S: HasCorpus + HasExecutions + UsesInput::Input>, + ::Input: HasTargetBytes, SP: ShMemProvider, { #[inline] fn run_target( &mut self, _fuzzer: &mut Z, - state: &mut Self::State, + state: &mut S, _mgr: &mut EM, - input: &Self::Input, + input: &::Input, ) -> Result { *state.executions_mut() += 1; match &self.map { @@ -317,9 +318,7 @@ where impl HasObservers for TinyInstExecutor where - S: State, SP: ShMemProvider, - OT: ObserversTuple, { type Observers = OT; @@ -331,10 +330,3 @@ where RefIndexable::from(&mut self.observers) } } -impl UsesState for TinyInstExecutor -where - S: State, - SP: ShMemProvider, -{ - type State = S; -}