diff --git a/fuzzers/others/libafl-fuzz/src/afl_stats.rs b/fuzzers/others/libafl-fuzz/src/afl_stats.rs index 527455f2b9..1113d25cb5 100644 --- a/fuzzers/others/libafl-fuzz/src/afl_stats.rs +++ b/fuzzers/others/libafl-fuzz/src/afl_stats.rs @@ -15,7 +15,7 @@ use libafl::{ inputs::UsesInput, mutators::Tokens, observers::MapObserver, - schedulers::{minimizer::IsFavoredMetadata, HasQueueCycles, Scheduler}, + schedulers::{minimizer::IsFavoredMetadata, HasQueueCycles}, stages::{calibrate::UnstableEntriesMetadata, Stage}, state::{HasCorpus, HasExecutions, HasImported, HasStartTime, Stoppable, UsesState}, Error, HasMetadata, HasNamedMetadata, HasScheduler, SerdeAny, @@ -240,7 +240,7 @@ where + HasTestcase, O: MapObserver, C: AsRef + Named, - ::Scheduler: Scheduler + HasQueueCycles, + ::Scheduler: HasQueueCycles, { fn perform( &mut self, diff --git a/fuzzers/others/libafl-fuzz/src/scheduler.rs b/fuzzers/others/libafl-fuzz/src/scheduler.rs index c29c6412c3..0ddf7f137f 100644 --- a/fuzzers/others/libafl-fuzz/src/scheduler.rs +++ b/fuzzers/others/libafl-fuzz/src/scheduler.rs @@ -2,45 +2,39 @@ use std::marker::PhantomData; use libafl::{ corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase}, - inputs::UsesInput, + inputs::{Input, UsesInput}, observers::{CanTrack, ObserversTuple}, schedulers::{ HasQueueCycles, MinimizerScheduler, RemovableScheduler, Scheduler, TestcaseScore, }, - state::{HasCorpus, HasRand, State, UsesState}, + state::{HasCorpus, HasRand, State}, Error, HasMetadata, }; use libafl_bolts::{serdeany::SerdeAny, AsIter, HasRefCnt}; -pub enum SupportedSchedulers { - Queue(Q, PhantomData<(S, Q, CS, F, M, O)>), +pub enum SupportedSchedulers { + Queue(Q, PhantomData<(CS, F, I, M, O, S, Q)>), Weighted( - MinimizerScheduler, - PhantomData<(S, Q, CS, F, M, O)>, + MinimizerScheduler, + PhantomData<(CS, F, I, M, O, S, Q)>, ), } -impl UsesState for SupportedSchedulers +impl RemovableScheduler for SupportedSchedulers where - S: State + HasRand + HasCorpus + HasMetadata + HasTestcase, -{ - type State = S; -} - -impl RemovableScheduler for SupportedSchedulers -where - S: UsesInput + HasTestcase + HasMetadata + HasCorpus + HasRand + State, - Q: Scheduler + RemovableScheduler, - CS: RemovableScheduler, + CS: Scheduler + RemovableScheduler, + F: TestcaseScore, + I: Input, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, O: CanTrack, - F: TestcaseScore, + Q: Scheduler + RemovableScheduler, + S: UsesInput + HasTestcase + HasMetadata + HasCorpus + HasRand + State, { fn on_remove( &mut self, - state: &mut Self::State, + state: &mut S, id: CorpusId, - testcase: &Option::Input>>, + testcase: &Option>, ) -> Result<(), Error> { match self { Self::Queue(queue, _) => queue.on_remove(state, id, testcase), @@ -48,12 +42,7 @@ where } } - fn on_replace( - &mut self, - state: &mut Self::State, - id: CorpusId, - prev: &Testcase<::Input>, - ) -> Result<(), Error> { + fn on_replace(&mut self, state: &mut S, id: CorpusId, prev: &Testcase) -> Result<(), Error> { match self { Self::Queue(queue, _) => queue.on_replace(state, id, prev), Self::Weighted(weighted, _) => weighted.on_replace(state, id, prev), @@ -61,16 +50,17 @@ where } } -impl Scheduler for SupportedSchedulers +impl Scheduler for SupportedSchedulers where - S: UsesInput + HasTestcase + HasMetadata + HasCorpus + HasRand + State, - Q: Scheduler, - CS: Scheduler, + CS: Scheduler, + F: TestcaseScore, + I: Input, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, O: CanTrack, - F: TestcaseScore, + Q: Scheduler, + S: UsesInput + HasTestcase + HasMetadata + HasCorpus + HasRand + State, { - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { match self { // We need to manually set the depth // since we want to avoid implementing `AflScheduler` for `QueueScheduler` @@ -94,20 +84,15 @@ where } /// Gets the next entry in the queue - fn next(&mut self, state: &mut Self::State) -> Result { + fn next(&mut self, state: &mut S) -> Result { match self { Self::Queue(queue, _) => queue.next(state), Self::Weighted(weighted, _) => weighted.next(state), } } - fn on_evaluation( - &mut self, - state: &mut Self::State, - input: &::Input, - observers: &OTB, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, input: &I, observers: &OTB) -> Result<(), Error> where - OTB: ObserversTuple, + OTB: ObserversTuple, { match self { Self::Queue(queue, _) => queue.on_evaluation(state, input, observers), @@ -117,7 +102,7 @@ where fn set_current_scheduled( &mut self, - state: &mut Self::State, + state: &mut S, next_id: Option, ) -> Result<(), Error> { match self { @@ -127,14 +112,16 @@ where } } -impl HasQueueCycles for SupportedSchedulers +impl HasQueueCycles for SupportedSchedulers where - S: UsesInput + HasTestcase + HasMetadata + HasCorpus + HasRand + State, - Q: Scheduler + HasQueueCycles, - CS: Scheduler + HasQueueCycles, - O: CanTrack, + CS: Scheduler + HasQueueCycles, + F: TestcaseScore, + I: Input, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, - F: TestcaseScore, + + O: CanTrack, + Q: Scheduler + HasQueueCycles, + S: UsesInput + HasTestcase + HasMetadata + HasCorpus + HasRand + State, { fn queue_cycles(&self) -> u64 { match self { diff --git a/fuzzers/others/tutorial/src/metadata.rs b/fuzzers/others/tutorial/src/metadata.rs index 2115cdd0b9..25255b2608 100644 --- a/fuzzers/others/tutorial/src/metadata.rs +++ b/fuzzers/others/tutorial/src/metadata.rs @@ -22,7 +22,7 @@ pub struct PacketLenMetadata { pub struct PacketLenTestcaseScore {} -impl TestcaseScore for PacketLenTestcaseScore +impl TestcaseScore for PacketLenTestcaseScore where S: HasCorpus + HasMetadata, { @@ -34,8 +34,8 @@ where } } -pub type PacketLenMinimizerScheduler = - MinimizerScheduler; +pub type PacketLenMinimizerScheduler = + MinimizerScheduler; #[derive(Serialize, Deserialize, Default, Clone, Debug)] pub struct PacketLenFeedback { diff --git a/libafl/src/corpus/minimizer.rs b/libafl/src/corpus/minimizer.rs index 5dce383bfb..5fdb7afedf 100644 --- a/libafl/src/corpus/minimizer.rs +++ b/libafl/src/corpus/minimizer.rs @@ -17,6 +17,7 @@ use crate::{ corpus::Corpus, events::{Event, EventFirer, LogSeverity}, executors::{Executor, HasObservers}, + inputs::UsesInput, monitors::{AggregatorOps, UserStats, UserStatsValue}, observers::{MapObserver, ObserversTuple}, schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, @@ -41,7 +42,7 @@ where ) -> Result<(), Error> where E: Executor + HasObservers, - CS: Scheduler + RemovableScheduler, // schedulers that has on_remove/on_replace only! + CS: Scheduler + RemovableScheduler, // schedulers that has on_remove/on_replace only! EM: EventFirer, Z: HasScheduler; } @@ -56,14 +57,19 @@ pub struct MapCorpusMinimizer { } /// Standard corpus minimizer, which weights inputs by length and time. -pub type StdCorpusMinimizer = - MapCorpusMinimizer::State>>; +pub type StdCorpusMinimizer = MapCorpusMinimizer< + C, + E, + O, + T, + LenTimeMulTestcaseScore<::Input, ::State>, +>; impl MapCorpusMinimizer where E: UsesState, E::State: HasCorpus + HasMetadata, - TS: TestcaseScore, + TS: TestcaseScore, C: Named, { /// Constructs a new `MapCorpusMinimizer` from a provided observer. This observer will be used @@ -83,7 +89,7 @@ where C: AsRef, E::State: HasMetadata + HasCorpus + HasExecutions, T: Copy + Hash + Eq, - TS: TestcaseScore, + TS: TestcaseScore, { #[allow(clippy::too_many_lines)] fn minimize( @@ -95,7 +101,7 @@ where ) -> Result<(), Error> where E: Executor + HasObservers, - CS: Scheduler + RemovableScheduler, + CS: Scheduler + RemovableScheduler, EM: EventFirer, Z: HasScheduler, { diff --git a/libafl/src/executors/inprocess/mod.rs b/libafl/src/executors/inprocess/mod.rs index 72ea126c9c..adbe454af5 100644 --- a/libafl/src/executors/inprocess/mod.rs +++ b/libafl/src/executors/inprocess/mod.rs @@ -560,7 +560,7 @@ mod tests { let mut mgr = NopEventManager::new(); let mut state = StdState::new(rand, corpus, solutions, &mut feedback, &mut objective).unwrap(); - let mut fuzzer = StdFuzzer::<_, _, _>::new(sche, feedback, objective); + let mut fuzzer = StdFuzzer::<_, _, _, _>::new(sche, feedback, objective); let mut in_process_executor = InProcessExecutor::new( &mut harness, diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index 3cdca8fc05..51d40a151a 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -6,6 +6,8 @@ use core::{fmt::Debug, marker::PhantomData, time::Duration}; use libafl_bolts::current_time; use serde::{de::DeserializeOwned, Serialize}; +#[cfg(feature = "introspection")] +use crate::monitors::PerfFeature; use crate::{ corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase}, events::{Event, EventConfig, EventFirer, EventProcessor, ProgressReporter}, @@ -23,8 +25,6 @@ use crate::{ }, Error, HasMetadata, }; -#[cfg(feature = "introspection")] -use crate::{monitors::PerfFeature, state::HasClientPerfMonitor}; /// Send a monitor update all 15 (or more) seconds const STATS_TIMEOUT_DEFAULT: Duration = Duration::from_secs(15); @@ -35,7 +35,7 @@ where Self::State: HasCorpus, { /// The [`Scheduler`] for this fuzzer - type Scheduler: Scheduler; + type Scheduler: Scheduler; /// The scheduler fn scheduler(&self) -> &Self::Scheduler; @@ -303,24 +303,24 @@ pub enum ExecuteInputResult { /// Your default fuzzer instance, for everyday use. #[derive(Debug)] -pub struct StdFuzzer { +pub struct StdFuzzer { scheduler: CS, feedback: F, objective: OF, + phantom: PhantomData, } -impl UsesState for StdFuzzer +impl UsesState for StdFuzzer where - CS: Scheduler, - CS::State: HasCorpus, + S: State, { - type State = CS::State; + type State = S; } -impl HasScheduler for StdFuzzer +impl HasScheduler for StdFuzzer where - CS: Scheduler, - CS::State: HasCorpus, + S: State + HasCorpus, + CS: Scheduler, { type Scheduler = CS; @@ -333,12 +333,11 @@ where } } -impl HasFeedback for StdFuzzer +impl HasFeedback for StdFuzzer where - CS: Scheduler, - F: Feedback, - OF: Feedback, - CS::State: HasCorpus, + S: State, + F: Feedback, + OF: Feedback, { type Feedback = F; @@ -351,12 +350,11 @@ where } } -impl HasObjective for StdFuzzer +impl HasObjective for StdFuzzer where - CS: Scheduler, - F: Feedback, - OF: Feedback, - CS::State: HasCorpus, + S: State, + F: Feedback, + OF: Feedback, { type Objective = OF; @@ -369,23 +367,24 @@ where } } -impl ExecutionProcessor for StdFuzzer +impl ExecutionProcessor for StdFuzzer where - CS: Scheduler, - F: Feedback, - OF: Feedback, - CS::State: HasCorpus + CS: Scheduler, + F: Feedback, + OF: Feedback, + S: HasCorpus + HasSolutions + HasExecutions + HasCorpus - + HasCurrentTestcase<::Input> - + HasCurrentCorpusId, + + HasCurrentTestcase + + HasCurrentCorpusId + + State, { fn check_results( &mut self, - state: &mut Self::State, + state: &mut S, manager: &mut EM, - input: &::Input, + input: &S::Input, observers: &OT, exit_kind: &ExitKind, ) -> Result @@ -590,27 +589,27 @@ where } } -impl EvaluatorObservers for StdFuzzer +impl EvaluatorObservers for StdFuzzer where - CS: Scheduler, - OT: ObserversTuple + Serialize + DeserializeOwned, - F: Feedback, - OF: Feedback, - CS::State: HasCorpus + HasSolutions + HasExecutions, + CS: Scheduler, + OT: ObserversTuple + Serialize + DeserializeOwned, + F: Feedback, + OF: Feedback, + S: HasCorpus + HasSolutions + HasExecutions + State, { /// Process one input, adding to the respective corpora if needed and firing the right events #[inline] fn evaluate_input_with_observers( &mut self, - state: &mut Self::State, + state: &mut S, executor: &mut E, manager: &mut EM, - input: ::Input, + input: S::Input, send_events: bool, ) -> Result<(ExecuteInputResult, Option), Error> where - E: Executor + HasObservers, - EM: EventFirer, + E: Executor + HasObservers, + EM: EventFirer, { let exit_kind = self.execute_input(state, executor, manager, &input)?; let observers = executor.observers(); @@ -621,15 +620,15 @@ where } } -impl Evaluator for StdFuzzer +impl Evaluator for StdFuzzer where - CS: Scheduler, - E: HasObservers + Executor, - EM: EventFirer, - F: Feedback, - OF: Feedback, - OT: ObserversTuple + Serialize + DeserializeOwned, - CS::State: HasCorpus + HasSolutions + HasExecutions + HasLastFoundTime, + CS: Scheduler, + E: HasObservers + Executor, + EM: EventFirer, + F: Feedback, + OF: Feedback, + OT: ObserversTuple + Serialize + DeserializeOwned, + S: HasCorpus + HasSolutions + HasExecutions + HasLastFoundTime + State, { /// Process one input, adding to the respective corpora if needed and firing the right events #[inline] @@ -756,21 +755,22 @@ where } } -impl Fuzzer for StdFuzzer +impl Fuzzer for StdFuzzer where - CS: Scheduler, - E: UsesState, - EM: ProgressReporter + EventProcessor, - F: Feedback, - OF: Feedback, - CS::State: HasExecutions + CS: Scheduler, + E: UsesState, + EM: ProgressReporter + EventProcessor, + F: Feedback, + OF: Feedback, + S: HasExecutions + HasMetadata + HasCorpus + HasTestcase + HasLastReportTime + HasCurrentCorpusId - + HasCurrentStageId, - ST: StagesTuple, + + HasCurrentStageId + + State, + ST: StagesTuple, { fn fuzz_one( &mut self, @@ -834,12 +834,12 @@ where } } -impl StdFuzzer +impl StdFuzzer where - CS: Scheduler, + CS: Scheduler, F: Feedback<::State>, OF: Feedback<::State>, - CS::State: UsesInput + HasExecutions + HasCorpus, + S: UsesInput + HasExecutions + HasCorpus + State, { /// Create a new `StdFuzzer` with standard behavior. pub fn new(scheduler: CS, feedback: F, objective: OF) -> Self { @@ -847,6 +847,7 @@ where scheduler, feedback, objective, + phantom: PhantomData, } } @@ -896,22 +897,22 @@ where ) -> Result; } -impl ExecutesInput for StdFuzzer +impl ExecutesInput for StdFuzzer where - CS: Scheduler, + CS: Scheduler, F: Feedback<::State>, OF: Feedback<::State>, E: Executor + HasObservers, EM: UsesState, - CS::State: UsesInput + HasExecutions + HasCorpus, + S: UsesInput + HasExecutions + HasCorpus + State, { /// Runs the input and triggers observers and feedback fn execute_input( &mut self, - state: &mut ::State, + state: &mut S, executor: &mut E, event_mgr: &mut EM, - input: &<::State as UsesInput>::Input, + input: &S::Input, ) -> Result { start_timer!(state); executor.observers_mut().pre_exec_all(state, input)?; diff --git a/libafl/src/schedulers/accounting.rs b/libafl/src/schedulers/accounting.rs index dd313a6fa8..6c8b1f8d3c 100644 --- a/libafl/src/schedulers/accounting.rs +++ b/libafl/src/schedulers/accounting.rs @@ -13,13 +13,13 @@ use serde::{Deserialize, Serialize}; use crate::{ corpus::{Corpus, CorpusId}, feedbacks::MapIndexesMetadata, - inputs::UsesInput, + inputs::Input, observers::{CanTrack, ObserversTuple}, schedulers::{ minimizer::{IsFavoredMetadata, MinimizerScheduler, DEFAULT_SKIP_NON_FAVORED_PROB}, LenTimeMulTestcaseScore, Scheduler, }, - state::{HasCorpus, HasRand, UsesState}, + state::{HasCorpus, HasRand}, Error, HasMetadata, }; @@ -105,55 +105,32 @@ impl TopAccountingMetadata { /// A minimizer scheduler using coverage accounting #[derive(Debug)] -pub struct CoverageAccountingScheduler<'a, CS, O> -where - CS: UsesState, - CS::State: Debug, -{ +pub struct CoverageAccountingScheduler<'a, CS, I, O, S> { accounting_map: &'a [u32], skip_non_favored_prob: f64, - inner: MinimizerScheduler< - CS, - LenTimeMulTestcaseScore<::State>, - MapIndexesMetadata, - O, - >, + inner: MinimizerScheduler, I, MapIndexesMetadata, O, S>, } -impl<'a, CS, O> UsesState for CoverageAccountingScheduler<'a, CS, O> +impl<'a, CS, I, O, S> Scheduler for CoverageAccountingScheduler<'a, CS, I, O, S> where - CS: UsesState, - CS::State: Debug, -{ - type State = CS::State; -} - -impl<'a, CS, O> Scheduler for CoverageAccountingScheduler<'a, CS, O> -where - CS: Scheduler, - Self::State: HasCorpus + HasMetadata + HasRand, - CS::State: Debug, - ::Input: HasLen, + CS: Scheduler, + S: HasCorpus + HasMetadata + HasRand + Debug, + I: HasLen + Input, O: CanTrack, { - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { self.update_accounting_score(state, id)?; self.inner.on_add(state, id) } - fn on_evaluation( - &mut self, - state: &mut Self::State, - input: &::Input, - observers: &OT, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error> where - OT: ObserversTuple, + OT: ObserversTuple, { self.inner.on_evaluation(state, input, observers) } - fn next(&mut self, state: &mut Self::State) -> Result { + fn next(&mut self, state: &mut S) -> Result { if state .metadata_map() .get::() @@ -184,7 +161,7 @@ where /// Set current fuzzed corpus id and `scheduled_count` fn set_current_scheduled( &mut self, - _state: &mut Self::State, + _state: &mut S, _next_id: Option, ) -> Result<(), Error> { // We do nothing here, the inner scheduler will take care of it @@ -192,21 +169,17 @@ where } } -impl<'a, CS, O> CoverageAccountingScheduler<'a, CS, O> +impl<'a, CS, I, O, S> CoverageAccountingScheduler<'a, CS, I, O, S> where - CS: Scheduler, - CS::State: HasCorpus + HasMetadata + HasRand + Debug, - ::Input: HasLen, + CS: Scheduler, + S: HasCorpus + HasMetadata + HasRand + Debug, + I: HasLen + Input, O: CanTrack, { /// Update the `Corpus` score #[allow(clippy::unused_self)] #[allow(clippy::cast_possible_wrap)] - pub fn update_accounting_score( - &self, - state: &mut CS::State, - id: CorpusId, - ) -> Result<(), Error> { + pub fn update_accounting_score(&self, state: &mut S, id: CorpusId) -> Result<(), Error> { let mut indexes = vec![]; let mut new_favoreds = vec![]; { @@ -291,7 +264,7 @@ where /// Cull the `Corpus` #[allow(clippy::unused_self)] - pub fn accounting_cull(&self, state: &CS::State) -> Result<(), Error> { + pub fn accounting_cull(&self, state: &S) -> Result<(), Error> { let Some(top_rated) = state.metadata_map().get::() else { return Ok(()); }; @@ -312,7 +285,7 @@ where /// and has a default probability to skip non-faved Testcases of [`DEFAULT_SKIP_NON_FAVORED_PROB`]. /// /// Provide the observer responsible for determining new indexes. - pub fn new(observer: &O, state: &mut CS::State, base: CS, accounting_map: &'a [u32]) -> Self { + pub fn new(observer: &O, state: &mut S, base: CS, accounting_map: &'a [u32]) -> Self { match state.metadata_map().get::() { Some(meta) => { if meta.max_accounting.len() != accounting_map.len() { @@ -336,7 +309,7 @@ where /// Provide the observer responsible for determining new indexes. pub fn with_skip_prob( observer: &O, - state: &mut CS::State, + state: &mut S, base: CS, skip_non_favored_prob: f64, accounting_map: &'a [u32], diff --git a/libafl/src/schedulers/minimizer.rs b/libafl/src/schedulers/minimizer.rs index fd53cd8d51..0232866f5b 100644 --- a/libafl/src/schedulers/minimizer.rs +++ b/libafl/src/schedulers/minimizer.rs @@ -11,11 +11,11 @@ use serde::{Deserialize, Serialize}; use crate::{ corpus::{Corpus, CorpusId, Testcase}, feedbacks::MapIndexesMetadata, - inputs::UsesInput, + inputs::Input, observers::{CanTrack, ObserversTuple}, require_index_tracking, schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, - state::{HasCorpus, HasRand, UsesState}, + state::{HasCorpus, HasRand}, Error, HasMetadata, }; @@ -72,34 +72,28 @@ impl Default for TopRatedsMetadata { /// /// E.g., it can use all the coverage seen so far to prioritize [`Testcase`]`s` using a [`TestcaseScore`]. #[derive(Debug, Clone)] -pub struct MinimizerScheduler { +pub struct MinimizerScheduler { base: CS, skip_non_favored_prob: f64, remove_metadata: bool, - phantom: PhantomData<(F, M, O)>, + phantom: PhantomData<(F, I, M, O, S)>, } -impl UsesState for MinimizerScheduler +impl RemovableScheduler for MinimizerScheduler where - CS: UsesState, -{ - type State = CS::State; -} - -impl RemovableScheduler for MinimizerScheduler -where - CS: RemovableScheduler, - F: TestcaseScore<::State>, + CS: RemovableScheduler + Scheduler, + I: Input, + F: TestcaseScore, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, - ::State: HasCorpus + HasMetadata + HasRand, + S: HasCorpus + HasMetadata + HasRand, O: CanTrack, { /// Replaces the [`Testcase`] at the given [`CorpusId`] fn on_replace( &mut self, - state: &mut ::State, + state: &mut S, id: CorpusId, - testcase: &Testcase<<::State as UsesInput>::Input>, + testcase: &Testcase, ) -> Result<(), Error> { self.base.on_replace(state, id, testcase)?; self.update_score(state, id) @@ -108,9 +102,9 @@ where /// Removes an entry from the corpus fn on_remove( &mut self, - state: &mut ::State, + state: &mut S, id: CorpusId, - testcase: &Option::State as UsesInput>::Input>>, + testcase: &Option>, ) -> Result<(), Error> { self.base.on_remove(state, id, testcase)?; let mut entries = @@ -194,35 +188,31 @@ where } } -impl Scheduler for MinimizerScheduler +impl Scheduler for MinimizerScheduler where - CS: Scheduler, - F: TestcaseScore, + CS: Scheduler, + F: TestcaseScore, + I: Input, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, - Self::State: HasCorpus + HasMetadata + HasRand, + S: HasCorpus + HasMetadata + HasRand, O: CanTrack, { /// Called when a [`Testcase`] is added to the corpus - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { self.base.on_add(state, id)?; self.update_score(state, id) } /// An input has been evaluated - fn on_evaluation( - &mut self, - state: &mut Self::State, - input: &::Input, - observers: &OT, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error> where - OT: ObserversTuple, + OT: ObserversTuple, { self.base.on_evaluation(state, input, observers) } /// Gets the next entry - fn next(&mut self, state: &mut Self::State) -> Result { + fn next(&mut self, state: &mut S) -> Result { self.cull(state)?; let mut id = self.base.next(state)?; while { @@ -242,7 +232,7 @@ where /// Set current fuzzed corpus id and `scheduled_count` fn set_current_scheduled( &mut self, - _state: &mut Self::State, + _state: &mut S, _next_id: Option, ) -> Result<(), Error> { // We do nothing here, the inner scheduler will take care of it @@ -250,22 +240,19 @@ where } } -impl MinimizerScheduler +impl MinimizerScheduler where - CS: Scheduler, - F: TestcaseScore<::State>, + CS: Scheduler, + F: TestcaseScore, + I: Input, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, - ::State: HasCorpus + HasMetadata + HasRand, + S: HasCorpus + HasMetadata + HasRand, O: CanTrack, { /// Update the [`Corpus`] score using the [`MinimizerScheduler`] #[allow(clippy::unused_self)] #[allow(clippy::cast_possible_wrap)] - pub fn update_score( - &self, - state: &mut ::State, - id: CorpusId, - ) -> Result<(), Error> { + pub fn update_score(&self, state: &mut S, id: CorpusId) -> Result<(), Error> { // Create a new top rated meta if not existing if state.metadata_map().get::().is_none() { state.add_metadata(TopRatedsMetadata::new()); @@ -339,7 +326,7 @@ where /// Cull the [`Corpus`] using the [`MinimizerScheduler`] #[allow(clippy::unused_self)] - pub fn cull(&self, state: &::State) -> Result<(), Error> { + pub fn cull(&self, state: &S) -> Result<(), Error> { let Some(top_rated) = state.metadata_map().get::() else { return Ok(()); }; @@ -423,14 +410,10 @@ where } /// A [`MinimizerScheduler`] with [`LenTimeMulTestcaseScore`] to prioritize quick and small [`Testcase`]`s`. -pub type LenTimeMinimizerScheduler = - MinimizerScheduler::State>, M, O>; +pub type LenTimeMinimizerScheduler = + MinimizerScheduler, I, M, O, S>; /// A [`MinimizerScheduler`] with [`LenTimeMulTestcaseScore`] to prioritize quick and small [`Testcase`]`s` /// that exercise all the entries registered in the [`MapIndexesMetadata`]. -pub type IndexesLenTimeMinimizerScheduler = MinimizerScheduler< - CS, - LenTimeMulTestcaseScore<::State>, - MapIndexesMetadata, - O, ->; +pub type IndexesLenTimeMinimizerScheduler = + MinimizerScheduler, I, MapIndexesMetadata, O, S>; diff --git a/libafl/src/schedulers/mod.rs b/libafl/src/schedulers/mod.rs index 37022adc63..7b7744a441 100644 --- a/libafl/src/schedulers/mod.rs +++ b/libafl/src/schedulers/mod.rs @@ -35,25 +35,25 @@ pub use tuneable::*; use crate::{ corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase}, - inputs::UsesInput, + inputs::Input, observers::{MapObserver, ObserversTuple}, random_corpus_id, - state::{HasCorpus, HasRand, State, UsesState}, + state::{HasCorpus, HasRand, State}, Error, HasMetadata, }; /// The scheduler also implements `on_remove` and `on_replace` if it implements this stage. -pub trait RemovableScheduler: Scheduler +pub trait RemovableScheduler where - Self::State: HasCorpus, + I: Input, { /// Removed the given entry from the corpus at the given index /// When you remove testcases, make sure that that testcase is not currently fuzzed one! fn on_remove( &mut self, - _state: &mut Self::State, + _state: &mut S, _id: CorpusId, - _testcase: &Option::Input>>, + _testcase: &Option>, ) -> Result<(), Error> { Ok(()) } @@ -61,21 +61,23 @@ where /// Replaced the given testcase at the given idx fn on_replace( &mut self, - _state: &mut Self::State, + _state: &mut S, _id: CorpusId, - _prev: &Testcase<::Input>, + _prev: &Testcase, ) -> Result<(), Error> { Ok(()) } } /// Defines the common metadata operations for the AFL-style schedulers -pub trait AflScheduler: Scheduler +pub trait AflScheduler where - Self::State: HasCorpus + HasMetadata + HasTestcase, + S: HasCorpus + HasMetadata + HasTestcase, O: MapObserver, - C: AsRef, { + /// The type of [`MapObserver`] that this scheduler will use as reference + type MapObserverRef: AsRef; + /// Return the last hash fn last_hash(&self) -> usize; @@ -83,10 +85,10 @@ where fn set_last_hash(&mut self, value: usize); /// Get the observer map observer name - fn map_observer_handle(&self) -> &Handle; + fn map_observer_handle(&self) -> &Handle; /// Called when a [`Testcase`] is added to the corpus - fn on_add_metadata(&self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add_metadata(&self, state: &mut S, id: CorpusId) -> Result<(), Error> { let current_id = *state.corpus().current(); let mut depth = match current_id { @@ -114,12 +116,12 @@ where /// Called when a [`Testcase`] is evaluated fn on_evaluation_metadata( &mut self, - state: &mut Self::State, - _input: &::Input, + state: &mut S, + _input: &I, observers: &OT, ) -> Result<(), Error> where - OT: ObserversTuple, + OT: ObserversTuple, { let observer = observers .get(self.map_observer_handle()) @@ -140,11 +142,7 @@ where } /// Called when choosing the next [`Testcase`] - fn on_next_metadata( - &mut self, - state: &mut Self::State, - _next_id: Option, - ) -> Result<(), Error> { + fn on_next_metadata(&mut self, state: &mut S, _next_id: Option) -> Result<(), Error> { let current_id = *state.corpus().current(); if let Some(id) = current_id { @@ -163,45 +161,42 @@ where } /// Trait for Schedulers which track queue cycles -pub trait HasQueueCycles: Scheduler -where - Self::State: HasCorpus, -{ +pub trait HasQueueCycles { /// The amount of cycles the scheduler has completed. fn queue_cycles(&self) -> u64; } /// The scheduler define how the fuzzer requests a testcase from the corpus. /// It has hooks to corpus add/replace/remove to allow complex scheduling algorithms to collect data. -pub trait Scheduler: UsesState +pub trait Scheduler where - Self::State: HasCorpus, + S: HasCorpus, { /// Called when a [`Testcase`] is added to the corpus - fn on_add(&mut self, _state: &mut Self::State, _id: CorpusId) -> Result<(), Error>; + fn on_add(&mut self, _state: &mut S, _id: CorpusId) -> Result<(), Error>; // Add parent_id here if it has no inner /// An input has been evaluated fn on_evaluation( &mut self, - _state: &mut Self::State, - _input: &::Input, + _state: &mut S, + _input: &I, _observers: &OT, ) -> Result<(), Error> where - OT: ObserversTuple, + OT: ObserversTuple, { Ok(()) } /// Gets the next entry - fn next(&mut self, state: &mut Self::State) -> Result; + fn next(&mut self, state: &mut S) -> Result; // Increment corpus.current() here if it has no inner /// Set current fuzzed corpus id and `scheduled_count` fn set_current_scheduled( &mut self, - state: &mut Self::State, + state: &mut S, next_id: Option, ) -> Result<(), Error> { *state.corpus_mut().current_mut() = next_id; @@ -215,18 +210,11 @@ pub struct RandScheduler { phantom: PhantomData, } -impl UsesState for RandScheduler -where - S: State + HasTestcase, -{ - type State = S; -} - -impl Scheduler for RandScheduler +impl Scheduler for RandScheduler where S: HasCorpus + HasRand + HasTestcase + State, { - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { // Set parent id let current_id = *state.corpus().current(); state @@ -239,7 +227,7 @@ where } /// Gets the next entry at random - fn next(&mut self, state: &mut Self::State) -> Result { + fn next(&mut self, state: &mut S) -> Result { if state.corpus().count() == 0 { Err(Error::empty( "No entries in corpus. This often implies the target is not properly instrumented." @@ -247,7 +235,7 @@ where )) } else { let id = random_corpus_id!(state.corpus(), state.rand_mut()); - self.set_current_scheduled(state, Some(id))?; + >::set_current_scheduled(self, state, Some(id))?; Ok(id) } } diff --git a/libafl/src/schedulers/powersched.rs b/libafl/src/schedulers/powersched.rs index f85391a2fa..5de71076c0 100644 --- a/libafl/src/schedulers/powersched.rs +++ b/libafl/src/schedulers/powersched.rs @@ -11,10 +11,10 @@ use serde::{Deserialize, Serialize}; use crate::{ corpus::{Corpus, CorpusId, HasTestcase, Testcase}, - inputs::UsesInput, + inputs::Input, observers::{MapObserver, ObserversTuple}, schedulers::{AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler}, - state::{HasCorpus, State, UsesState}, + state::{HasCorpus, State}, Error, HasMetadata, }; @@ -271,33 +271,27 @@ pub enum BaseSchedule { /// Note that this corpus is merely holding the metadata necessary for the power calculation /// and here we DON'T actually calculate the power (we do it in the stage) #[derive(Clone, Debug)] -pub struct PowerQueueScheduler { +pub struct PowerQueueScheduler { queue_cycles: u64, strat: PowerSchedule, map_observer_handle: Handle, last_hash: usize, - phantom: PhantomData<(O, S)>, + phantom: PhantomData<(I, O, S)>, } -impl UsesState for PowerQueueScheduler -where - S: State, -{ - type State = S; -} - -impl RemovableScheduler for PowerQueueScheduler +impl RemovableScheduler for PowerQueueScheduler where S: State + HasTestcase + HasMetadata + HasCorpus, O: MapObserver, C: AsRef, + I: Input, { /// This will *NOT* neutralize the effect of this removed testcase from the global data such as `SchedulerMetadata` fn on_remove( &mut self, - _state: &mut Self::State, + _state: &mut S, _id: CorpusId, - _prev: &Option::Input>>, + _prev: &Option>, ) -> Result<(), Error> { Ok(()) } @@ -305,20 +299,22 @@ where /// This will *NOT* neutralize the effect of this removed testcase from the global data such as `SchedulerMetadata` fn on_replace( &mut self, - _state: &mut Self::State, + _state: &mut S, _id: CorpusId, - _prev: &Testcase<::Input>, + _prev: &Testcase, ) -> Result<(), Error> { Ok(()) } } -impl AflScheduler for PowerQueueScheduler +impl AflScheduler for PowerQueueScheduler where S: HasCorpus + HasMetadata + HasTestcase + State, O: MapObserver, C: AsRef, { + type MapObserverRef = C; + fn last_hash(&self) -> usize { self.last_hash } @@ -332,7 +328,7 @@ where } } -impl HasQueueCycles for PowerQueueScheduler +impl HasQueueCycles for PowerQueueScheduler where S: HasCorpus + HasMetadata + HasTestcase + State, O: MapObserver, @@ -343,30 +339,25 @@ where } } -impl Scheduler for PowerQueueScheduler +impl Scheduler for PowerQueueScheduler where S: HasCorpus + HasMetadata + HasTestcase + State, O: MapObserver, C: AsRef, { /// Called when a [`Testcase`] is added to the corpus - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { - self.on_add_metadata(state, id) + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { + >::on_add_metadata(self, state, id) } - fn on_evaluation( - &mut self, - state: &mut Self::State, - input: &::Input, - observers: &OT, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error> where - OT: ObserversTuple, + OT: ObserversTuple, { self.on_evaluation_metadata(state, input, observers) } - fn next(&mut self, state: &mut Self::State) -> Result { + fn next(&mut self, state: &mut S) -> Result { if state.corpus().count() == 0 { Err(Error::empty( "No entries in corpus. This often implies the target is not properly instrumented.", @@ -394,17 +385,17 @@ where /// Set current fuzzed corpus id and `scheduled_count` fn set_current_scheduled( &mut self, - state: &mut Self::State, + state: &mut S, next_id: Option, ) -> Result<(), Error> { - self.on_next_metadata(state, next_id)?; + >::on_next_metadata(self, state, next_id)?; *state.corpus_mut().current_mut() = next_id; Ok(()) } } -impl PowerQueueScheduler +impl PowerQueueScheduler where S: HasMetadata, O: MapObserver, diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs index 552e81f754..41d7207ddd 100644 --- a/libafl/src/schedulers/probabilistic_sampling.rs +++ b/libafl/src/schedulers/probabilistic_sampling.rs @@ -10,19 +10,16 @@ use serde::{Deserialize, Serialize}; use crate::{ corpus::{Corpus, CorpusId, HasTestcase, Testcase}, - inputs::UsesInput, + inputs::Input, schedulers::{RemovableScheduler, Scheduler, TestcaseScore}, - state::{HasCorpus, HasRand, State, UsesState}, + state::{HasCorpus, HasRand, State}, Error, HasMetadata, }; /// Conduct reservoir sampling (probabilistic sampling) over all corpus elements. #[derive(Debug, Clone)] -pub struct ProbabilitySamplingScheduler -where - S: UsesInput, -{ - phantom: PhantomData<(F, S)>, +pub struct ProbabilitySamplingScheduler { + phantom: PhantomData<(F, I, S)>, } /// A state metadata holding a map of probability of corpus elements. @@ -57,10 +54,11 @@ impl Default for ProbabilityMetadata { } } -impl ProbabilitySamplingScheduler +impl ProbabilitySamplingScheduler where - F: TestcaseScore, - S: HasCorpus + HasMetadata + HasRand, + F: TestcaseScore, + I: Input, + S: HasCorpus + HasMetadata + HasRand, { /// Creates a new [`struct@ProbabilitySamplingScheduler`] #[must_use] @@ -89,16 +87,17 @@ where } } -impl RemovableScheduler for ProbabilitySamplingScheduler +impl RemovableScheduler for ProbabilitySamplingScheduler where - F: TestcaseScore, - S: HasCorpus + HasMetadata + HasRand + HasTestcase + State, + F: TestcaseScore, + I: Input, + S: HasCorpus + HasMetadata + HasRand + HasTestcase + State, { fn on_remove( &mut self, - state: &mut Self::State, + state: &mut S, id: CorpusId, - _testcase: &Option::Input>>, + _testcase: &Option>, ) -> Result<(), Error> { let meta = state .metadata_map_mut() @@ -112,9 +111,9 @@ where fn on_replace( &mut self, - state: &mut Self::State, + state: &mut S, id: CorpusId, - _prev: &Testcase<::Input>, + _prev: &Testcase, ) -> Result<(), Error> { let meta = state .metadata_map_mut() @@ -128,19 +127,13 @@ where } } -impl UsesState for ProbabilitySamplingScheduler +impl Scheduler for ProbabilitySamplingScheduler where - S: State + HasTestcase, + F: TestcaseScore, + I: Input, + S: HasCorpus + HasMetadata + HasRand + HasTestcase + State, { - type State = S; -} - -impl Scheduler for ProbabilitySamplingScheduler -where - F: TestcaseScore, - S: HasCorpus + HasMetadata + HasRand + HasTestcase + State, -{ - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { let current_id = *state.corpus().current(); state .corpus() @@ -156,7 +149,7 @@ where /// Gets the next entry #[allow(clippy::cast_precision_loss)] - fn next(&mut self, state: &mut Self::State) -> Result { + fn next(&mut self, state: &mut S) -> Result { if state.corpus().count() == 0 { Err(Error::empty(String::from( "No entries in corpus. This often implies the target is not properly instrumented.", @@ -180,10 +173,11 @@ where } } -impl Default for ProbabilitySamplingScheduler +impl Default for ProbabilitySamplingScheduler where - F: TestcaseScore, - S: HasCorpus + HasMetadata + HasRand, + F: TestcaseScore, + I: Input, + S: HasCorpus + HasMetadata + HasRand, { fn default() -> Self { Self::new() @@ -200,7 +194,7 @@ mod tests { use crate::{ corpus::{Corpus, InMemoryCorpus, Testcase}, feedbacks::ConstFeedback, - inputs::{bytes::BytesInput, Input, UsesInput}, + inputs::{bytes::BytesInput, Input}, schedulers::{ProbabilitySamplingScheduler, Scheduler, TestcaseScore}, state::{HasCorpus, StdState}, Error, HasMetadata, @@ -216,17 +210,18 @@ mod tests { phantom: PhantomData, } - impl TestcaseScore for UniformDistribution + impl TestcaseScore for UniformDistribution where S: HasMetadata + HasCorpus, + I: Input, { - fn compute(_state: &S, _: &mut Testcase) -> Result { + fn compute(_state: &S, _: &mut Testcase) -> Result { Ok(FACTOR) } } - pub type UniformProbabilitySamplingScheduler = - ProbabilitySamplingScheduler::Input>, S>; + pub type UniformProbabilitySamplingScheduler = + ProbabilitySamplingScheduler, I, S>; #[test] fn test_prob_sampling() { @@ -240,7 +235,8 @@ mod tests { // the first 3 probabilities will be .76, .86, .36 let rand = StdRand::with_seed(2); - let mut scheduler = UniformProbabilitySamplingScheduler::new(); + let mut scheduler: ProbabilitySamplingScheduler<_, BytesInput, _> = + UniformProbabilitySamplingScheduler::new(); let mut feedback = ConstFeedback::new(false); let mut objective = ConstFeedback::new(false); diff --git a/libafl/src/schedulers/queue.rs b/libafl/src/schedulers/queue.rs index ad0bad693c..605c1940e9 100644 --- a/libafl/src/schedulers/queue.rs +++ b/libafl/src/schedulers/queue.rs @@ -5,33 +5,27 @@ use core::marker::PhantomData; use crate::{ corpus::{Corpus, CorpusId, HasTestcase}, + inputs::Input, schedulers::{HasQueueCycles, RemovableScheduler, Scheduler}, - state::{HasCorpus, State, UsesState}, + state::{HasCorpus, State}, Error, }; /// Walk the corpus in a queue-like fashion #[derive(Debug, Clone)] -pub struct QueueScheduler { +pub struct QueueScheduler { queue_cycles: u64, runs_in_current_cycle: u64, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl UsesState for QueueScheduler -where - S: State, -{ - type State = S; -} +impl RemovableScheduler for QueueScheduler where I: Input {} -impl RemovableScheduler for QueueScheduler where S: HasCorpus + HasTestcase + State {} - -impl Scheduler for QueueScheduler +impl Scheduler for QueueScheduler where S: HasCorpus + HasTestcase + State, { - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { // Set parent id let current_id = *state.corpus().current(); state @@ -44,7 +38,7 @@ where } /// Gets the next entry in the queue - fn next(&mut self, state: &mut Self::State) -> Result { + fn next(&mut self, state: &mut S) -> Result { if state.corpus().count() == 0 { Err(Error::empty( "No entries in corpus. This often implies the target is not properly instrumented." @@ -69,7 +63,7 @@ where } } -impl QueueScheduler { +impl QueueScheduler { /// Creates a new `QueueScheduler` #[must_use] pub fn new() -> Self { @@ -81,16 +75,13 @@ impl QueueScheduler { } } -impl Default for QueueScheduler { +impl Default for QueueScheduler { fn default() -> Self { Self::new() } } -impl HasQueueCycles for QueueScheduler -where - S: HasCorpus + HasTestcase + State, -{ +impl HasQueueCycles for QueueScheduler { fn queue_cycles(&self) -> u64 { self.queue_cycles } @@ -115,7 +106,7 @@ mod tests { #[test] fn test_queuecorpus() { let rand = StdRand::with_seed(4); - let mut scheduler = QueueScheduler::new(); + let mut scheduler: QueueScheduler = QueueScheduler::new(); let mut q = OnDiskCorpus::::new(PathBuf::from("target/.test/fancy/path")).unwrap(); diff --git a/libafl/src/schedulers/testcase_score.rs b/libafl/src/schedulers/testcase_score.rs index 31d1fc0c93..d11404d3a2 100644 --- a/libafl/src/schedulers/testcase_score.rs +++ b/libafl/src/schedulers/testcase_score.rs @@ -7,6 +7,7 @@ use libafl_bolts::{HasLen, HasRefCnt}; use crate::{ corpus::{Corpus, SchedulerTestcaseMetadata, Testcase}, feedbacks::MapIndexesMetadata, + inputs::Input, schedulers::{ minimizer::{IsFavoredMetadata, TopRatedsMetadata}, powersched::{BaseSchedule, SchedulerMetadata}, @@ -16,28 +17,29 @@ use crate::{ }; /// Compute the favor factor of a [`Testcase`]. Higher is better. -pub trait TestcaseScore +pub trait TestcaseScore where S: HasMetadata + HasCorpus, + I: Input, { /// Computes the favor factor of a [`Testcase`]. Higher is better. - fn compute(state: &S, entry: &mut Testcase) -> Result; + fn compute(state: &S, entry: &mut Testcase) -> Result; } /// Multiply the testcase size with the execution time. /// This favors small and quick testcases. #[derive(Debug, Clone)] -pub struct LenTimeMulTestcaseScore { - phantom: PhantomData, +pub struct LenTimeMulTestcaseScore { + phantom: PhantomData<(I, S)>, } -impl TestcaseScore for LenTimeMulTestcaseScore +impl TestcaseScore for LenTimeMulTestcaseScore where - S: HasCorpus + HasMetadata, - S::Input: HasLen, + S: HasCorpus + HasMetadata, + I: HasLen + Input, { #[allow(clippy::cast_precision_loss, clippy::cast_lossless)] - fn compute(state: &S, entry: &mut Testcase) -> Result { + fn compute(state: &S, entry: &mut Testcase) -> Result { // TODO maybe enforce entry.exec_time().is_some() Ok(entry.exec_time().map_or(1, |d| d.as_millis()) as f64 * entry.load_len(state.corpus())? as f64) @@ -56,9 +58,10 @@ pub struct CorpusPowerTestcaseScore { phantom: PhantomData, } -impl TestcaseScore for CorpusPowerTestcaseScore +impl TestcaseScore for CorpusPowerTestcaseScore where S: HasCorpus + HasMetadata, + I: Input, { /// Compute the `power` we assign to each corpus entry #[allow( @@ -67,7 +70,7 @@ where clippy::cast_sign_loss, clippy::cast_lossless )] - fn compute(state: &S, entry: &mut Testcase) -> Result { + fn compute(state: &S, entry: &mut Testcase) -> Result { let psmeta = state.metadata::()?; let fuzz_mu = if let Some(strat) = psmeta.strat() { @@ -277,13 +280,14 @@ pub struct CorpusWeightTestcaseScore { phantom: PhantomData, } -impl TestcaseScore for CorpusWeightTestcaseScore +impl TestcaseScore for CorpusWeightTestcaseScore where S: HasCorpus + HasMetadata, + I: Input, { /// Compute the `weight` used in weighted corpus entry selection algo #[allow(clippy::cast_precision_loss, clippy::cast_lossless)] - fn compute(state: &S, entry: &mut Testcase) -> Result { + fn compute(state: &S, entry: &mut Testcase) -> Result { let mut weight = 1.0; let psmeta = state.metadata::()?; diff --git a/libafl/src/schedulers/tuneable.rs b/libafl/src/schedulers/tuneable.rs index 8424261ebb..d744be4266 100644 --- a/libafl/src/schedulers/tuneable.rs +++ b/libafl/src/schedulers/tuneable.rs @@ -11,8 +11,9 @@ use serde::{Deserialize, Serialize}; use super::RemovableScheduler; use crate::{ corpus::{Corpus, CorpusId, HasTestcase}, + inputs::Input, schedulers::Scheduler, - state::{HasCorpus, State, UsesState}, + state::{HasCorpus, State}, Error, HasMetadata, }; @@ -30,11 +31,11 @@ impl_serdeany!(TuneableSchedulerMetadata); /// Walk the corpus in a queue-like fashion /// With the specific `set_next` method, we can chose the next corpus entry manually #[derive(Debug, Clone)] -pub struct TuneableScheduler { - phantom: PhantomData, +pub struct TuneableScheduler { + phantom: PhantomData<(I, S)>, } -impl TuneableScheduler +impl TuneableScheduler where S: HasMetadata + HasCorpus, { @@ -88,23 +89,13 @@ where } } -impl UsesState for TuneableScheduler -where - S: State, -{ - type State = S; -} +impl RemovableScheduler for TuneableScheduler where I: Input {} -impl RemovableScheduler for TuneableScheduler where - S: HasCorpus + HasMetadata + HasTestcase + State -{ -} - -impl Scheduler for TuneableScheduler +impl Scheduler for TuneableScheduler where S: HasCorpus + HasMetadata + HasTestcase + State, { - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { // Set parent id let current_id = *state.corpus().current(); state @@ -117,7 +108,7 @@ where } /// Gets the next entry in the queue - fn next(&mut self, state: &mut Self::State) -> Result { + fn next(&mut self, state: &mut S) -> Result { if state.corpus().count() == 0 { return Err(Error::empty( "No entries in corpus. This often implies the target is not properly instrumented." diff --git a/libafl/src/schedulers/weighted.rs b/libafl/src/schedulers/weighted.rs index 83fe746b3e..4e73da31c4 100644 --- a/libafl/src/schedulers/weighted.rs +++ b/libafl/src/schedulers/weighted.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize}; use super::powersched::PowerSchedule; use crate::{ corpus::{Corpus, CorpusId, HasTestcase, Testcase}, - inputs::UsesInput, + inputs::Input, observers::{MapObserver, ObserversTuple}, random_corpus_id, schedulers::{ @@ -24,7 +24,7 @@ use crate::{ testcase_score::{CorpusWeightTestcaseScore, TestcaseScore}, AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler, }, - state::{HasCorpus, HasRand, State, UsesState}, + state::{HasCorpus, HasRand, State}, Error, HasMetadata, }; @@ -98,22 +98,23 @@ libafl_bolts::impl_serdeany!(WeightedScheduleMetadata); /// A corpus scheduler using power schedules with weighted queue item selection algo. #[derive(Clone, Debug)] -pub struct WeightedScheduler { +pub struct WeightedScheduler { table_invalidated: bool, strat: Option, map_observer_handle: Handle, last_hash: usize, queue_cycles: u64, - phantom: PhantomData<(F, O, S)>, + phantom: PhantomData<(F, I, O, S)>, /// Cycle `PowerSchedule` on completion of every queue cycle. cycle_schedules: bool, } -impl WeightedScheduler +impl WeightedScheduler where - F: TestcaseScore, + F: TestcaseScore, + I: Input, O: MapObserver, - S: HasCorpus + HasMetadata + HasRand, + S: HasCorpus + HasMetadata + HasRand, C: AsRef + Named, { /// Create a new [`WeightedScheduler`] without any power schedule @@ -257,26 +258,20 @@ where } } -impl UsesState for WeightedScheduler +impl RemovableScheduler for WeightedScheduler where - S: State, -{ - type State = S; -} - -impl RemovableScheduler for WeightedScheduler -where - F: TestcaseScore, + F: TestcaseScore, O: MapObserver, + I: Input, S: HasCorpus + HasMetadata + HasRand + HasTestcase + State, C: AsRef + Named, { /// This will *NOT* neutralize the effect of this removed testcase from the global data such as `SchedulerMetadata` fn on_remove( &mut self, - _state: &mut Self::State, + _state: &mut S, _id: CorpusId, - _prev: &Option::Input>>, + _prev: &Option>, ) -> Result<(), Error> { self.table_invalidated = true; Ok(()) @@ -285,22 +280,25 @@ where /// This will *NOT* neutralize the effect of this removed testcase from the global data such as `SchedulerMetadata` fn on_replace( &mut self, - _state: &mut Self::State, + _state: &mut S, _id: CorpusId, - _prev: &Testcase<::Input>, + _prev: &Testcase, ) -> Result<(), Error> { self.table_invalidated = true; Ok(()) } } -impl AflScheduler for WeightedScheduler +impl AflScheduler for WeightedScheduler where - F: TestcaseScore, + F: TestcaseScore, + I: Input, O: MapObserver, S: HasCorpus + HasMetadata + HasTestcase + HasRand + State, C: AsRef + Named, { + type MapObserverRef = C; + fn last_hash(&self) -> usize { self.last_hash } @@ -314,9 +312,10 @@ where } } -impl HasQueueCycles for WeightedScheduler +impl HasQueueCycles for WeightedScheduler where - F: TestcaseScore, + F: TestcaseScore, + I: Input, O: MapObserver, S: HasCorpus + HasMetadata + HasRand + HasTestcase + State, C: AsRef + Named, @@ -326,11 +325,12 @@ where } } -impl Scheduler for WeightedScheduler +impl Scheduler for WeightedScheduler where - F: TestcaseScore, + F: TestcaseScore, + I: Input, O: MapObserver, - S: HasCorpus + HasMetadata + HasRand + HasTestcase + State, + S: HasCorpus + HasMetadata + HasRand + HasTestcase + State, C: AsRef + Named, { /// Called when a [`Testcase`] is added to the corpus @@ -340,14 +340,9 @@ where Ok(()) } - fn on_evaluation( - &mut self, - state: &mut Self::State, - input: &::Input, - observers: &OT, - ) -> Result<(), Error> + fn on_evaluation(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error> where - OT: ObserversTuple, + OT: ObserversTuple, { self.on_evaluation_metadata(state, input, observers) } @@ -404,7 +399,7 @@ where /// Set current fuzzed corpus id and `scheduled_count` fn set_current_scheduled( &mut self, - state: &mut Self::State, + state: &mut S, next_id: Option, ) -> Result<(), Error> { self.on_next_metadata(state, next_id)?; @@ -415,4 +410,5 @@ where } /// The standard corpus weight, same as in `AFL++` -pub type StdWeightedScheduler = WeightedScheduler, O, S>; +pub type StdWeightedScheduler = + WeightedScheduler, I, O, S>; diff --git a/libafl/src/stages/mod.rs b/libafl/src/stages/mod.rs index b0f08bf55f..6d40b96936 100644 --- a/libafl/src/stages/mod.rs +++ b/libafl/src/stages/mod.rs @@ -417,9 +417,9 @@ pub static PUSH_STAGE_ADAPTER_NAME: &str = "pushstageadapter"; impl UsesState for PushStageAdapter where - CS: UsesState, + Z: UsesState, { - type State = CS::State; + type State = Z::State; } impl Named for PushStageAdapter { @@ -431,7 +431,7 @@ impl Named for PushStageAdapter { impl Stage for PushStageAdapter where - CS: Scheduler, + CS: Scheduler, Self::State: HasExecutions + HasRand + HasCorpus @@ -446,7 +446,7 @@ where + ProgressReporter, OT: ObserversTuple, PS: PushStage, - Z: ExecutesInput + Z: ExecutesInput + ExecutionProcessor + EvaluatorObservers + HasScheduler, @@ -455,7 +455,7 @@ where &mut self, fuzzer: &mut Z, executor: &mut E, - state: &mut CS::State, + state: &mut Z::State, event_mgr: &mut EM, ) -> Result<(), Error> { let push_stage = &mut self.push_stage; diff --git a/libafl/src/stages/power.rs b/libafl/src/stages/power.rs index 344ae578ae..7b3ce40678 100644 --- a/libafl/src/stages/power.rs +++ b/libafl/src/stages/power.rs @@ -11,6 +11,7 @@ use libafl_bolts::Named; use crate::{ executors::{Executor, HasObservers}, fuzzer::Evaluator, + inputs::Input, mutators::Mutator, schedulers::{testcase_score::CorpusPowerTestcaseScore, TestcaseScore}, stages::{mutational::MutatedTransform, MutationalStage, RetryCountRestartHelper, Stage}, @@ -49,9 +50,10 @@ impl MutationalStage for PowerMutationalStage where E: Executor + HasObservers, EM: UsesState, - F: TestcaseScore, + F: TestcaseScore, + I: Input, M: Mutator, - Self::State: HasCorpus + HasMetadata + HasRand + HasExecutions + HasNamedMetadata, + Self::State: HasCorpus + HasMetadata + HasRand + HasExecutions + HasNamedMetadata, Z: Evaluator, I: MutatedTransform + Clone, { @@ -82,11 +84,11 @@ impl Stage for PowerMutationalStage + HasObservers, EM: UsesState, - F: TestcaseScore, + F: TestcaseScore, M: Mutator, - Self::State: HasCorpus + HasMetadata + HasRand + HasExecutions + HasNamedMetadata, + Self::State: HasCorpus + HasMetadata + HasRand + HasExecutions + HasNamedMetadata, Z: Evaluator, - I: MutatedTransform + Clone, + I: MutatedTransform + Clone + Input, { #[inline] #[allow(clippy::let_and_return)] @@ -111,12 +113,13 @@ where } } -impl PowerMutationalStage +impl PowerMutationalStage where E: Executor + HasObservers, EM: UsesState::State>, - F: TestcaseScore<::State>, - M: Mutator::State>, + F: TestcaseScore::State>, + I: Input, + M: Mutator::State>, ::State: HasCorpus + HasMetadata + HasRand, Z: Evaluator::State>, { diff --git a/libafl/src/stages/push/mod.rs b/libafl/src/stages/push/mod.rs index 9f6c074ec8..688acae0a0 100644 --- a/libafl/src/stages/push/mod.rs +++ b/libafl/src/stages/push/mod.rs @@ -36,16 +36,14 @@ const STATS_TIMEOUT_DEFAULT: Duration = Duration::from_secs(15); #[derive(Clone, Debug)] pub struct PushStageSharedState where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId, - OT: ObserversTuple, - CS::State: HasRand + HasCorpus, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + OT: ObserversTuple, + Z::State: HasRand + HasCorpus, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { /// The [`crate::state::State`] - pub state: CS::State, + pub state: Z::State, /// The [`crate::fuzzer::Fuzzer`] instance pub fuzzer: Z, /// The [`crate::events::EventManager`] @@ -57,17 +55,15 @@ where impl PushStageSharedState where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId, - OT: ObserversTuple, - CS::State: HasRand + HasCorpus, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + OT: ObserversTuple, + Z::State: HasRand + HasCorpus, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { /// Create a new `PushStageSharedState` that can be used by all [`PushStage`]s #[must_use] - pub fn new(fuzzer: Z, state: CS::State, observers: OT, event_mgr: EM) -> Self { + pub fn new(fuzzer: Z, state: Z::State, observers: OT, event_mgr: EM) -> Self { Self { state, fuzzer, @@ -82,13 +78,11 @@ where #[derive(Clone, Debug)] pub struct PushStageHelper where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId, - OT: ObserversTuple, - CS::State: HasRand + HasCorpus, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + OT: ObserversTuple, + Z::State: HasRand + HasCorpus, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { /// If this stage has already been initalized. /// This gets reset to `false` after one iteration of the stage is done. @@ -103,7 +97,7 @@ where pub current_corpus_id: Option, /// The input we just ran - pub current_input: Option<::Input>, // Todo: Get rid of copy + pub current_input: Option<::Input>, // Todo: Get rid of copy #[allow(clippy::type_complexity)] phantom: PhantomData<(CS, EM, OT, Z)>, @@ -112,13 +106,11 @@ where impl PushStageHelper where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId, - OT: ObserversTuple, - CS::State: HasRand + HasCorpus, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + OT: ObserversTuple, + Z::State: HasRand + HasCorpus, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { /// Create a new [`PushStageHelper`] #[must_use] @@ -181,13 +173,11 @@ where /// After it has finished once, we will call it agan for the next fuzzer round. pub trait PushStage: Iterator where - CS: Scheduler, - CS::State: HasRand + HasExecutions + HasMetadata + HasCorpus + HasLastReportTime, - EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, - OT: ObserversTuple, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + Z::State: HasRand + HasExecutions + HasMetadata + HasCorpus + HasLastReportTime, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + OT: ObserversTuple, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { /// Gets the [`PushStageHelper`] fn push_stage_helper(&self) -> &PushStageHelper; @@ -206,7 +196,7 @@ where fn init( &mut self, _fuzzer: &mut Z, - _state: &mut CS::State, + _state: &mut Z::State, _event_mgr: &mut EM, _observers: &mut OT, ) -> Result<(), Error> { @@ -219,20 +209,20 @@ where fn pre_exec( &mut self, _fuzzer: &mut Z, - _state: &mut CS::State, + _state: &mut Z::State, _event_mgr: &mut EM, _observers: &mut OT, - ) -> Option::Input, Error>>; + ) -> Option::Input, Error>>; /// Called after the execution of a testcase finished. #[inline] fn post_exec( &mut self, _fuzzer: &mut Z, - _state: &mut CS::State, + _state: &mut Z::State, _event_mgr: &mut EM, _observers: &mut OT, - _input: ::Input, + _input: ::Input, _exit_kind: ExitKind, ) -> Result<(), Error> { Ok(()) @@ -243,7 +233,7 @@ where fn deinit( &mut self, _fuzzer: &mut Z, - _state: &mut CS::State, + _state: &mut Z::State, _event_mgr: &mut EM, _observers: &mut OT, ) -> Result<(), Error> { @@ -251,7 +241,7 @@ where } /// This is the default implementation for `next` for this stage - fn next_std(&mut self) -> Option::Input, Error>> { + fn next_std(&mut self) -> Option::Input, Error>> { let mut shared_state = { let shared_state_ref = &mut (*self.push_stage_helper_mut().shared_state).borrow_mut(); shared_state_ref.take().unwrap() diff --git a/libafl/src/stages/push/mutational.rs b/libafl/src/stages/push/mutational.rs index 6c4926981f..4b38846d25 100644 --- a/libafl/src/stages/push/mutational.rs +++ b/libafl/src/stages/push/mutational.rs @@ -43,14 +43,12 @@ pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128; #[derive(Clone, Debug)] pub struct StdMutationalPushStage where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId, - M: Mutator, - OT: ObserversTuple + Serialize, - CS::State: HasRand + HasCorpus + Clone + Debug, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + M: Mutator, + OT: ObserversTuple + Serialize, + Z::State: HasRand + HasCorpus + Clone + Debug, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { current_corpus_id: Option, testcases_to_do: usize, @@ -63,18 +61,16 @@ where impl StdMutationalPushStage where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId, - M: Mutator, - OT: ObserversTuple + Serialize, - CS::State: HasCorpus + HasRand + Clone + Debug, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + M: Mutator, + OT: ObserversTuple + Serialize, + Z::State: HasCorpus + HasRand + Clone + Debug, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { /// 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 - fn iterations(&self, state: &mut CS::State, _corpus_id: CorpusId) -> Result { + fn iterations(&self, state: &mut Z::State, _corpus_id: CorpusId) -> Result { Ok(1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS)) } @@ -86,15 +82,12 @@ where impl PushStage for StdMutationalPushStage where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, - M: Mutator, - OT: ObserversTuple + Serialize, - CS::State: - HasCorpus + HasRand + HasExecutions + HasLastReportTime + HasMetadata + Clone + Debug, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + M: Mutator, + OT: ObserversTuple + Serialize, + Z::State: HasCorpus + HasRand + HasExecutions + HasLastReportTime + HasMetadata + Clone + Debug, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { #[inline] fn push_stage_helper(&self) -> &PushStageHelper { @@ -110,7 +103,7 @@ where fn init( &mut self, fuzzer: &mut Z, - state: &mut CS::State, + state: &mut Z::State, _event_mgr: &mut EM, _observers: &mut OT, ) -> Result<(), Error> { @@ -129,10 +122,10 @@ where fn pre_exec( &mut self, _fuzzer: &mut Z, - state: &mut CS::State, + state: &mut Z::State, _event_mgr: &mut EM, _observers: &mut OT, - ) -> Option::Input, Error>> { + ) -> Option::Input, Error>> { if self.testcases_done >= self.testcases_to_do { // finished with this cicle. return None; @@ -164,10 +157,10 @@ where fn post_exec( &mut self, fuzzer: &mut Z, - state: &mut CS::State, + state: &mut Z::State, event_mgr: &mut EM, observers: &mut OT, - last_input: ::Input, + last_input: ::Input, exit_kind: ExitKind, ) -> Result<(), Error> { // todo: is_interesting, etc. @@ -186,7 +179,7 @@ where fn deinit( &mut self, _fuzzer: &mut Z, - _state: &mut CS::State, + _state: &mut Z::State, _event_mgr: &mut EM, _observers: &mut OT, ) -> Result<(), Error> { @@ -197,33 +190,28 @@ where impl Iterator for StdMutationalPushStage where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, - M: Mutator, - OT: ObserversTuple + Serialize, - CS::State: - HasCorpus + HasRand + HasExecutions + HasMetadata + HasLastReportTime + Clone + Debug, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, + M: Mutator, + OT: ObserversTuple + Serialize, + Z::State: HasCorpus + HasRand + HasExecutions + HasMetadata + HasLastReportTime + Clone + Debug, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { - type Item = Result<::Input, Error>; + type Item = Result<::Input, Error>; - fn next(&mut self) -> Option::Input, Error>> { + fn next(&mut self) -> Option::Input, Error>> { self.next_std() } } impl StdMutationalPushStage where - CS: Scheduler, - EM: EventFirer + EventRestarter + HasEventManagerId, - M: Mutator, - OT: ObserversTuple + Serialize, - CS::State: HasCorpus + HasRand + Clone + Debug, - Z: ExecutionProcessor - + EvaluatorObservers - + HasScheduler, + CS: Scheduler, + EM: EventFirer + EventRestarter + HasEventManagerId, + M: Mutator, + OT: ObserversTuple + Serialize, + Z::State: HasCorpus + HasRand + Clone + Debug, + Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, { /// Creates a new default mutational stage #[must_use] diff --git a/libafl/src/stages/tmin.rs b/libafl/src/stages/tmin.rs index f488d9cbad..b07855ba1e 100644 --- a/libafl/src/stages/tmin.rs +++ b/libafl/src/stages/tmin.rs @@ -57,7 +57,7 @@ where + HasFeedback + ExecutesInput + ExecutionProcessor, - Z::Scheduler: RemovableScheduler, + Z::Scheduler: RemovableScheduler, { /// The mutator registered for this stage fn mutator(&self) -> &M; @@ -239,7 +239,7 @@ where impl Stage for StdTMinMutationalStage where Z: HasScheduler + ExecutionProcessor + ExecutesInput + HasFeedback, - Z::Scheduler: RemovableScheduler, + Z::Scheduler: RemovableScheduler, E: HasObservers, ::Observers: Serialize, EM: EventFirer, @@ -301,7 +301,7 @@ impl TMinMutationalStage for StdTMinMutationalStage where Z: HasScheduler + ExecutionProcessor + ExecutesInput + HasFeedback, - Z::Scheduler: RemovableScheduler, + Z::Scheduler: RemovableScheduler, E: HasObservers, ::Observers: Serialize, EM: EventFirer, diff --git a/libafl_libfuzzer/runtime/src/schedulers.rs b/libafl_libfuzzer/runtime/src/schedulers.rs index 743775159f..fc83b01d98 100644 --- a/libafl_libfuzzer/runtime/src/schedulers.rs +++ b/libafl_libfuzzer/runtime/src/schedulers.rs @@ -4,46 +4,40 @@ use hashbrown::HashMap; use libafl::{ corpus::{Corpus, CorpusId, Testcase}, feedbacks::MapNoveltiesMetadata, - inputs::UsesInput, + inputs::Input, schedulers::{RemovableScheduler, Scheduler}, - state::{HasCorpus, State, UsesState}, + state::{HasCorpus, State}, Error, HasMetadata, }; #[derive(Clone, Debug)] -pub struct MergeScheduler { +pub struct MergeScheduler { mapping: HashMap, all: BTreeSet, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl UsesState for MergeScheduler -where - S: State, -{ - type State = S; -} - -impl RemovableScheduler for MergeScheduler +impl RemovableScheduler for MergeScheduler where + I: Input, S: State + HasCorpus, { fn on_remove( &mut self, - _state: &mut Self::State, + _state: &mut S, id: CorpusId, - _testcase: &Option::Input>>, + _testcase: &Option>, ) -> Result<(), Error> { self.all.remove(&id); Ok(()) } } -impl Scheduler for MergeScheduler +impl Scheduler for MergeScheduler where S: State + HasCorpus, { - fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> { + fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { self.all.insert(id); let testcase = state.corpus().get(id)?.borrow(); let meta = testcase.metadata::()?; @@ -53,12 +47,12 @@ where Ok(()) } - fn next(&mut self, _state: &mut Self::State) -> Result { + fn next(&mut self, _state: &mut S) -> Result { unimplemented!("Not suitable for actual scheduling."); } } -impl MergeScheduler { +impl MergeScheduler { pub fn new() -> Self { Self { mapping: HashMap::default(),