From 4d778dd64dfa059890a239732fb1393d5f171488 Mon Sep 17 00:00:00 2001 From: "Dongjia \"toka\" Zhang" Date: Thu, 9 Mar 2023 03:43:32 +0900 Subject: [PATCH] Fix fuzz_level related thing, separate on_replace/on_remove from Scheduler & various fixes (#1119) * delete HasFuzzedCorpusId * more * fmt clp * aa * fixing * delete * a * append parent id when Objective * add HasCorpus inprocss executor * ecofuzz, delete was_fuzzed, update fuzz_level * fix * RemovableScheduler for Tunable, Queue, Weighted * clp * no std * import * on_execution * fix * win * fmt * fix * revert to on_evaluation and propogate in the accounting scheduler * fix --------- Co-authored-by: Andrea Fioraldi --- libafl/src/corpus/minimizer.rs | 6 +- libafl/src/corpus/testcase.rs | 40 ++--- libafl/src/executors/inprocess.rs | 32 ++-- libafl/src/feedbacks/nautilus.rs | 3 +- libafl/src/fuzzer/mod.rs | 23 +-- libafl/src/schedulers/accounting.rs | 44 +++--- libafl/src/schedulers/ecofuzz.rs | 75 ++++----- libafl/src/schedulers/minimizer.rs | 36 +++-- libafl/src/schedulers/mod.rs | 62 ++++++-- libafl/src/schedulers/powersched.rs | 99 +++++++----- .../src/schedulers/probabilistic_sampling.rs | 19 ++- libafl/src/schedulers/queue.rs | 28 +++- libafl/src/schedulers/testcase_score.rs | 10 +- libafl/src/schedulers/tuneable.rs | 27 +++- libafl/src/schedulers/weighted.rs | 149 ++++++++++++++---- libafl/src/stages/calibrate.rs | 8 +- libafl/src/stages/push/mutational.rs | 27 +--- libafl/src/stages/tmin.rs | 8 +- libafl/src/state/mod.rs | 32 ---- libafl_frida/src/executor.rs | 4 +- libafl_qemu/src/executor.rs | 12 +- libafl_targets/src/windows_asan.rs | 4 +- 22 files changed, 445 insertions(+), 303 deletions(-) diff --git a/libafl/src/corpus/minimizer.rs b/libafl/src/corpus/minimizer.rs index 50ce83e8ee..97833483ce 100644 --- a/libafl/src/corpus/minimizer.rs +++ b/libafl/src/corpus/minimizer.rs @@ -19,7 +19,7 @@ use crate::{ corpus::Corpus, executors::{Executor, HasObservers}, observers::{MapObserver, ObserversTuple}, - schedulers::{LenTimeMulTestcaseScore, Scheduler, TestcaseScore}, + schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, state::{HasCorpus, HasMetadata, UsesState}, Error, HasScheduler, }; @@ -41,7 +41,7 @@ where ) -> Result<(), Error> where E: Executor + HasObservers, - CS: Scheduler, + CS: Scheduler + RemovableScheduler, // schedulers that has on_remove/on_replace only! EM: UsesState, Z: HasScheduler; } @@ -100,7 +100,7 @@ where ) -> Result<(), Error> where E: Executor + HasObservers, - CS: Scheduler, + CS: Scheduler + RemovableScheduler, EM: UsesState, Z: HasScheduler, { diff --git a/libafl/src/corpus/testcase.rs b/libafl/src/corpus/testcase.rs index 837d02a313..f7e2092cf1 100644 --- a/libafl/src/corpus/testcase.rs +++ b/libafl/src/corpus/testcase.rs @@ -34,9 +34,7 @@ where /// Number of executions done at discovery time executions: usize, /// Number of fuzzing iterations of this particular input updated in perform_mutational - fuzz_level: usize, - /// If it has been fuzzed - fuzzed: bool, + scheduled_count: usize, /// Parent [`CorpusId`], if known parent_id: Option, } @@ -160,28 +158,16 @@ where &mut self.executions } - /// Get the `fuzz_level` + /// Get the `scheduled_count` #[inline] - pub fn fuzz_level(&self) -> usize { - self.fuzz_level + pub fn scheduled_count(&self) -> usize { + self.scheduled_count } - /// Set the `fuzz_level` + /// Set the `scheduled_count` #[inline] - pub fn set_fuzz_level(&mut self, fuzz_level: usize) { - self.fuzz_level = fuzz_level; - } - - /// Get if it was fuzzed - #[inline] - pub fn fuzzed(&self) -> bool { - self.fuzzed - } - - /// Set if it was fuzzed - #[inline] - pub fn set_fuzzed(&mut self, fuzzed: bool) { - self.fuzzed = fuzzed; + pub fn set_scheduled_count(&mut self, scheduled_count: usize) { + self.scheduled_count = scheduled_count; } /// Create a new Testcase instance given an input @@ -257,9 +243,8 @@ where metadata: SerdeAnyMap::new(), exec_time: None, cached_len: None, - fuzz_level: 0, + scheduled_count: 0, executions: 0, - fuzzed: false, parent_id: None, } } @@ -486,13 +471,8 @@ pub mod pybind { } #[getter] - fn fuzz_level(&self) -> usize { - self.inner.as_ref().fuzz_level() - } - - #[getter] - fn fuzzed(&self) -> bool { - self.inner.as_ref().fuzzed() + fn scheduled_count(&self) -> usize { + self.inner.as_ref().scheduled_count() } fn metadata(&mut self) -> PyObject { diff --git a/libafl/src/executors/inprocess.rs b/libafl/src/executors/inprocess.rs index 030861c03b..8a9100ea58 100644 --- a/libafl/src/executors/inprocess.rs +++ b/libafl/src/executors/inprocess.rs @@ -50,7 +50,7 @@ use crate::{ fuzzer::HasObjective, inputs::UsesInput, observers::{ObserversTuple, UsesObservers}, - state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions, UsesState}, + state::{HasClientPerfMonitor, HasCorpus, HasSolutions, UsesState}, Error, }; @@ -167,7 +167,7 @@ where H: FnMut(&::Input) -> ExitKind + ?Sized, HB: BorrowMut, OT: ObserversTuple, - S: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + S: HasSolutions + HasClientPerfMonitor + HasCorpus, { /// Create a new in mem executor. /// Caution: crash and restart in one of them will lead to odd behavior if multiple are used, @@ -344,7 +344,7 @@ impl InProcessHandlers { E: Executor + HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { #[cfg(unix)] @@ -545,7 +545,7 @@ pub fn run_observers_and_save_state( E: HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { let observers = executor.observers_mut(); @@ -561,8 +561,8 @@ pub fn run_observers_and_save_state( if interesting { let mut new_testcase = Testcase::new(input.clone()); - new_testcase.set_parent_id_optional(state.fuzzed_corpus_id()); new_testcase.add_metadata(exitkind); + new_testcase.set_parent_id_optional(*state.corpus().current()); fuzzer .objective_mut() .append_metadata(state, observers, &mut new_testcase) @@ -582,8 +582,6 @@ pub fn run_observers_and_save_state( } // We will start mutators from scratch after restart. - state.clear_fuzzed_corpus_id(); - event_mgr.on_restart(state).unwrap(); log::info!("Waiting for broker..."); @@ -614,7 +612,7 @@ mod unix_signal_handler { feedbacks::Feedback, fuzzer::HasObjective, inputs::UsesInput, - state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions}, + state::{HasClientPerfMonitor, HasCorpus, HasSolutions}, }; pub(crate) type HandlerFuncPtr = @@ -673,7 +671,7 @@ mod unix_signal_handler { E: HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { let old_hook = panic::take_hook(); @@ -714,7 +712,7 @@ mod unix_signal_handler { E: HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { if !data.is_valid() { @@ -757,7 +755,7 @@ mod unix_signal_handler { E: Executor + HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { #[cfg(all(target_os = "android", target_arch = "aarch64"))] @@ -865,7 +863,7 @@ pub mod windows_asan_handler { feedbacks::Feedback, fuzzer::HasObjective, inputs::UsesInput, - state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions}, + state::{HasClientPerfMonitor, HasCorpus, HasSolutions}, }; /// # Safety @@ -875,7 +873,7 @@ pub mod windows_asan_handler { E: Executor + HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { let mut data = &mut GLOBAL_STATE; @@ -974,7 +972,7 @@ mod windows_exception_handler { feedbacks::Feedback, fuzzer::HasObjective, inputs::UsesInput, - state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions}, + state::{HasClientPerfMonitor, HasCorpus, HasSolutions}, }; pub(crate) type HandlerFuncPtr = @@ -1013,7 +1011,7 @@ mod windows_exception_handler { E: HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { let old_hook = panic::take_hook(); @@ -1072,7 +1070,7 @@ mod windows_exception_handler { E: HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { let data: &mut InProcessExecutorHandlerData = @@ -1133,7 +1131,7 @@ mod windows_exception_handler { E: Executor + HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { // Have we set a timer_before? diff --git a/libafl/src/feedbacks/nautilus.rs b/libafl/src/feedbacks/nautilus.rs index f6f58417f9..a7bd967dd2 100644 --- a/libafl/src/feedbacks/nautilus.rs +++ b/libafl/src/feedbacks/nautilus.rs @@ -14,9 +14,8 @@ use crate::{ executors::ExitKind, feedbacks::Feedback, generators::NautilusContext, - inputs::NautilusInput, + inputs::{NautilusInput, UsesInput}, observers::ObserversTuple, - prelude::UsesInput, state::{HasClientPerfMonitor, HasMetadata}, Error, }; diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index 08c9be0afd..a09e8560d7 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -23,10 +23,7 @@ use crate::{ schedulers::Scheduler, stages::StagesTuple, start_timer, - state::{ - HasClientPerfMonitor, HasCorpus, HasExecutions, HasFuzzedCorpusId, HasMetadata, - HasSolutions, UsesState, - }, + state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasMetadata, HasSolutions, UsesState}, Error, }; @@ -330,7 +327,7 @@ where F: Feedback, OF: Feedback, OT: ObserversTuple + Serialize + DeserializeOwned, - CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions + HasFuzzedCorpusId, + CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions, { /// Evaluate if a set of observation channels has an interesting state fn process_execution( @@ -387,7 +384,6 @@ where // Add the input to the main corpus let mut testcase = Testcase::with_executions(input.clone(), *state.executions()); - testcase.set_parent_id_optional(state.fuzzed_corpus_id()); self.feedback_mut() .append_metadata(state, observers, &mut testcase)?; let idx = state.corpus_mut().add(testcase)?; @@ -421,7 +417,7 @@ where // The input is a solution, add it to the respective corpus let mut testcase = Testcase::with_executions(input, *state.executions()); - testcase.set_parent_id_optional(state.fuzzed_corpus_id()); + testcase.set_parent_id_optional(*state.corpus().current()); self.objective_mut() .append_metadata(state, observers, &mut testcase)?; state.solutions_mut().add(testcase)?; @@ -447,7 +443,7 @@ where OT: ObserversTuple + Serialize + DeserializeOwned, F: Feedback, OF: Feedback, - CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions + HasFuzzedCorpusId, + CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions, { /// Process one input, adding to the respective corpora if needed and firing the right events #[inline] @@ -480,7 +476,7 @@ where F: Feedback, OF: Feedback, OT: ObserversTuple + Serialize + DeserializeOwned, - CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions + HasFuzzedCorpusId, + CS::State: HasCorpus + HasSolutions + HasClientPerfMonitor + HasExecutions, { /// Process one input, adding to the respective corpora if needed and firing the right events #[inline] @@ -518,7 +514,6 @@ where // Add the input to the main corpus let mut testcase = Testcase::with_executions(input.clone(), *state.executions()); - testcase.set_parent_id_optional(state.fuzzed_corpus_id()); self.feedback_mut() .append_metadata(state, observers, &mut testcase)?; let idx = state.corpus_mut().add(testcase)?; @@ -552,7 +547,7 @@ where EM: ProgressReporter + EventProcessor, F: Feedback, OF: Feedback, - CS::State: HasClientPerfMonitor + HasExecutions + HasMetadata + HasFuzzedCorpusId, + CS::State: HasClientPerfMonitor + HasExecutions + HasMetadata, ST: StagesTuple, { fn fuzz_one( @@ -577,15 +572,9 @@ where #[cfg(feature = "introspection")] state.introspection_monitor_mut().reset_stage_index(); - // Set the parent id - all new testcases will have this id as parent in the following stages. - state.set_fuzzed_corpus_id(idx); - // Execute all stages stages.perform_all(self, executor, state, manager, idx)?; - // Reset the parent id - state.clear_fuzzed_corpus_id(); - // Init timer for manager #[cfg(feature = "introspection")] state.introspection_monitor_mut().start_timer(); diff --git a/libafl/src/schedulers/accounting.rs b/libafl/src/schedulers/accounting.rs index e6b26b5b7b..3b6e3bd4ab 100644 --- a/libafl/src/schedulers/accounting.rs +++ b/libafl/src/schedulers/accounting.rs @@ -8,9 +8,10 @@ use serde::{Deserialize, Serialize}; use crate::{ bolts::{rands::Rand, AsMutSlice, AsSlice, HasLen, HasRefCnt}, - corpus::{Corpus, CorpusId, Testcase}, + corpus::{Corpus, CorpusId}, feedbacks::MapIndexesMetadata, inputs::UsesInput, + observers::ObserversTuple, schedulers::{ minimizer::{IsFavoredMetadata, MinimizerScheduler, DEFAULT_SKIP_NON_FAVORED_PROB}, LenTimeMulTestcaseScore, Scheduler, @@ -130,22 +131,16 @@ where self.inner.on_add(state, idx) } - fn on_replace( + fn on_evaluation( &mut self, state: &mut Self::State, - idx: CorpusId, - testcase: &Testcase<::Input>, - ) -> Result<(), Error> { - self.inner.on_replace(state, idx, testcase) - } - - fn on_remove( - &mut self, - state: &mut Self::State, - idx: CorpusId, - testcase: &Option::Input>>, - ) -> Result<(), Error> { - self.inner.on_remove(state, idx, testcase) + input: &::Input, + observers: &OT, + ) -> Result<(), Error> + where + OT: ObserversTuple, + { + self.inner.on_evaluation(state, input, observers) } fn next(&mut self, state: &mut Self::State) -> Result { @@ -170,8 +165,21 @@ where { idx = self.inner.base_mut().next(state)?; } + + // Don't add corpus.curret(). The inner scheduler will take care of it + Ok(idx) } + + /// Set current fuzzed corpus id and `scheduled_count` + fn set_current_scheduled( + &mut self, + _state: &mut Self::State, + _next_idx: Option, + ) -> Result<(), Error> { + // We do nothing here, the inner scheduler will take care of it + Ok(()) + } } impl<'a, CS> CoverageAccountingScheduler<'a, CS> @@ -271,7 +279,7 @@ where for (_key, idx) in &top_rated.map { let mut entry = state.corpus().get(*idx)?.borrow_mut(); - if entry.fuzzed() { + if entry.scheduled_count() > 0 { continue; } @@ -282,7 +290,7 @@ where } /// Creates a new [`CoverageAccountingScheduler`] that wraps a `base` [`Scheduler`] - /// and has a default probability to skip non-faved [`Testcase`]s of [`DEFAULT_SKIP_NON_FAVORED_PROB`]. + /// and has a default probability to skip non-faved Testcases of [`DEFAULT_SKIP_NON_FAVORED_PROB`]. pub fn new(state: &mut CS::State, base: CS, accounting_map: &'a [u32]) -> Self { match state.metadata().get::() { Some(meta) => { @@ -302,7 +310,7 @@ where } /// Creates a new [`CoverageAccountingScheduler`] that wraps a `base` [`Scheduler`] - /// and has a non-default probability to skip non-faved [`Testcase`]s using (`skip_non_favored_prob`). + /// and has a non-default probability to skip non-faved Testcases using (`skip_non_favored_prob`). pub fn with_skip_prob( state: &mut CS::State, base: CS, diff --git a/libafl/src/schedulers/ecofuzz.rs b/libafl/src/schedulers/ecofuzz.rs index cdbb4c2985..3fc815d8fb 100644 --- a/libafl/src/schedulers/ecofuzz.rs +++ b/libafl/src/schedulers/ecofuzz.rs @@ -47,7 +47,6 @@ pub struct EcoTestcaseMetadata { last_energy: u64, state: EcoState, serial: u64, - was_fuzzed: bool, computed_score: f64, } @@ -117,7 +116,6 @@ where .get_mut::() .ok_or_else(|| Error::key_not_found("EcoTestcaseMetadata not found".to_string()))?; // Set was_fuzzed for the old current - meta.was_fuzzed = true; meta.last_found = count - last_corpus_count; meta.last_energy = meta.mutation_num - last_mutation_num; meta.computed_score @@ -165,29 +163,15 @@ where fn schedule(state: &mut S) -> Result { let mut selection = None; for id in state.corpus().ids() { - let was_fuzzed = state - .corpus() - .get(id)? - .borrow() - .metadata() - .get::() - .ok_or_else(|| Error::key_not_found("EcoTestcaseMetadata not found".to_string()))? - .was_fuzzed; - if !was_fuzzed { + let was_fuzzed = state.corpus().get(id)?.borrow().scheduled_count() > 0; + if was_fuzzed { selection = Some(id); break; } } for id in state.corpus().ids() { - let was_fuzzed = state - .corpus() - .get(id)? - .borrow() - .metadata() - .get::() - .ok_or_else(|| Error::key_not_found("EcoTestcaseMetadata not found".to_string()))? - .was_fuzzed; + let was_fuzzed = state.corpus().get(id)?.borrow().scheduled_count() > 0; if was_fuzzed { state .metadata_mut() @@ -301,10 +285,14 @@ where // Attach a `SchedulerTestcaseMetaData` to the queue entry. depth += 1; - state.corpus().get(idx)?.borrow_mut().add_metadata( - SchedulerTestcaseMetaData::with_n_fuzz_entry(depth, self.last_hash), - ); - + { + let mut testcase = state.corpus().get(idx)?.borrow_mut(); + testcase.add_metadata(SchedulerTestcaseMetaData::with_n_fuzz_entry( + depth, + self.last_hash, + )); + testcase.set_parent_id_optional(current_idx); + } // Add the testcase metadata for this scheduler state .corpus() @@ -324,25 +312,6 @@ where Ok(()) } - fn on_replace( - &mut self, - state: &mut S, - idx: CorpusId, - _testcase: &Testcase, - ) -> Result<(), Error> { - self.on_add(state, idx) - } - - #[allow(clippy::unused_self)] - fn on_remove( - &mut self, - _state: &mut S, - _idx: CorpusId, - _testcase: &Option>, - ) -> Result<(), Error> { - Ok(()) - } - fn on_evaluation( &mut self, state: &mut S, @@ -414,7 +383,7 @@ where } let id = Self::schedule(state)?; - *state.corpus_mut().current_mut() = Some(id); + self.set_current_scheduled(state, Some(id))?; let mutation_num = state .corpus() @@ -439,6 +408,26 @@ where Ok(id) } + + /// Set current fuzzed corpus id and `scheduled_count` + fn set_current_scheduled( + &mut self, + state: &mut Self::State, + next_idx: Option, + ) -> Result<(), Error> { + let current_idx = *state.corpus().current(); + + if let Some(idx) = current_idx { + let mut testcase = state.corpus().get(idx)?.borrow_mut(); + let scheduled_count = testcase.scheduled_count(); + + // increase scheduled count, this was fuzz_level in afl + testcase.set_scheduled_count(scheduled_count + 1); + } + + *state.corpus_mut().current_mut() = next_idx; + Ok(()) + } } /// The weight for each corpus entry diff --git a/libafl/src/schedulers/minimizer.rs b/libafl/src/schedulers/minimizer.rs index 3a260a14ef..d925c6cfee 100644 --- a/libafl/src/schedulers/minimizer.rs +++ b/libafl/src/schedulers/minimizer.rs @@ -13,7 +13,7 @@ use crate::{ feedbacks::MapIndexesMetadata, inputs::UsesInput, observers::ObserversTuple, - schedulers::{LenTimeMulTestcaseScore, Scheduler, TestcaseScore}, + schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, state::{HasCorpus, HasMetadata, HasRand, UsesState}, Error, }; @@ -75,19 +75,13 @@ where type State = CS::State; } -impl Scheduler for MinimizerScheduler +impl RemovableScheduler for MinimizerScheduler where - CS: Scheduler, + CS: RemovableScheduler, F: TestcaseScore, M: AsSlice + SerdeAny + HasRefCnt, CS::State: HasCorpus + HasMetadata + HasRand, { - /// Add an entry to the corpus and return its index - fn on_add(&mut self, state: &mut CS::State, idx: CorpusId) -> Result<(), Error> { - self.base.on_add(state, idx)?; - self.update_score(state, idx) - } - /// Replaces the testcase at the given idx fn on_replace( &mut self, @@ -162,6 +156,20 @@ where } Ok(()) } +} + +impl Scheduler for MinimizerScheduler +where + CS: Scheduler, + F: TestcaseScore, + M: AsSlice + SerdeAny + HasRefCnt, + CS::State: HasCorpus + HasMetadata + HasRand, +{ + /// Add an entry to the corpus and return its index + fn on_add(&mut self, state: &mut CS::State, idx: CorpusId) -> Result<(), Error> { + self.base.on_add(state, idx)?; + self.update_score(state, idx) + } /// An input has been evaluated fn on_evaluation( @@ -193,6 +201,16 @@ where } Ok(idx) } + + /// Set current fuzzed corpus id and `scheduled_count` + fn set_current_scheduled( + &mut self, + _state: &mut Self::State, + _next_idx: Option, + ) -> Result<(), Error> { + // We do nothing here, the inner scheduler will take care of it + Ok(()) + } } impl MinimizerScheduler diff --git a/libafl/src/schedulers/mod.rs b/libafl/src/schedulers/mod.rs index 2e2bd7523c..ba86dd6c29 100644 --- a/libafl/src/schedulers/mod.rs +++ b/libafl/src/schedulers/mod.rs @@ -42,11 +42,15 @@ use crate::{ Error, }; -/// 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 { - /// Added an entry to the corpus at the given index - fn on_add(&mut self, _state: &mut Self::State, _idx: CorpusId) -> Result<(), Error> { +/// The scheduler also implemnts `on_remove` and `on_replace` if it implements this stage. +pub trait RemovableScheduler: Scheduler { + /// Removed the given entry from the corpus at the given index + fn on_remove( + &mut self, + _state: &mut Self::State, + _idx: CorpusId, + _testcase: &Option::Input>>, + ) -> Result<(), Error> { Ok(()) } @@ -59,16 +63,14 @@ pub trait Scheduler: UsesState { ) -> Result<(), Error> { Ok(()) } +} - /// Removed the given entry from the corpus at the given index - fn on_remove( - &mut self, - _state: &mut Self::State, - _idx: CorpusId, - _testcase: &Option::Input>>, - ) -> Result<(), Error> { - Ok(()) - } +/// 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 { + /// Added an entry to the corpus at the given index + fn on_add(&mut self, _state: &mut Self::State, _idx: CorpusId) -> Result<(), Error>; + // Add parent_id here if it has no inner /// An input has been evaluated fn on_evaluation( @@ -85,6 +87,14 @@ pub trait Scheduler: UsesState { /// Gets the next entry fn next(&mut self, state: &mut Self::State) -> 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, + next_idx: Option, + ) -> Result<(), Error>; } /// Feed the fuzzer simply with a random testcase on request @@ -104,16 +114,38 @@ impl Scheduler for RandScheduler where S: HasCorpus + HasRand, { + fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { + // Set parent id + let current_idx = *state.corpus().current(); + state + .corpus() + .get(idx)? + .borrow_mut() + .set_parent_id_optional(current_idx); + + Ok(()) + } + /// Gets the next entry at random fn next(&mut self, state: &mut Self::State) -> Result { if state.corpus().count() == 0 { Err(Error::empty("No entries in corpus".to_owned())) } else { let id = random_corpus_id!(state.corpus(), state.rand_mut()); - *state.corpus_mut().current_mut() = Some(id); + self.set_current_scheduled(state, Some(id))?; Ok(id) } } + + /// Set current fuzzed corpus id and `scheduled_count`. You should call this from `next` + fn set_current_scheduled( + &mut self, + state: &mut Self::State, + next_idx: Option, + ) -> Result<(), Error> { + *state.corpus_mut().current_mut() = next_idx; + Ok(()) + } } impl RandScheduler { diff --git a/libafl/src/schedulers/powersched.rs b/libafl/src/schedulers/powersched.rs index b59389abf1..3ef37685ac 100644 --- a/libafl/src/schedulers/powersched.rs +++ b/libafl/src/schedulers/powersched.rs @@ -12,7 +12,7 @@ use crate::{ corpus::{Corpus, CorpusId, SchedulerTestcaseMetaData, Testcase}, inputs::UsesInput, observers::{MapObserver, ObserversTuple}, - schedulers::Scheduler, + schedulers::{RemovableScheduler, Scheduler}, state::{HasCorpus, HasMetadata, UsesState}, Error, }; @@ -178,40 +178,11 @@ where type State = S; } -impl Scheduler for PowerQueueScheduler +impl RemovableScheduler for PowerQueueScheduler where S: HasCorpus + HasMetadata, O: MapObserver, { - /// Add an entry to the corpus and return its index - fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { - let current_idx = *state.corpus().current(); - - let mut depth = match current_idx { - Some(parent_idx) => state - .corpus() - .get(parent_idx)? - .borrow() - .metadata() - .get::() - .ok_or_else(|| { - Error::key_not_found("SchedulerTestcaseMetaData not found".to_string()) - })? - .depth(), - None => 0, - }; - - // TODO increase perf_score when finding new things like in AFL - // https://github.com/google/AFL/blob/master/afl-fuzz.c#L6547 - - // Attach a `SchedulerTestcaseMetaData` to the queue entry. - depth += 1; - state.corpus().get(idx)?.borrow_mut().add_metadata( - SchedulerTestcaseMetaData::with_n_fuzz_entry(depth, self.last_hash), - ); - Ok(()) - } - #[allow(clippy::cast_precision_loss)] fn on_replace( &mut self, @@ -292,6 +263,44 @@ where Ok(()) } +} + +impl Scheduler for PowerQueueScheduler +where + S: HasCorpus + HasMetadata, + O: MapObserver, +{ + /// Add an entry to the corpus and return its index + fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { + let current_idx = *state.corpus().current(); + + let mut depth = match current_idx { + Some(parent_idx) => state + .corpus() + .get(parent_idx)? + .borrow() + .metadata() + .get::() + .ok_or_else(|| { + Error::key_not_found("SchedulerTestcaseMetaData not found".to_string()) + })? + .depth(), + None => 0, + }; + + // TODO increase perf_score when finding new things like in AFL + // https://github.com/google/AFL/blob/master/afl-fuzz.c#L6547 + + // Attach a `SchedulerTestcaseMetaData` to the queue entry. + depth += 1; + let mut testcase = state.corpus().get(idx)?.borrow_mut(); + testcase.add_metadata(SchedulerTestcaseMetaData::with_n_fuzz_entry( + depth, + self.last_hash, + )); + testcase.set_parent_id_optional(current_idx); + Ok(()) + } fn on_evaluation( &mut self, @@ -343,10 +352,27 @@ where } None => state.corpus().first().unwrap(), }; - *state.corpus_mut().current_mut() = Some(id); + self.set_current_scheduled(state, Some(id))?; + + Ok(id) + } + } + + /// Set current fuzzed corpus id and `scheduled_count` + fn set_current_scheduled( + &mut self, + state: &mut Self::State, + next_idx: Option, + ) -> Result<(), Error> { + let current_idx = *state.corpus().current(); + + if let Some(idx) = current_idx { + let mut testcase = state.corpus().get(idx)?.borrow_mut(); + let scheduled_count = testcase.scheduled_count(); + + // increase scheduled count, this was fuzz_level in afl + testcase.set_scheduled_count(scheduled_count + 1); - // Update the handicap - let mut testcase = state.corpus().get(id)?.borrow_mut(); let tcmeta = testcase .metadata_mut() .get_mut::() @@ -359,9 +385,10 @@ where } else if tcmeta.handicap() > 0 { tcmeta.set_handicap(tcmeta.handicap() - 1); } - - Ok(id) } + + *state.corpus_mut().current_mut() = next_idx; + Ok(()) } } diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs index 8c20e05c46..cacbebd2fd 100644 --- a/libafl/src/schedulers/probabilistic_sampling.rs +++ b/libafl/src/schedulers/probabilistic_sampling.rs @@ -100,6 +100,13 @@ where S: HasCorpus + HasMetadata + HasRand, { fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { + let current_idx = *state.corpus().current(); + state + .corpus() + .get(idx)? + .borrow_mut() + .set_parent_id_optional(current_idx); + if state.metadata().get::().is_none() { state.add_metadata(ProbabilityMetadata::new()); } @@ -124,10 +131,20 @@ where break; } } - *state.corpus_mut().current_mut() = Some(ret); + self.set_current_scheduled(state, Some(ret))?; Ok(ret) } } + + /// Set current fuzzed corpus id and `scheduled_count` + fn set_current_scheduled( + &mut self, + state: &mut Self::State, + next_idx: Option, + ) -> Result<(), Error> { + *state.corpus_mut().current_mut() = next_idx; + Ok(()) + } } impl Default for ProbabilitySamplingScheduler diff --git a/libafl/src/schedulers/queue.rs b/libafl/src/schedulers/queue.rs index 116791dda8..c34a5312b1 100644 --- a/libafl/src/schedulers/queue.rs +++ b/libafl/src/schedulers/queue.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use crate::{ corpus::{Corpus, CorpusId}, inputs::UsesInput, - schedulers::Scheduler, + schedulers::{RemovableScheduler, Scheduler}, state::{HasCorpus, UsesState}, Error, }; @@ -24,10 +24,24 @@ where type State = S; } +impl RemovableScheduler for QueueScheduler where S: HasCorpus {} + impl Scheduler for QueueScheduler where S: HasCorpus, { + fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { + // Set parent id + let current_idx = *state.corpus().current(); + state + .corpus() + .get(idx)? + .borrow_mut() + .set_parent_id_optional(current_idx); + + Ok(()) + } + /// Gets the next entry in the queue fn next(&mut self, state: &mut Self::State) -> Result { if state.corpus().count() == 0 { @@ -39,10 +53,20 @@ where .map(|id| state.corpus().next(id)) .flatten() .unwrap_or_else(|| state.corpus().first().unwrap()); - *state.corpus_mut().current_mut() = Some(id); + self.set_current_scheduled(state, Some(id))?; Ok(id) } } + + /// Set current fuzzed corpus id and `scheduled_count` + fn set_current_scheduled( + &mut self, + state: &mut Self::State, + next_idx: Option, + ) -> Result<(), Error> { + *state.corpus_mut().current_mut() = next_idx; + Ok(()) + } } impl QueueScheduler { diff --git a/libafl/src/schedulers/testcase_score.rs b/libafl/src/schedulers/testcase_score.rs index e0b1e39ff0..fc91ee6592 100644 --- a/libafl/src/schedulers/testcase_score.rs +++ b/libafl/src/schedulers/testcase_score.rs @@ -205,7 +205,7 @@ where } } PowerSchedule::FAST => { - if entry.fuzz_level() != 0 { + if entry.scheduled_count() != 0 { let lg = libm::log2(f64::from(psmeta.n_fuzz()[tcmeta.n_fuzz_entry()])); match lg { @@ -244,11 +244,11 @@ where } } PowerSchedule::LIN => { - factor = (entry.fuzz_level() as f64) + factor = (entry.scheduled_count() as f64) / f64::from(psmeta.n_fuzz()[tcmeta.n_fuzz_entry()] + 1); } PowerSchedule::QUAD => { - factor = ((entry.fuzz_level() * entry.fuzz_level()) as f64) + factor = ((entry.scheduled_count() * entry.scheduled_count()) as f64) / f64::from(psmeta.n_fuzz()[tcmeta.n_fuzz_entry()] + 1); } } @@ -310,7 +310,7 @@ where // This means that this testcase has never gone through the calibration stage before1, // In this case we'll just return the default weight // This methoud is called in corpus's on_add() method. Fuzz_level is zero at that time. - if entry.fuzz_level() == 0 || psmeta.cycles() == 0 { + if entry.scheduled_count() == 0 || psmeta.cycles() == 0 { return Ok(weight); } @@ -362,7 +362,7 @@ where } // was it fuzzed before? - if entry.fuzz_level() == 0 { + if entry.scheduled_count() == 0 { weight *= 2.0; } diff --git a/libafl/src/schedulers/tuneable.rs b/libafl/src/schedulers/tuneable.rs index c6340f98bd..1d8a74aeaa 100644 --- a/libafl/src/schedulers/tuneable.rs +++ b/libafl/src/schedulers/tuneable.rs @@ -7,6 +7,7 @@ use core::marker::PhantomData; use serde::{Deserialize, Serialize}; +use super::RemovableScheduler; use crate::{ corpus::{Corpus, CorpusId}, impl_serdeany, @@ -88,10 +89,24 @@ where type State = S; } +impl RemovableScheduler for TuneableScheduler where S: HasCorpus + HasMetadata {} + impl Scheduler for TuneableScheduler where S: HasCorpus + HasMetadata, { + fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { + // Set parent id + let current_idx = *state.corpus().current(); + state + .corpus() + .get(idx)? + .borrow_mut() + .set_parent_id_optional(current_idx); + + Ok(()) + } + /// Gets the next entry in the queue fn next(&mut self, state: &mut Self::State) -> Result { if state.corpus().count() == 0 { @@ -105,7 +120,17 @@ where } else { state.corpus().first().unwrap() }; - *state.corpus_mut().current_mut() = Some(id); + self.set_current_scheduled(state, Some(id))?; Ok(id) } + + /// Set current fuzzed corpus id and `scheduled_count` + fn set_current_scheduled( + &mut self, + state: &mut Self::State, + next_idx: Option, + ) -> Result<(), Error> { + *state.corpus_mut().current_mut() = next_idx; + Ok(()) + } } diff --git a/libafl/src/schedulers/weighted.rs b/libafl/src/schedulers/weighted.rs index f10efad2cc..2e6ebd6c42 100644 --- a/libafl/src/schedulers/weighted.rs +++ b/libafl/src/schedulers/weighted.rs @@ -9,14 +9,14 @@ use serde::{Deserialize, Serialize}; use crate::{ bolts::rands::Rand, - corpus::{Corpus, CorpusId, SchedulerTestcaseMetaData, Testcase}, + corpus::{Corpus, CorpusId, SchedulerTestcaseMetaData}, inputs::UsesInput, observers::{MapObserver, ObserversTuple}, random_corpus_id, schedulers::{ powersched::{PowerSchedule, SchedulerMetadata}, testcase_score::{CorpusWeightTestcaseScore, TestcaseScore}, - Scheduler, + RemovableScheduler, Scheduler, }, state::{HasCorpus, HasMetadata, HasRand, UsesState}, Error, @@ -229,6 +229,94 @@ where type State = S; } +impl RemovableScheduler for WeightedScheduler +where + F: TestcaseScore, + O: MapObserver, + S: HasCorpus + HasMetadata + HasRand, +{ + #[allow(clippy::cast_precision_loss)] + fn on_remove( + &mut self, + state: &mut Self::State, + _idx: CorpusId, + prev: &Option::Input>>, + ) -> Result<(), Error> { + let prev = prev.as_ref().ok_or_else(|| { + Error::illegal_argument( + "Power schedulers must be aware of the removed corpus entry for reweighting.", + ) + })?; + + let prev_meta = prev + .metadata() + .get::() + .ok_or_else(|| { + Error::key_not_found("SchedulerTestcaseMetaData not found".to_string()) + })?; + + // Use these to adjust `SchedulerMetadata` + let (prev_total_time, prev_cycles) = prev_meta.cycle_and_time(); + let prev_bitmap_size = prev_meta.bitmap_size(); + let prev_bitmap_size_log = libm::log2(prev_bitmap_size as f64); + + let psmeta = state + .metadata_mut() + .get_mut::() + .ok_or_else(|| Error::key_not_found("SchedulerMetadata not found".to_string()))?; + + psmeta.set_exec_time(psmeta.exec_time() - prev_total_time); + psmeta.set_cycles(psmeta.cycles() - (prev_cycles as u64)); + psmeta.set_bitmap_size(psmeta.bitmap_size() - prev_bitmap_size); + psmeta.set_bitmap_size_log(psmeta.bitmap_size_log() - prev_bitmap_size_log); + psmeta.set_bitmap_entries(psmeta.bitmap_entries() - 1); + + Ok(()) + } + + #[allow(clippy::cast_precision_loss)] + fn on_replace( + &mut self, + state: &mut Self::State, + idx: CorpusId, + prev: &crate::corpus::Testcase<::Input>, + ) -> Result<(), Error> { + let prev_meta = prev + .metadata() + .get::() + .ok_or_else(|| { + Error::key_not_found("SchedulerTestcaseMetaData not found".to_string()) + })?; + + // Next depth is + 1 + let prev_depth = prev_meta.depth() + 1; + + // Use these to adjust `SchedulerMetadata` + let (prev_total_time, prev_cycles) = prev_meta.cycle_and_time(); + let prev_bitmap_size = prev_meta.bitmap_size(); + let prev_bitmap_size_log = libm::log2(prev_bitmap_size as f64); + + let psmeta = state + .metadata_mut() + .get_mut::() + .ok_or_else(|| Error::key_not_found("SchedulerMetadata not found".to_string()))?; + + // We won't add new one because it'll get added when it gets executed in calirbation next time. + psmeta.set_exec_time(psmeta.exec_time() - prev_total_time); + psmeta.set_cycles(psmeta.cycles() - (prev_cycles as u64)); + psmeta.set_bitmap_size(psmeta.bitmap_size() - prev_bitmap_size); + psmeta.set_bitmap_size_log(psmeta.bitmap_size_log() - prev_bitmap_size_log); + psmeta.set_bitmap_entries(psmeta.bitmap_entries() - 1); + + state + .corpus() + .get(idx)? + .borrow_mut() + .add_metadata(SchedulerTestcaseMetaData::new(prev_depth)); + Ok(()) + } +} + impl Scheduler for WeightedScheduler where F: TestcaseScore, @@ -255,9 +343,14 @@ where // Attach a `SchedulerTestcaseMetaData` to the queue entry. depth += 1; - state.corpus().get(idx)?.borrow_mut().add_metadata( - SchedulerTestcaseMetaData::with_n_fuzz_entry(depth, self.last_hash), - ); + { + let mut testcase = state.corpus().get(idx)?.borrow_mut(); + testcase.add_metadata(SchedulerTestcaseMetaData::with_n_fuzz_entry( + depth, + self.last_hash, + )); + testcase.set_parent_id_optional(current_idx); + } // TODO increase perf_score when finding new things like in AFL // https://github.com/google/AFL/blob/master/afl-fuzz.c#L6547 @@ -267,27 +360,6 @@ where Ok(()) } - fn on_replace( - &mut self, - state: &mut S, - idx: CorpusId, - _testcase: &Testcase, - ) -> Result<(), Error> { - // Recreate the alias table - self.on_add(state, idx) - } - - fn on_remove( - &mut self, - state: &mut S, - _idx: CorpusId, - _testcase: &Option>, - ) -> Result<(), Error> { - // Recreate the alias table - self.create_alias_table(state)?; - Ok(()) - } - fn on_evaluation( &mut self, state: &mut Self::State, @@ -360,10 +432,27 @@ where })?; psmeta.set_queue_cycles(psmeta.queue_cycles() + 1); } - *state.corpus_mut().current_mut() = Some(idx); - // Update the handicap + self.set_current_scheduled(state, Some(idx))?; + Ok(idx) + } + } + + /// Set current fuzzed corpus id and `scheduled_count` + fn set_current_scheduled( + &mut self, + state: &mut Self::State, + next_idx: Option, + ) -> Result<(), Error> { + let current_idx = *state.corpus().current(); + + if let Some(idx) = current_idx { let mut testcase = state.corpus().get(idx)?.borrow_mut(); + let scheduled_count = testcase.scheduled_count(); + + // increase scheduled count, this was fuzz_level in afl + testcase.set_scheduled_count(scheduled_count + 1); + let tcmeta = testcase .metadata_mut() .get_mut::() @@ -376,8 +465,10 @@ where } else if tcmeta.handicap() > 0 { tcmeta.set_handicap(tcmeta.handicap() - 1); } - Ok(idx) } + + *state.corpus_mut().current_mut() = next_idx; + Ok(()) } } diff --git a/libafl/src/stages/calibrate.rs b/libafl/src/stages/calibrate.rs index fe1a001eb9..5a573c7038 100644 --- a/libafl/src/stages/calibrate.rs +++ b/libafl/src/stages/calibrate.rs @@ -106,7 +106,9 @@ where // Run this stage only once for each corpus entry and only if we haven't already inspected it { let corpus = state.corpus().get(corpus_idx)?.borrow(); - if corpus.fuzz_level() > 0 { + // println!("calibration; corpus.scheduled_count() : {}", corpus.scheduled_count()); + + if corpus.scheduled_count() > 0 { return Ok(()); } } @@ -269,10 +271,10 @@ where psmeta.set_bitmap_entries(psmeta.bitmap_entries() + 1); let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut(); - let fuzz_level = testcase.fuzz_level(); + let scheduled_count = testcase.scheduled_count(); testcase.set_exec_time(total_time / (iter as u32)); - testcase.set_fuzz_level(fuzz_level + 1); + testcase.set_scheduled_count(scheduled_count + 1); // log::trace!("time: {:#?}", testcase.exec_time()); let data = testcase diff --git a/libafl/src/stages/push/mutational.rs b/libafl/src/stages/push/mutational.rs index 39b22374e2..74c1f392f1 100644 --- a/libafl/src/stages/push/mutational.rs +++ b/libafl/src/stages/push/mutational.rs @@ -21,9 +21,7 @@ use crate::{ observers::ObserversTuple, schedulers::Scheduler, start_timer, - state::{ - HasClientPerfMonitor, HasCorpus, HasExecutions, HasFuzzedCorpusId, HasMetadata, HasRand, - }, + state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasMetadata, HasRand}, Error, EvaluatorObservers, ExecutionProcessor, HasScheduler, }; @@ -90,14 +88,8 @@ where EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, M: Mutator, OT: ObserversTuple, - CS::State: HasFuzzedCorpusId - + HasClientPerfMonitor - + HasCorpus - + HasRand - + HasExecutions - + HasMetadata - + Clone - + Debug, + CS::State: + HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions + HasMetadata + Clone + Debug, Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, @@ -144,8 +136,6 @@ where return None; } - let idx = self.current_corpus_idx.unwrap(); - state.set_fuzzed_corpus_id(idx); start_timer!(state); let mut input = state .corpus() @@ -188,7 +178,6 @@ where .post_exec(state, self.stage_idx, self.current_corpus_idx)?; mark_feature_time!(state, PerfFeature::MutatePostExec); self.testcases_done += 1; - state.clear_fuzzed_corpus_id(); Ok(()) } @@ -212,14 +201,8 @@ where EM: EventFirer + EventRestarter + HasEventManagerId + ProgressReporter, M: Mutator, OT: ObserversTuple, - CS::State: HasClientPerfMonitor - + HasCorpus - + HasRand - + HasExecutions - + HasMetadata - + Clone - + Debug - + HasFuzzedCorpusId, + CS::State: + HasClientPerfMonitor + HasCorpus + HasRand + HasExecutions + HasMetadata + Clone + Debug, Z: ExecutionProcessor + EvaluatorObservers + HasScheduler, diff --git a/libafl/src/stages/tmin.rs b/libafl/src/stages/tmin.rs index 7c80ceae1f..1238c1ebfc 100644 --- a/libafl/src/stages/tmin.rs +++ b/libafl/src/stages/tmin.rs @@ -21,7 +21,7 @@ use crate::{ mark_feature_time, mutators::Mutator, observers::{MapObserver, ObserversTuple}, - schedulers::Scheduler, + schedulers::{RemovableScheduler, Scheduler}, stages::Stage, start_timer, state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasMaxSize, HasSolutions, UsesState}, @@ -36,7 +36,7 @@ pub trait TMinMutationalStage: where Self::State: HasCorpus + HasSolutions + HasExecutions + HasMaxSize + HasClientPerfMonitor, ::Input: HasLen + Hash, - CS: Scheduler, + CS: Scheduler + RemovableScheduler, E: Executor + HasObservers, EM: EventFirer, F1: Feedback, @@ -204,7 +204,7 @@ where impl Stage for StdTMinMutationalStage where - CS: Scheduler, + CS: Scheduler + RemovableScheduler, CS::State: HasCorpus + HasSolutions + HasExecutions + HasMaxSize + HasClientPerfMonitor, ::Input: HasLen + Hash, E: Executor + HasObservers, @@ -252,7 +252,7 @@ where impl TMinMutationalStage for StdTMinMutationalStage where - CS: Scheduler, + CS: Scheduler + RemovableScheduler, E: HasObservers + Executor, EM: EventFirer, F1: Feedback, diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index 06ee006c04..3d0da72fb4 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -60,21 +60,6 @@ pub trait HasCorpus: UsesInput { fn corpus_mut(&mut self) -> &mut Self::Corpus; } -/// Trait for a state that has information about which [`CorpusId`] -/// is currently being fuzzed. -/// When a new interesting input was found, this value becomes the `parent_id`. -pub trait HasFuzzedCorpusId { - /// The currently fuzzed [`CorpusId`], if known. - /// If a new interesting testcase was found, this should usually become the `parent_id`. - fn fuzzed_corpus_id(&self) -> Option; - - /// Sets the currently fuzzed [`CorpusId`]. - fn set_fuzzed_corpus_id(&mut self, corpus_id: CorpusId); - - /// Resets the currently fuzzed [`CorpusId`]. - fn clear_fuzzed_corpus_id(&mut self); -} - /// Interact with the maximum size pub trait HasMaxSize { /// The maximum size hint for items and mutations returned @@ -207,8 +192,6 @@ pub struct StdState { named_metadata: NamedSerdeAnyMap, /// MaxSize testcase size for mutators that appreciate it max_size: usize, - /// The [`CorpusId`] of the testcase we're currently fuzzing. - fuzzed_corpus_id: Option, /// Performance statistics for this fuzzer #[cfg(feature = "introspection")] introspection_monitor: ClientPerfMonitor, @@ -274,20 +257,6 @@ where } } -impl HasFuzzedCorpusId for StdState { - fn fuzzed_corpus_id(&self) -> Option { - self.fuzzed_corpus_id - } - - fn set_fuzzed_corpus_id(&mut self, fuzzed_corpus_id: CorpusId) { - self.fuzzed_corpus_id = Some(fuzzed_corpus_id); - } - - fn clear_fuzzed_corpus_id(&mut self) { - self.fuzzed_corpus_id = None; - } -} - impl HasSolutions for StdState where I: Input, @@ -725,7 +694,6 @@ where corpus, solutions, max_size: DEFAULT_MAX_SIZE, - fuzzed_corpus_id: None, #[cfg(feature = "introspection")] introspection_monitor: ClientPerfMonitor::new(), #[cfg(feature = "std")] diff --git a/libafl_frida/src/executor.rs b/libafl_frida/src/executor.rs index 2d2c87cb16..8cff0aca4a 100644 --- a/libafl_frida/src/executor.rs +++ b/libafl_frida/src/executor.rs @@ -8,7 +8,7 @@ use frida_gum::{ #[cfg(windows)] use libafl::{ executors::inprocess::{HasInProcessHandlers, InProcessHandlers}, - state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions}, + state::{HasClientPerfMonitor, HasCorpus, HasSolutions}, }; use libafl::{ executors::{Executor, ExitKind, HasObservers, InProcessExecutor}, @@ -200,7 +200,7 @@ impl<'a, 'b, 'c, H, OT, RT, S> HasInProcessHandlers for FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S> where H: FnMut(&S::Input) -> ExitKind, - S: UsesInput + HasClientPerfMonitor + HasSolutions + HasFuzzedCorpusId, + S: UsesInput + HasClientPerfMonitor + HasSolutions + HasCorpus, S::Input: HasTargetBytes, OT: ObserversTuple, RT: FridaRuntimeTuple, diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index 0666a71667..6be1d53b5b 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -13,10 +13,7 @@ use libafl::{ fuzzer::HasObjective, inputs::UsesInput, observers::{ObserversTuple, UsesObservers}, - state::{ - HasClientPerfMonitor, HasCorpus, HasExecutions, HasFuzzedCorpusId, HasSolutions, State, - UsesState, - }, + state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasSolutions, State, UsesState}, Error, }; @@ -67,12 +64,7 @@ where where EM: EventFirer + EventRestarter, OF: Feedback, - S: State - + HasExecutions - + HasCorpus - + HasSolutions - + HasClientPerfMonitor - + HasFuzzedCorpusId, + S: State + HasExecutions + HasCorpus + HasSolutions + HasClientPerfMonitor, Z: HasObjective, { Ok(Self { diff --git a/libafl_targets/src/windows_asan.rs b/libafl_targets/src/windows_asan.rs index a9044a8eb2..e062980362 100644 --- a/libafl_targets/src/windows_asan.rs +++ b/libafl_targets/src/windows_asan.rs @@ -4,7 +4,7 @@ use libafl::{ events::{EventFirer, EventRestarter}, executors::{inprocess::windows_asan_handler::asan_death_handler, Executor, HasObservers}, feedbacks::Feedback, - state::{HasClientPerfMonitor, HasFuzzedCorpusId, HasSolutions}, + state::{HasClientPerfMonitor, HasCorpus, HasSolutions}, HasObjective, }; @@ -32,7 +32,7 @@ where E: Executor + HasObservers, EM: EventFirer + EventRestarter, OF: Feedback, - E::State: HasSolutions + HasClientPerfMonitor + HasFuzzedCorpusId, + E::State: HasSolutions + HasClientPerfMonitor + HasCorpus, Z: HasObjective, { __sanitizer_set_death_callback(asan_death_handler::);