diff --git a/libafl/src/stages/sync.rs b/libafl/src/stages/sync.rs index 3dbed175a2..a0ce464025 100644 --- a/libafl/src/stages/sync.rs +++ b/libafl/src/stages/sync.rs @@ -12,6 +12,8 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "introspection")] use crate::state::HasClientPerfMonitor; +#[cfg(feature = "share_objectives")] +use crate::state::HasSolutions; use crate::{ corpus::{Corpus, CorpusId}, events::{llmp::LlmpEventConverter, Event, EventConfig, EventFirer}, @@ -245,6 +247,8 @@ where type State = S; } +// Do not include trait bound HasSolutions to S if share_objectives is disabled +#[cfg(not(feature = "share_objectives"))] impl Stage for SyncFromBrokerStage where EM: UsesState + EventFirer, @@ -331,6 +335,94 @@ where } } +// Add trait bound HasSolutions to S if share_objectives is enabled +#[cfg(feature = "share_objectives")] +impl Stage for SyncFromBrokerStage +where + EM: UsesState + EventFirer, + S: State + HasExecutions + HasCorpus + HasRand + HasMetadata + HasSolutions, + SP: ShMemProvider, + E: HasObservers + Executor, + for<'a> E::Observers: Deserialize<'a>, + Z: EvaluatorObservers + + ExecutionProcessor, + IC: InputConverter, + ICB: InputConverter, + DI: Input, + <::Corpus as Corpus>::Input: Clone, + S::Corpus: Corpus, // delete me +{ + #[inline] + fn perform( + &mut self, + fuzzer: &mut Z, + executor: &mut E, + state: &mut Self::State, + manager: &mut EM, + ) -> Result<(), Error> { + if self.client.can_convert() { + let last_id = state + .metadata_map() + .get::() + .and_then(|m| m.last_id); + + let mut cur_id = + last_id.map_or_else(|| state.corpus().first(), |id| state.corpus().next(id)); + + while let Some(id) = cur_id { + let input = state.corpus().cloned_input_for_id(id)?; + + self.client.fire( + state, + Event::NewTestcase { + input, + observers_buf: None, + exit_kind: ExitKind::Ok, + corpus_size: 0, // TODO choose if sending 0 or the actual real value + client_config: EventConfig::AlwaysUnique, + time: current_time(), + forward_id: None, + #[cfg(all(unix, feature = "std", feature = "multi_machine"))] + node_id: None, + }, + )?; + + cur_id = state.corpus().next(id); + } + + let last = state.corpus().last(); + if last_id.is_none() { + state + .metadata_map_mut() + .insert(SyncFromBrokerMetadata::new(last)); + } else { + state + .metadata_map_mut() + .get_mut::() + .unwrap() + .last_id = last; + } + } + + self.client.process(fuzzer, state, executor, manager)?; + #[cfg(feature = "introspection")] + state.introspection_monitor_mut().finish_stage(); + Ok(()) + } + + #[inline] + fn should_restart(&mut self, _state: &mut Self::State) -> Result { + // No restart handling needed - does not execute the target. + Ok(true) + } + + #[inline] + fn clear_progress(&mut self, _state: &mut Self::State) -> Result<(), Error> { + // Not needed - does not execute the target. + Ok(()) + } +} + impl SyncFromBrokerStage where SP: ShMemProvider + 'static,