diff --git a/fuzzers/FRET/src/systemstate/report.rs b/fuzzers/FRET/src/systemstate/report.rs index 99832253b4..7c96a3501c 100644 --- a/fuzzers/FRET/src/systemstate/report.rs +++ b/fuzzers/FRET/src/systemstate/report.rs @@ -4,8 +4,10 @@ use core::{marker::PhantomData, time::Duration}; use libafl_bolts::current_time; +use itertools::Itertools; + use libafl::{ - corpus::{Corpus, HasCurrentCorpusId}, events::EventFirer, prelude::minimizer::TopRatedsMetadata, schedulers::minimizer::IsFavoredMetadata, stages::Stage, state::{HasCorpus, HasImported, UsesState}, Error, HasMetadata + corpus::{Corpus, HasCurrentCorpusId}, events::EventFirer, prelude::{minimizer::TopRatedsMetadata, RemovableScheduler}, schedulers::minimizer::IsFavoredMetadata, stages::Stage, state::{HasCorpus, HasImported, UsesState}, Error, HasMetadata, HasScheduler }; use libafl::{ events::Event, @@ -35,12 +37,13 @@ impl Stage for SchedulerStatsStage where E: UsesState, EM: EventFirer, - Z: UsesState, + Z: UsesState + HasScheduler, + ::Scheduler: RemovableScheduler, Self::State: HasImported + HasCorpus + HasMetadata, { fn perform( &mut self, - _fuzzer: &mut Z, + fuzzer: &mut Z, _executor: &mut E, state: &mut ::State, _manager: &mut EM, @@ -59,7 +62,7 @@ where if cur.checked_sub(self.last_report_time).unwrap_or_default() > self.stats_report_interval { if let Some(meta) = state.metadata_map().get::() { let kc = meta.map.keys().count(); - let mut v : Vec<_> = meta.map.values().collect(); + let mut v : Vec<_> = meta.map.values().cloned().collect(); v.sort_unstable(); v.dedup(); let vc = v.len(); @@ -90,6 +93,31 @@ where self.imported_size ); self.last_report_time = cur; + // Experimental pruning + #[cfg(any(feature = "sched_stg",feature = "sched_afl"))] + { + const PRUNE_THRESHOLD: usize = 200; + if state.corpus().count() > PRUNE_THRESHOLD*vc { + // println!("Pruning corpus, keeping {} / {}", PRUNE_THRESHOLD*vc); + let corpus = state.corpus_mut(); + let currid = corpus.current(); + let ids : Vec<_> = corpus.ids().filter_map(|x| { + let tc = corpus.get(x).unwrap().borrow(); + let md = tc.metadata_map(); + if md.get::().is_some() || &Some(x) == currid || v.contains(&&x) { + None + } else { + Some((x, tc.exec_time().clone())) + } + }).sorted_by_key(|x| x.1).take(usize::saturating_sub(corpus.count(),(PRUNE_THRESHOLD/2)*vc)).sorted_by_key(|x| x.0).unique().rev().collect(); + for (cid, _) in ids { + let c = state.corpus_mut().remove(cid).unwrap(); + fuzzer + .scheduler_mut() + .on_remove(state, cid, &Some(c))?; + } + } + } } }