diff --git a/fuzzers/push_stage_harness/src/main.rs b/fuzzers/push_stage_harness/src/main.rs index 30da620adb..840fd01978 100644 --- a/fuzzers/push_stage_harness/src/main.rs +++ b/fuzzers/push_stage_harness/src/main.rs @@ -20,7 +20,7 @@ use libafl::{ monitors::SimpleMonitor, mutators::scheduled::{havoc_mutations, StdScheduledMutator}, observers::StdMapObserver, - stages::push::StdMutationalPushStage, + stages::push::{PushStageSharedState, StdMutationalPushStage}, state::{HasCorpus, StdState}, }; @@ -95,13 +95,12 @@ pub fn main() { let observers = tuple_list!(observer); + let shared_state = PushStageSharedState::new(fuzzer, state, observers, mgr); + // All fuzzer elements are hidden behind Rc>, so we can reuse them for multiple stages. let push_stage = StdMutationalPushStage::new( mutator, - Rc::new(RefCell::new(fuzzer)), - Rc::new(RefCell::new(state)), - Rc::new(RefCell::new(mgr)), - Rc::new(RefCell::new(observers)), + Rc::new(RefCell::new(Some(shared_state))), exit_kind.clone(), stage_idx, ); diff --git a/fuzzers/tutorial/src/metadata.rs b/fuzzers/tutorial/src/metadata.rs index d53b9d4608..a31de01645 100644 --- a/fuzzers/tutorial/src/metadata.rs +++ b/fuzzers/tutorial/src/metadata.rs @@ -50,7 +50,7 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { self.len = input.length; diff --git a/libafl/src/bolts/minibsod.rs b/libafl/src/bolts/minibsod.rs index 04b655de53..51a70e18a1 100644 --- a/libafl/src/bolts/minibsod.rs +++ b/libafl/src/bolts/minibsod.rs @@ -10,6 +10,7 @@ use crate::bolts::os::unix_signals::{ucontext_t, Signal}; /// Write the contens of all important registers #[cfg(all(target_os = "linux", target_arch = "x86_64"))] +#[allow(clippy::similar_names)] pub fn dump_registers( writer: &mut BufWriter, ucontext: &ucontext_t, diff --git a/libafl/src/events/llmp.rs b/libafl/src/events/llmp.rs index c3ff6e5e98..ecc6b47704 100644 --- a/libafl/src/events/llmp.rs +++ b/libafl/src/events/llmp.rs @@ -51,6 +51,8 @@ use crate::bolts::os::{fork, ForkResult}; #[cfg(feature = "std")] use typed_builder::TypedBuilder; +use super::ProgressReporter; + /// Forward this to the client const _LLMP_TAG_EVENT_TO_CLIENT: llmp::Tag = 0x2C11E471; /// Only handle this in the broker @@ -400,7 +402,7 @@ where } } -impl EventFirer for LlmpEventManager +impl EventFirer for LlmpEventManager where I: Input, OT: ObserversTuple, @@ -408,7 +410,7 @@ where //CE: CustomEvent, { #[cfg(feature = "llmp_compression")] - fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S2, event: Event) -> Result<(), Error> { let serialized = postcard::to_allocvec(&event)?; let flags: Flags = LLMP_FLAG_INITIALIZED; @@ -428,7 +430,7 @@ where } #[cfg(not(feature = "llmp_compression"))] - fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S2, event: Event) -> Result<(), Error> { let serialized = postcard::to_allocvec(&event)?; self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?; Ok(()) @@ -507,6 +509,14 @@ where { } +impl ProgressReporter for LlmpEventManager +where + I: Input, + OT: ObserversTuple + serde::de::DeserializeOwned, + SP: ShMemProvider, +{ +} + impl HasEventManagerId for LlmpEventManager where I: Input, @@ -538,15 +548,24 @@ where } #[cfg(feature = "std")] -impl EventFirer for LlmpRestartingEventManager +impl ProgressReporter for LlmpRestartingEventManager where I: Input, OT: ObserversTuple, S: Serialize, SP: ShMemProvider, +{ +} + +#[cfg(feature = "std")] +impl EventFirer for LlmpRestartingEventManager +where + I: Input, + OT: ObserversTuple, + SP: ShMemProvider, //CE: CustomEvent, { - fn fire(&mut self, state: &mut S, event: Event) -> Result<(), Error> { + fn fire(&mut self, state: &mut S2, event: Event) -> Result<(), Error> { // Check if we are going to crash in the event, in which case we store our current state for the next runner self.llmp_mgr.fire(state, event) } diff --git a/libafl/src/events/mod.rs b/libafl/src/events/mod.rs index b7b36d1488..c0e8c48cb5 100644 --- a/libafl/src/events/mod.rs +++ b/libafl/src/events/mod.rs @@ -14,7 +14,13 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ - executors::ExitKind, inputs::Input, monitors::UserStats, observers::ObserversTuple, Error, + bolts::current_time, + executors::ExitKind, + inputs::Input, + monitors::UserStats, + observers::ObserversTuple, + state::{HasClientPerfMonitor, HasExecutions}, + Error, }; /// A per-fuzzer unique `ID`, usually starting with `0` and increasing @@ -268,7 +274,7 @@ where } /// [`EventFirer`] fire an event. -pub trait EventFirer +pub trait EventFirer where I: Input, { @@ -280,10 +286,10 @@ where /// (for example for each [`Input`], on multiple cores) /// the [`llmp`] shared map may fill up and the client will eventually OOM or [`panic`]. /// This should not happen for a normal use-cases. - fn fire(&mut self, state: &mut S, event: Event) -> Result<(), Error>; + fn fire(&mut self, state: &mut S, event: Event) -> Result<(), Error>; /// Serialize all observers for this type and manager - fn serialize_observers(&mut self, observers: &OT) -> Result, Error> + fn serialize_observers(&mut self, observers: &OT) -> Result, Error> where OT: ObserversTuple + serde::Serialize, { @@ -296,6 +302,66 @@ where } } +/// [`EventFirer`] fire an event. +pub trait ProgressReporter: EventFirer +where + I: Input, +{ + /// Given the last time, if `monitor_timeout` seconds passed, send off an info/monitor/heartbeat message to the broker. + /// Returns the new `last` time (so the old one, unless `monitor_timeout` time has passed and monitor have been sent) + /// Will return an [`crate::Error`], if the stats could not be sent. + fn maybe_report_progress( + &mut self, + state: &mut S, + last_report_time: Duration, + monitor_timeout: Duration, + ) -> Result + where + S: HasExecutions + HasClientPerfMonitor, + { + let executions = *state.executions(); + let cur = current_time(); + // default to 0 here to avoid crashes on clock skew + if cur.checked_sub(last_report_time).unwrap_or_default() > monitor_timeout { + // Default no introspection implmentation + #[cfg(not(feature = "introspection"))] + self.fire( + state, + Event::UpdateExecutions { + executions, + time: cur, + phantom: PhantomData, + }, + )?; + + // If performance monitor are requested, fire the `UpdatePerfMonitor` event + #[cfg(feature = "introspection")] + { + state + .introspection_monitor_mut() + .set_current_time(crate::bolts::cpu::read_time_counter()); + + // Send the current monitor over to the manager. This `.clone` shouldn't be + // costly as `ClientPerfMonitor` impls `Copy` since it only contains `u64`s + self.fire( + state, + Event::UpdatePerfMonitor { + executions, + time: cur, + introspection_monitor: Box::new(state.introspection_monitor().clone()), + phantom: PhantomData, + }, + )?; + } + + Ok(cur) + } else { + if cur.as_millis() % 1000 == 0 {} + Ok(last_report_time) + } + } +} + pub trait EventRestarter { /// For restarting event managers, implement a way to forward state to their next peers. #[inline] @@ -332,7 +398,11 @@ pub trait HasEventManagerId { /// [`EventManager`] is the main communications hub. /// For the "normal" multi-processed mode, you may want to look into [`LlmpRestartingEventManager`] pub trait EventManager: - EventFirer + EventProcessor + EventRestarter + HasEventManagerId + EventFirer + + EventProcessor + + EventRestarter + + HasEventManagerId + + ProgressReporter where I: Input, { @@ -342,11 +412,11 @@ where #[derive(Copy, Clone, Debug)] pub struct NopEventManager {} -impl EventFirer for NopEventManager +impl EventFirer for NopEventManager where I: Input, { - fn fire(&mut self, _state: &mut S, _event: Event) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S, _event: Event) -> Result<(), Error> { Ok(()) } } @@ -366,6 +436,8 @@ impl EventProcessor for NopEventManager { impl EventManager for NopEventManager where I: Input {} +impl ProgressReporter for NopEventManager where I: Input {} + impl HasEventManagerId for NopEventManager { fn mgr_id(&self) -> EventManagerId { EventManagerId { id: 0 } diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index 64a87408dc..f20479ef91 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -29,6 +29,8 @@ use crate::{ state::{HasCorpus, HasSolutions}, }; +use super::ProgressReporter; + /// The llmp connection from the actual fuzzer to the process supervising it const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER"; const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER"; @@ -48,12 +50,12 @@ where events: Vec>, } -impl EventFirer for SimpleEventManager +impl EventFirer for SimpleEventManager where I: Input, MT: Monitor, //CE: CustomEvent, { - fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { match Self::handle_in_broker(&mut self.monitor, &event)? { BrokerEventResult::Forward => self.events.push(event), BrokerEventResult::Handled => (), @@ -96,6 +98,13 @@ where { } +impl ProgressReporter for SimpleEventManager +where + I: Input, + MT: Monitor, //CE: CustomEvent, +{ +} + impl HasEventManagerId for SimpleEventManager where I: Input, @@ -230,7 +239,7 @@ where } #[cfg(feature = "std")] -impl<'a, C, I, MT, S, SC, SP> EventFirer +impl<'a, C, I, MT, S, SC, SP> EventFirer for SimpleRestartingEventManager<'a, C, I, MT, S, SC, SP> where C: Corpus, @@ -239,7 +248,7 @@ where SP: ShMemProvider, MT: Monitor, //CE: CustomEvent, { - fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S2, event: Event) -> Result<(), Error> { self.simple_event_mgr.fire(_state, event) } } @@ -289,6 +298,18 @@ where { } +#[cfg(feature = "std")] +impl<'a, C, I, MT, S, SC, SP> ProgressReporter + for SimpleRestartingEventManager<'a, C, I, MT, S, SC, SP> +where + I: Input, + C: Corpus, + S: Serialize, + SP: ShMemProvider, + MT: Monitor, //CE: CustomEvent, +{ +} + #[cfg(feature = "std")] impl<'a, C, I, MT, S, SC, SP> HasEventManagerId for SimpleRestartingEventManager<'a, C, I, MT, S, SC, SP> diff --git a/libafl/src/executors/inprocess.rs b/libafl/src/executors/inprocess.rs index 199b3f5f52..a70c46daec 100644 --- a/libafl/src/executors/inprocess.rs +++ b/libafl/src/executors/inprocess.rs @@ -163,7 +163,7 @@ where _event_mgr: &mut EM, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OC: Corpus, OF: Feedback, S: HasSolutions + HasClientPerfMonitor, @@ -393,7 +393,7 @@ mod unix_signal_handler { data: &mut InProcessExecutorHandlerData, ) where E: HasObservers, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OT: ObserversTuple, OC: Corpus, OF: Feedback, @@ -471,7 +471,7 @@ mod unix_signal_handler { data: &mut InProcessExecutorHandlerData, ) where E: HasObservers, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OT: ObserversTuple, OC: Corpus, OF: Feedback, @@ -643,7 +643,7 @@ mod windows_exception_handler { _p1: u8, ) where E: HasObservers, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OT: ObserversTuple, OC: Corpus, OF: Feedback, @@ -719,7 +719,7 @@ mod windows_exception_handler { data: &mut InProcessExecutorHandlerData, ) where E: HasObservers, - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OT: ObserversTuple, OC: Corpus, OF: Feedback, @@ -917,7 +917,7 @@ where shmem_provider: SP, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OC: Corpus, OF: Feedback, S: HasSolutions + HasClientPerfMonitor, diff --git a/libafl/src/feedbacks/concolic.rs b/libafl/src/feedbacks/concolic.rs index 9efa963fdf..434d940ea6 100644 --- a/libafl/src/feedbacks/concolic.rs +++ b/libafl/src/feedbacks/concolic.rs @@ -53,7 +53,7 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { self.metadata = observers diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs index 72f9c94924..2f97411d0c 100644 --- a/libafl/src/feedbacks/map.rs +++ b/libafl/src/feedbacks/map.rs @@ -336,7 +336,7 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { let mut interesting = false; @@ -563,7 +563,7 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { // TODO Replace with match_name_type when stable diff --git a/libafl/src/feedbacks/mod.rs b/libafl/src/feedbacks/mod.rs index 4c689ac1da..81ec585158 100644 --- a/libafl/src/feedbacks/mod.rs +++ b/libafl/src/feedbacks/mod.rs @@ -48,7 +48,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple; #[cfg(feature = "introspection")] @@ -62,7 +62,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { // Start a timer for this feedback @@ -193,7 +193,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { FL::is_pair_interesting( @@ -217,7 +217,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { FL::is_pair_interesting_introspection( @@ -263,7 +263,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple; #[cfg(feature = "introspection")] @@ -278,7 +278,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple; } @@ -308,7 +308,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { let a = first.is_interesting(state, manager, input, observers, exit_kind)?; @@ -327,7 +327,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { // Execute this feedback @@ -359,7 +359,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { let a = first.is_interesting(state, manager, input, observers, exit_kind)?; @@ -381,7 +381,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { // Execute this feedback @@ -416,7 +416,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { let a = first.is_interesting(state, manager, input, observers, exit_kind)?; @@ -435,7 +435,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { // Execute this feedback @@ -467,7 +467,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { let a = first.is_interesting(state, manager, input, observers, exit_kind)?; @@ -489,7 +489,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { // Execute this feedback @@ -550,7 +550,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { Ok(!self @@ -664,7 +664,7 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { Ok(false) @@ -696,7 +696,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { if let ExitKind::Crash = exit_kind { @@ -746,7 +746,7 @@ where exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { if let ExitKind::Timeout = exit_kind { @@ -801,7 +801,7 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { // TODO Replace with match_name_type when stable diff --git a/libafl/src/feedbacks/nautilus.rs b/libafl/src/feedbacks/nautilus.rs index b7125f016f..e51e2cd5b3 100644 --- a/libafl/src/feedbacks/nautilus.rs +++ b/libafl/src/feedbacks/nautilus.rs @@ -63,7 +63,7 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { Ok(false) diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index a6fe74d544..e487edcb27 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -3,7 +3,7 @@ use crate::{ bolts::current_time, corpus::{Corpus, CorpusScheduler, Testcase}, - events::{Event, EventConfig, EventFirer, EventManager}, + events::{Event, EventConfig, EventFirer, EventManager, ProgressReporter}, executors::{Executor, ExitKind, HasObservers}, feedbacks::Feedback, inputs::Input, @@ -17,8 +17,6 @@ use crate::{ #[cfg(feature = "introspection")] use crate::monitors::PerfFeature; -#[cfg(feature = "introspection")] -use alloc::boxed::Box; use alloc::string::ToString; use core::{marker::PhantomData, time::Duration}; @@ -84,7 +82,7 @@ where send_events: bool, ) -> Result<(ExecuteInputResult, Option), Error> where - EM: EventFirer; + EM: EventFirer; } /// Evaluate an input modyfing the state of the fuzzer @@ -148,7 +146,12 @@ pub trait Evaluator { } /// The main fuzzer trait. -pub trait Fuzzer { +pub trait Fuzzer +where + I: Input, + EM: ProgressReporter, + S: HasExecutions + HasClientPerfMonitor, +{ /// Fuzz for a single iteration /// Returns the index of the last fuzzed corpus item /// @@ -175,7 +178,7 @@ pub trait Fuzzer { let monitor_timeout = STATS_TIMEOUT_DEFAULT; loop { self.fuzz_one(stages, executor, state, manager)?; - last = Self::maybe_report_monitor(state, manager, last, monitor_timeout)?; + last = manager.maybe_report_progress(state, last, monitor_timeout)?; } } @@ -205,7 +208,7 @@ pub trait Fuzzer { for _ in 0..iters { ret = self.fuzz_one(stages, executor, state, manager)?; - last = Self::maybe_report_monitor(state, manager, last, monitor_timeout)?; + last = manager.maybe_report_progress(state, last, monitor_timeout)?; } // If we would assume the fuzzer loop will always exit after this, we could do this here: @@ -215,16 +218,6 @@ pub trait Fuzzer { Ok(ret) } - - /// Given the last time, if `monitor_timeout` seconds passed, send off an info/monitor/heartbeat message to the broker. - /// Returns the new `last` time (so the old one, unless `monitor_timeout` time has passed and monitor have been sent) - /// Will return an [`crate::Error`], if the monitor could not be sent. - fn maybe_report_monitor( - state: &mut S, - manager: &mut EM, - last: Duration, - monitor_timeout: Duration, - ) -> Result; } #[derive(Debug, PartialEq)] @@ -325,7 +318,7 @@ where send_events: bool, ) -> Result<(ExecuteInputResult, Option), Error> where - EM: EventFirer, + EM: EventFirer, { let mut res = ExecuteInputResult::None; @@ -428,7 +421,7 @@ where F: Feedback, I: Input, OF: Feedback, - S: HasExecutions + HasCorpus + HasSolutions + HasClientPerfMonitor, + S: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions, SC: Corpus, { /// Process one input, adding to the respective corpuses if needed and firing the right events @@ -462,7 +455,7 @@ where F: Feedback, I: Input, OF: Feedback, - S: HasExecutions + HasCorpus + HasSolutions + HasClientPerfMonitor, + S: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions, SC: Corpus, { /// Process one input, adding to the respective corpuses if needed and firing the right events @@ -527,58 +520,10 @@ where EM: EventManager, F: Feedback, I: Input, - S: HasExecutions + HasClientPerfMonitor, + S: HasClientPerfMonitor + HasExecutions, OF: Feedback, ST: StagesTuple, { - #[inline] - fn maybe_report_monitor( - state: &mut S, - manager: &mut EM, - last: Duration, - monitor_timeout: Duration, - ) -> Result { - let cur = current_time(); - // default to 0 here to avoid crashes on clock skew - if cur.checked_sub(last).unwrap_or_default() > monitor_timeout { - // Default no introspection implmentation - #[cfg(not(feature = "introspection"))] - manager.fire( - state, - Event::UpdateExecutions { - executions: *state.executions(), - time: cur, - phantom: PhantomData, - }, - )?; - - // If performance monitor are requested, fire the `UpdatePerfMonitor` event - #[cfg(feature = "introspection")] - { - state - .introspection_monitor_mut() - .set_current_time(crate::bolts::cpu::read_time_counter()); - - // Send the current monitor over to the manager. This `.clone` shouldn't be - // costly as `ClientPerfMonitor` impls `Copy` since it only contains `u64`s - manager.fire( - state, - Event::UpdatePerfMonitor { - executions: *state.executions(), - time: cur, - introspection_monitor: Box::new(state.introspection_monitor().clone()), - phantom: PhantomData, - }, - )?; - } - - Ok(cur) - } else { - if cur.as_millis() % 1000 == 0 {} - Ok(last) - } - } - fn fuzz_one( &mut self, stages: &mut ST, @@ -666,3 +611,61 @@ where Ok(exit_kind) } } + +pub trait ExecutesInput +where + I: Input, + OT: ObserversTuple, +{ + /// Runs the input and triggers observers and feedback + fn execute_input( + &mut self, + state: &mut S, + executor: &mut E, + event_mgr: &mut EM, + input: &I, + ) -> Result + where + E: Executor + HasObservers, + OT: ObserversTuple; +} + +impl ExecutesInput + for StdFuzzer +where + CS: CorpusScheduler, + F: Feedback, + I: Input, + OT: ObserversTuple, + OF: Feedback, + S: HasExecutions + HasClientPerfMonitor, +{ + /// Runs the input and triggers observers and feedback + fn execute_input( + &mut self, + state: &mut S, + executor: &mut E, + event_mgr: &mut EM, + input: &I, + ) -> Result + where + E: Executor + HasObservers, + OT: ObserversTuple, + { + start_timer!(state); + executor.observers_mut().pre_exec_all(state, input)?; + mark_feature_time!(state, PerfFeature::PreExecObservers); + + start_timer!(state); + let exit_kind = executor.run_target(self, state, event_mgr, input)?; + mark_feature_time!(state, PerfFeature::TargetExecution); + + *state.executions_mut() += 1; + + start_timer!(state); + executor.observers_mut().post_exec_all(state, input)?; + mark_feature_time!(state, PerfFeature::PostExecObservers); + + Ok(exit_kind) + } +} diff --git a/libafl/src/stages/mod.rs b/libafl/src/stages/mod.rs index aa263899be..135a96281d 100644 --- a/libafl/src/stages/mod.rs +++ b/libafl/src/stages/mod.rs @@ -31,9 +31,27 @@ pub mod sync; #[cfg(feature = "std")] pub use sync::*; -use crate::Error; +use crate::events::EventFirer; +use crate::events::EventRestarter; +use crate::events::HasEventManagerId; +use crate::events::ProgressReporter; +use crate::state::HasExecutions; +use crate::{ + bolts::rands::Rand, + corpus::Corpus, + corpus::CorpusScheduler, + executors::Executor, + executors::HasObservers, + inputs::Input, + observers::ObserversTuple, + state::HasRand, + state::{HasClientPerfMonitor, HasCorpus}, + Error, EvaluatorObservers, ExecutesInput, ExecutionProcessor, HasCorpusScheduler, +}; use core::{convert::From, marker::PhantomData}; +use self::push::PushStage; + /// A stage is one step in the fuzzing process. /// Multiple stages will be scheduled one by one for each input. pub trait Stage { @@ -143,3 +161,100 @@ where Self::new(closure) } } + +/// Allows us to use a [`push::PushStage`] as a normal [`Stage`] +#[allow(clippy::type_complexity)] +pub struct PushStageAdapter +where + C: Corpus, + CS: CorpusScheduler, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + I: Input, + OT: ObserversTuple, + PS: PushStage, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, +{ + push_stage: PS, + phantom: PhantomData<(C, CS, EM, I, OT, R, S, Z)>, +} + +impl PushStageAdapter +where + C: Corpus, + CS: CorpusScheduler, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + I: Input, + OT: ObserversTuple, + PS: PushStage, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, +{ + /// Create a new [`PushStageAdapter`], warpping the given [`PushStage`] + /// to be used as a normal [`Stage`] + #[must_use] + pub fn new(push_stage: PS) -> Self { + Self { + push_stage, + phantom: PhantomData, + } + } +} + +impl Stage + for PushStageAdapter +where + C: Corpus, + CS: CorpusScheduler, + E: Executor + HasObservers, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + I: Input, + OT: ObserversTuple, + PS: PushStage, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions, + Z: ExecutesInput + + ExecutionProcessor + + EvaluatorObservers + + HasCorpusScheduler, +{ + fn perform( + &mut self, + fuzzer: &mut Z, + executor: &mut E, + state: &mut S, + event_mgr: &mut EM, + corpus_idx: usize, + ) -> Result<(), Error> { + let push_stage = &mut self.push_stage; + + push_stage.set_current_corpus_idx(corpus_idx); + + push_stage.init(fuzzer, state, event_mgr, executor.observers_mut())?; + + loop { + let input = + match push_stage.pre_exec(fuzzer, state, event_mgr, executor.observers_mut()) { + Some(Ok(next_input)) => next_input, + Some(Err(err)) => return Err(err), + None => break, + }; + + let exit_kind = fuzzer.execute_input(state, executor, event_mgr, &input)?; + + push_stage.post_exec( + fuzzer, + state, + event_mgr, + executor.observers_mut(), + input, + exit_kind, + )?; + } + + self.push_stage + .deinit(fuzzer, state, event_mgr, executor.observers_mut()) + } +} diff --git a/libafl/src/stages/push/mod.rs b/libafl/src/stages/push/mod.rs index 5db0f13702..6ceb7e001e 100644 --- a/libafl/src/stages/push/mod.rs +++ b/libafl/src/stages/push/mod.rs @@ -8,5 +8,337 @@ pub mod mutational; pub use mutational::StdMutationalPushStage; +use alloc::rc::Rc; +use core::{ + cell::{Cell, RefCell}, + marker::PhantomData, + time::Duration, +}; + +use crate::{ + bolts::{current_time, rands::Rand}, + corpus::{Corpus, CorpusScheduler}, + events::{EventFirer, EventRestarter, HasEventManagerId, ProgressReporter}, + executors::ExitKind, + inputs::Input, + observers::ObserversTuple, + state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasRand}, + Error, EvaluatorObservers, ExecutionProcessor, HasCorpusScheduler, +}; + +/// Send a monitor update all 15 (or more) seconds +const STATS_TIMEOUT_DEFAULT: Duration = Duration::from_secs(15); + +// The shared state for all [`PushStage`]s +/// Should be stored inside a `[Rc>`] +#[derive(Clone, Debug)] +pub struct PushStageSharedState +where + C: Corpus, + CS: CorpusScheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + I: Input, + OT: ObserversTuple, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, +{ + /// The [`crate::state::State`] + pub state: S, + /// The [`crate::fuzzer::Fuzzer`] instance + pub fuzzer: Z, + /// The [`crate::events::EventManager`] + pub event_mgr: EM, + /// The [`crate::observers::ObserversTuple`] + pub observers: OT, + phantom: PhantomData<(C, CS, I, OT, R, S, Z)>, +} + +impl PushStageSharedState +where + C: Corpus, + CS: CorpusScheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + I: Input, + OT: ObserversTuple, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, +{ + /// Create a new `PushStageSharedState` that can be used by all [`PushStage`]s + #[must_use] + pub fn new(fuzzer: Z, state: S, observers: OT, event_mgr: EM) -> Self { + Self { + state, + fuzzer, + event_mgr, + observers, + phantom: PhantomData, + } + } +} + +/// Helper class for the [`PushStage`] trait, taking care of borrowing the shared state +#[derive(Clone, Debug)] +pub struct PushStageHelper +where + C: Corpus, + CS: CorpusScheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + I: Input, + OT: ObserversTuple, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, +{ + /// If this stage has already been initalized. + /// This gets reset to `false` after one iteration of the stage is done. + pub initialized: bool, + /// The last time the monitor was updated + pub last_monitor_time: Duration, + /// The shared state, keeping track of the corpus and the fuzzer + #[allow(clippy::type_complexity)] + pub shared_state: Rc>>>, + /// If the last iteraation failed + pub errored: bool, + + /// The corpus index we're currently working on + pub current_corpus_idx: Option, + + /// The input we just ran + pub current_input: Option, // Todo: Get rid of copy + + #[allow(clippy::type_complexity)] + phantom: PhantomData<(C, CS, (), EM, I, R, OT, S, Z)>, + exit_kind: Rc>>, +} + +impl PushStageHelper +where + C: Corpus, + CS: CorpusScheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + I: Input, + OT: ObserversTuple, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, +{ + /// Create a new [`PushStageHelper`] + #[must_use] + #[allow(clippy::type_complexity)] + pub fn new( + shared_state: Rc>>>, + exit_kind_ref: Rc>>, + ) -> Self { + Self { + shared_state, + initialized: false, + phantom: PhantomData, + last_monitor_time: current_time(), + exit_kind: exit_kind_ref, + errored: false, + current_input: None, + current_corpus_idx: None, + } + } + + /// Sets the shared state for this helper (and all other helpers owning the same [`RefCell`]) + #[inline] + pub fn set_shared_state( + &mut self, + shared_state: PushStageSharedState, + ) { + (&mut *self.shared_state.borrow_mut()).replace(shared_state); + } + + /// Takes the shared state from this helper, replacing it with `None` + #[inline] + #[allow(clippy::type_complexity)] + pub fn take_shared_state(&mut self) -> Option> { + let shared_state_ref = &mut (*self.shared_state).borrow_mut(); + shared_state_ref.take() + } + + /// Returns the exit kind of the last run + #[inline] + #[must_use] + pub fn exit_kind(&self) -> Option { + self.exit_kind.get() + } + + /// Resets the exit kind + #[inline] + pub fn reset_exit_kind(&mut self) { + self.exit_kind.set(None); + } + + /// Resets this state after a full stage iter. + fn end_of_iter( + &mut self, + shared_state: PushStageSharedState, + errored: bool, + ) { + self.set_shared_state(shared_state); + self.errored = errored; + self.current_corpus_idx = None; + if errored { + self.initialized = false; + } + } +} + /// A push stage is a generator that returns a single testcase for each call. -pub trait PushStage: Iterator {} +/// It's an iterator so we can chain it. +/// After it has finished once, we will call it agan for the next fuzzer round. +pub trait PushStage: Iterator +where + C: Corpus, + CS: CorpusScheduler, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + I: Input, + OT: ObserversTuple, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, +{ + /// Gets the [`PushStageHelper`] + fn push_stage_helper(&self) -> &PushStageHelper; + /// Gets the [`PushStageHelper`], mut + fn push_stage_helper_mut(&mut self) -> &mut PushStageHelper; + + /// Set the current corpus index this stagve works on + fn set_current_corpus_idx(&mut self, corpus_idx: usize) { + self.push_stage_helper_mut().current_corpus_idx = Some(corpus_idx); + } + + /// Called by `next_std` when this stage is being initialized. + /// This is called before the first iteration of the stage. + /// After the stage has finished once (after `deinit`), this will be called again. + #[inline] + fn init( + &mut self, + _fuzzer: &mut Z, + _state: &mut S, + _event_mgr: &mut EM, + _observers: &mut OT, + ) -> Result<(), Error> { + Ok(()) + } + + /// Called before the a test case is executed. + /// Should return the test case to be executed. + /// After this stage has finished, or if the stage does not process any inputs, this should return `None`. + fn pre_exec( + &mut self, + _fuzzer: &mut Z, + _state: &mut S, + _event_mgr: &mut EM, + _observers: &mut OT, + ) -> Option>; + + /// Called after the execution of a testcase finished. + #[inline] + fn post_exec( + &mut self, + _fuzzer: &mut Z, + _state: &mut S, + _event_mgr: &mut EM, + _observers: &mut OT, + _input: I, + _exit_kind: ExitKind, + ) -> Result<(), Error> { + Ok(()) + } + + /// Called after the stage finished (`pre_exec` returned `None`) + #[inline] + fn deinit( + &mut self, + _fuzzer: &mut Z, + _state: &mut S, + _event_mgr: &mut EM, + _observers: &mut OT, + ) -> Result<(), Error> { + Ok(()) + } + + /// This is the default implementation for `next` for this stage + fn next_std(&mut self) -> Option> { + let mut shared_state = { + let shared_state_ref = &mut (*self.push_stage_helper_mut().shared_state).borrow_mut(); + shared_state_ref.take().unwrap() + }; + + let step_success = if self.push_stage_helper().initialized { + // We already ran once + + let last_input = self.push_stage_helper_mut().current_input.take().unwrap(); + + self.post_exec( + &mut shared_state.fuzzer, + &mut shared_state.state, + &mut shared_state.event_mgr, + &mut shared_state.observers, + last_input, + self.push_stage_helper().exit_kind().unwrap(), + ) + } else { + self.init( + &mut shared_state.fuzzer, + &mut shared_state.state, + &mut shared_state.event_mgr, + &mut shared_state.observers, + ) + }; + if let Err(err) = step_success { + self.push_stage_helper_mut().end_of_iter(shared_state, true); + return Some(Err(err)); + } + + //for i in 0..num { + let ret = self.pre_exec( + &mut shared_state.fuzzer, + &mut shared_state.state, + &mut shared_state.event_mgr, + &mut shared_state.observers, + ); + if ret.is_none() { + // We're done. + drop(self.push_stage_helper_mut().current_input.take()); + self.push_stage_helper_mut().initialized = false; + + if let Err(err) = self.deinit( + &mut shared_state.fuzzer, + &mut shared_state.state, + &mut shared_state.event_mgr, + &mut shared_state.observers, + ) { + self.push_stage_helper_mut().end_of_iter(shared_state, true); + return Some(Err(err)); + }; + + let last_monitor_time = self.push_stage_helper().last_monitor_time; + + let new_monitor_time = match shared_state.event_mgr.maybe_report_progress( + &mut shared_state.state, + last_monitor_time, + STATS_TIMEOUT_DEFAULT, + ) { + Ok(new_time) => new_time, + Err(err) => { + self.push_stage_helper_mut().end_of_iter(shared_state, true); + return Some(Err(err)); + } + }; + + self.push_stage_helper_mut().last_monitor_time = new_monitor_time; + //self.fuzzer.maybe_report_monitor(); + } else { + self.push_stage_helper_mut().reset_exit_kind(); + } + self.push_stage_helper_mut() + .end_of_iter(shared_state, false); + ret + } +} diff --git a/libafl/src/stages/push/mutational.rs b/libafl/src/stages/push/mutational.rs index ce4753419c..d4eb9bd07e 100644 --- a/libafl/src/stages/push/mutational.rs +++ b/libafl/src/stages/push/mutational.rs @@ -2,35 +2,28 @@ //! For the current input, it will perform a range of random mutations, and then run them in the executor. use alloc::rc::Rc; -use core::{ - borrow::BorrowMut, - cell::{Cell, RefCell}, - marker::PhantomData, - time::Duration, -}; +use core::cell::{Cell, RefCell}; use crate::{ - bolts::{current_time, rands::Rand}, + bolts::rands::Rand, corpus::{Corpus, CorpusScheduler}, - events::EventManager, + events::{EventFirer, EventRestarter, HasEventManagerId, ProgressReporter}, executors::ExitKind, inputs::Input, mark_feature_time, mutators::Mutator, observers::ObserversTuple, start_timer, - state::{HasClientPerfMonitor, HasCorpus, HasRand}, - Error, EvaluatorObservers, ExecutionProcessor, Fuzzer, HasCorpusScheduler, + state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasRand}, + Error, EvaluatorObservers, ExecutionProcessor, HasCorpusScheduler, }; #[cfg(feature = "introspection")] use crate::monitors::PerfFeature; -/// Send a monitor update all 15 (or more) seconds -const STATS_TIMEOUT_DEFAULT: Duration = Duration::from_secs(15); +use super::{PushStage, PushStageHelper, PushStageSharedState}; pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: u64 = 128; - /// A Mutational push stage is the stage in a fuzzing run that mutates inputs. /// Mutational push stages will usually have a range of mutations that are /// being applied to the input one by one, between executions. @@ -45,52 +38,36 @@ pub struct StdMutationalPushStage where C: Corpus, CS: CorpusScheduler, - EM: EventManager<(), I, S, Z>, + EM: EventFirer + EventRestarter + HasEventManagerId, I: Input, M: Mutator, OT: ObserversTuple, R: Rand, S: HasClientPerfMonitor + HasCorpus + HasRand, - Z: ExecutionProcessor - + EvaluatorObservers - + Fuzzer<(), EM, I, S, ()> - + HasCorpusScheduler, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, { - initialized: bool, - state: Rc>, current_corpus_idx: Option, testcases_to_do: usize, testcases_done: usize, - fuzzer: Rc>, - event_mgr: Rc>, - - current_input: Option, // Todo: Get rid of copy - stage_idx: i32, mutator: M, - #[allow(clippy::type_complexity)] - phantom: PhantomData<(C, CS, (), EM, I, R, OT, S, Z)>, - last_monitor_time: Duration, - observers: Rc>, - exit_kind: Rc>>, + + psh: PushStageHelper, } impl StdMutationalPushStage where C: Corpus, CS: CorpusScheduler, - EM: EventManager<(), I, S, Z>, + EM: EventFirer + EventRestarter + HasEventManagerId, I: Input, M: Mutator, OT: ObserversTuple, R: Rand, S: HasClientPerfMonitor + HasCorpus + HasRand, - Z: ExecutionProcessor - + EvaluatorObservers - + Fuzzer<(), EM, I, S, ()> - + HasCorpusScheduler, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, { /// Gets the number of iterations as a random number #[allow(clippy::unused_self, clippy::unnecessary_wraps)] // TODO: we should put this function into a trait later @@ -101,16 +78,33 @@ where pub fn set_current_corpus_idx(&mut self, current_corpus_idx: usize) { self.current_corpus_idx = Some(current_corpus_idx); } +} +impl PushStage + for StdMutationalPushStage +where + C: Corpus, + CS: CorpusScheduler, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + I: Input, + M: Mutator, + OT: ObserversTuple, + R: Rand, + S: HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, +{ /// Creates a new default mutational stage - fn init(&mut self) -> Result<(), Error> { - let state: &mut S = &mut (*self.state).borrow_mut(); - + fn init( + &mut self, + fuzzer: &mut Z, + state: &mut S, + _event_mgr: &mut EM, + _observers: &mut OT, + ) -> Result<(), Error> { // Find a testcase to work on, unless someone already set it self.current_corpus_idx = Some(if let Some(corpus_idx) = self.current_corpus_idx { corpus_idx } else { - let fuzzer: &mut Z = &mut (*self.fuzzer).borrow_mut(); fuzzer.scheduler().next(state)? }); @@ -119,9 +113,25 @@ where Ok(()) } - fn pre_exec(&mut self) -> Option> { - let state: &mut S = &mut (*self.state).borrow_mut(); + #[inline] + fn deinit( + &mut self, + _fuzzer: &mut Z, + _state: &mut S, + _event_mgr: &mut EM, + _observers: &mut OT, + ) -> Result<(), Error> { + self.current_corpus_idx = None; + Ok(()) + } + fn pre_exec( + &mut self, + _fuzzer: &mut Z, + state: &mut S, + _event_mgr: &mut EM, + _observers: &mut OT, + ) -> Option> { if self.testcases_done >= self.testcases_to_do { // finished with this cicle. return None; @@ -144,29 +154,25 @@ where .unwrap(); mark_feature_time!(state, PerfFeature::Mutate); - self.current_input = Some(input.clone()); // TODO: Get rid of this + self.push_stage_helper_mut() + .current_input + .replace(input.clone()); // TODO: Get rid of this Some(Ok(input)) } - fn post_exec(&mut self) -> Result<(), Error> { + fn post_exec( + &mut self, + fuzzer: &mut Z, + state: &mut S, + event_mgr: &mut EM, + observers: &mut OT, + last_input: I, + exit_kind: ExitKind, + ) -> Result<(), Error> { // todo: isintersting, etc. - let state: &mut S = &mut (*self.state).borrow_mut(); - - let fuzzer: &mut Z = &mut (*self.fuzzer).borrow_mut(); - let event_mgr: &mut EM = &mut (*self.event_mgr).borrow_mut(); - let observers_refcell: &RefCell = self.observers.borrow_mut(); - let observers: &mut OT = &mut observers_refcell.borrow_mut(); - - fuzzer.process_execution( - state, - event_mgr, - self.current_input.take().unwrap(), - observers, - &self.exit_kind.get().unwrap(), - true, - )?; + fuzzer.process_execution(state, event_mgr, last_input, observers, &exit_kind, true)?; start_timer!(state); self.mutator @@ -176,60 +182,34 @@ where Ok(()) } + + #[inline] + fn push_stage_helper(&self) -> &PushStageHelper { + &self.psh + } + + #[inline] + fn push_stage_helper_mut(&mut self) -> &mut PushStageHelper { + &mut self.psh + } } impl Iterator for StdMutationalPushStage where C: Corpus, CS: CorpusScheduler, - EM: EventManager<(), I, S, Z>, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, I: Input, M: Mutator, OT: ObserversTuple, R: Rand, - S: HasClientPerfMonitor + HasCorpus + HasRand, - Z: ExecutionProcessor - + EvaluatorObservers - + Fuzzer<(), EM, I, S, ()> - + HasCorpusScheduler, + S: HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, { type Item = Result; fn next(&mut self) -> Option> { - let step_success = if self.initialized { - // We already ran once - self.post_exec() - } else { - self.init() - }; - if let Err(err) = step_success { - //let errored = true; - return Some(Err(err)); - } - - //for i in 0..num { - let ret = self.pre_exec(); - if ret.is_none() { - // We're done. - self.initialized = false; - self.current_corpus_idx = None; - - let state: &mut S = &mut (*self.state).borrow_mut(); - //let fuzzer: &mut Z = &mut (*self.fuzzer).borrow_mut(); - let event_mgr: &mut EM = &mut (*self.event_mgr).borrow_mut(); - - self.last_monitor_time = Z::maybe_report_monitor( - state, - event_mgr, - self.last_monitor_time, - STATS_TIMEOUT_DEFAULT, - ) - .unwrap(); - //self.fuzzer.maybe_report_monitor(); - } else { - self.exit_kind.replace(None); - } - ret + self.next_std() } } @@ -237,42 +217,30 @@ impl StdMutationalPushStage, CS: CorpusScheduler, - EM: EventManager<(), I, S, Z>, + EM: EventFirer + EventRestarter + HasEventManagerId, I: Input, M: Mutator, OT: ObserversTuple, R: Rand, S: HasClientPerfMonitor + HasCorpus + HasRand, - Z: ExecutionProcessor - + EvaluatorObservers - + Fuzzer<(), EM, I, S, ()> - + HasCorpusScheduler, + Z: ExecutionProcessor + EvaluatorObservers + HasCorpusScheduler, { /// Creates a new default mutational stage + #[must_use] + #[allow(clippy::type_complexity)] pub fn new( mutator: M, - fuzzer: Rc>, - state: Rc>, - event_mgr: Rc>, - observers: Rc>, + shared_state: Rc>>>, exit_kind: Rc>>, stage_idx: i32, ) -> Self { Self { mutator, - phantom: PhantomData, - initialized: false, - state, + psh: PushStageHelper::new(shared_state, exit_kind), current_corpus_idx: None, // todo testcases_to_do: 0, testcases_done: 0, - current_input: None, stage_idx, - fuzzer, - event_mgr, - observers, - exit_kind, - last_monitor_time: current_time(), } } } diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index ecae009a96..285d6308aa 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -411,7 +411,7 @@ where ) -> Result<(), Error> where Z: Evaluator, - EM: EventFirer, + EM: EventFirer, { for in_dir in in_dirs { self.load_from_directory( @@ -446,7 +446,7 @@ where ) -> Result<(), Error> where Z: Evaluator, - EM: EventFirer, + EM: EventFirer, { self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, true) } @@ -461,7 +461,7 @@ where ) -> Result<(), Error> where Z: Evaluator, - EM: EventFirer, + EM: EventFirer, { self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, false) } @@ -487,7 +487,7 @@ where where G: Generator, Z: Evaluator, - EM: EventFirer, + EM: EventFirer, { let mut added = 0; for _ in 0..num { @@ -525,7 +525,7 @@ where where G: Generator, Z: Evaluator, - EM: EventFirer, + EM: EventFirer, { self.generate_initial_internal(fuzzer, executor, generator, manager, num, true) } @@ -542,7 +542,7 @@ where where G: Generator, Z: Evaluator, - EM: EventFirer, + EM: EventFirer, { self.generate_initial_internal(fuzzer, executor, generator, manager, num, false) } diff --git a/libafl_frida/src/asan_errors.rs b/libafl_frida/src/asan_errors.rs index 0fc2374e0f..7abb4de91a 100644 --- a/libafl_frida/src/asan_errors.rs +++ b/libafl_frida/src/asan_errors.rs @@ -126,7 +126,7 @@ impl AsanErrors { self.errors.is_empty() } - /// Get a mutable reference to the global [`AsanErrors`] object + /// Get a mutable reference to the global [`struct@AsanErrors`] object #[must_use] pub fn get_mut<'a>() -> &'a mut Self { unsafe { ASAN_ERRORS.as_mut().unwrap() } @@ -595,7 +595,7 @@ impl AsanErrorsObserver { } } - /// gets the [`AsanErrors`] from the previous run + /// gets the [`struct@AsanErrors`] from the previous run #[must_use] pub fn errors(&self) -> Option<&AsanErrors> { match &self.errors { @@ -605,7 +605,7 @@ impl AsanErrorsObserver { } } -/// A feedback reporting potential [`AsanErrors`] from an `AsanErrorsObserver` +/// A feedback reporting potential [`struct@AsanErrors`] from an `AsanErrorsObserver` #[derive(Serialize, Deserialize, Clone, Debug)] pub struct AsanErrorsFeedback { errors: Option, @@ -625,7 +625,7 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, + EM: EventFirer, OT: ObserversTuple, { let observer = observers diff --git a/libafl_frida/src/helper.rs b/libafl_frida/src/helper.rs index 38590178da..9af558d950 100644 --- a/libafl_frida/src/helper.rs +++ b/libafl_frida/src/helper.rs @@ -75,7 +75,7 @@ const ANONYMOUS_FLAG: MapFlags = MapFlags::MAP_ANON; #[cfg(not(any(target_vendor = "apple", target_os = "windows")))] const ANONYMOUS_FLAG: MapFlags = MapFlags::MAP_ANONYMOUS; -/// An helper that feeds [`FridaInProcessExecutor`] with user-supplied instrumentation +/// An helper that feeds `FridaInProcessExecutor` with user-supplied instrumentation pub trait FridaHelper<'a> { /// Access to the stalker `Transformer` fn transformer(&self) -> &Transformer<'a>; @@ -99,7 +99,7 @@ pub trait FridaHelper<'a> { fn ranges(&self) -> &RangeMap; } -/// An helper that feeds [`FridaInProcessExecutor`] with edge-coverage instrumentation +/// An helper that feeds `FridaInProcessExecutor` with edge-coverage instrumentation pub struct FridaInstrumentationHelper<'a> { coverage_rt: CoverageRuntime, #[cfg(unix)] diff --git a/libafl_frida/src/lib.rs b/libafl_frida/src/lib.rs index 7a20e93fcc..b96cf1e081 100644 --- a/libafl_frida/src/lib.rs +++ b/libafl_frida/src/lib.rs @@ -44,7 +44,7 @@ pub struct FridaOptions { } impl FridaOptions { - /// Parse the frida options from the [`LIBAFL_FRIDA_OPTIONS`] environment variable. + /// Parse the frida options from the "`LIBAFL_FRIDA_OPTIONS`" environment variable. /// /// Options are `:` separated, and each options is a `name=value` string. /// diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index 34debdbcd1..910daeef35 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -383,7 +383,7 @@ where event_mgr: &mut EM, ) -> Result where - EM: EventFirer + EventRestarter, + EM: EventFirer + EventRestarter, OC: Corpus, OF: Feedback, S: HasSolutions + HasClientPerfMonitor,