diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 789b94619c..7ab96701a2 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -371,7 +371,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { #[cfg(all(feature = "observe_systemstate"))] let mut feedback = feedback_or!( feedback, - DumpSystraceFeedback::::with_dump(if cli.dump_traces {cli.dump_name.clone().map(|x| x.with_extension("trace.ron"))} else {None}) + DumpSystraceFeedback::::with_dump(if cli.dump_traces {cli.dump_name.clone()} else {None}) ); #[cfg(feature = "trace_stg")] let mut feedback = feedback_or!( diff --git a/fuzzers/FRET/src/systemstate/feedbacks.rs b/fuzzers/FRET/src/systemstate/feedbacks.rs index 0ed67c68d6..e63801ea98 100644 --- a/fuzzers/FRET/src/systemstate/feedbacks.rs +++ b/fuzzers/FRET/src/systemstate/feedbacks.rs @@ -4,12 +4,15 @@ use libafl::{ feedbacks::Feedback, observers::ObserversTuple, prelude::{State, UsesInput}, - state::MaybeHasClientPerfMonitor, + state::{HasCorpus, MaybeHasClientPerfMonitor}, Error, + corpus::Corpus, + inputs::Input, }; use libafl::events::EventFirer; use libafl_bolts::Named; use std::path::PathBuf; +use std::time::{Duration, Instant}; use super::target_os::TargetSystem; use std::borrow::Cow; @@ -28,16 +31,19 @@ where name: Cow<'static, str>, dumpfile: Option, phantom: PhantomData, + init_time: Instant, + last_dump: Option, } impl StateInitializer for DumpSystraceFeedback where SYS: TargetSystem {} impl Feedback for DumpSystraceFeedback where - S: State + UsesInput + MaybeHasClientPerfMonitor + HasMetadata, + S: State + UsesInput + MaybeHasClientPerfMonitor + HasMetadata + HasCorpus>, EM: EventFirer, OT: ObserversTuple, SYS: TargetSystem, + I: Input, { fn is_interesting( &mut self, @@ -50,16 +56,37 @@ where where { match &self.dumpfile { Some(s) => { - let trace = state - .metadata::() - .expect("TraceData not found"); - std::fs::write( - s, - ron::to_string(trace) - .expect("Error serializing hashmap"), - ) - .expect("Can not dump to file"); - self.dumpfile = None + let time_has_come = self.last_dump.map(|t| Instant::now()-t > Duration::from_secs(60)).unwrap_or(true); + if time_has_come { + self.last_dump = Some(Instant::now()); + // Try dumping the worst case + let casename = s.with_extension(format!("at_{}h.case", (Instant::now()-self.init_time).as_secs()/60)); + let corpus = state.corpus(); + let mut worst = Duration::new(0,0); + let mut worst_input = None; + for i in 0..corpus.count() { + let tc = corpus.get(corpus.nth(i.into())).expect("Could not get element from corpus").borrow(); + if worst < tc.exec_time().expect("Testcase missing duration") { + worst_input = Some(tc.input().as_ref().unwrap().clone()); + worst = tc.exec_time().expect("Testcase missing duration"); + } + } + if let Some(wi) = worst_input { + wi.to_file(casename); + } + + // Try dumping the current case + let tracename = s.with_extension("trace.ron"); + let trace = state + .metadata::() + .expect("TraceData not found"); + std::fs::write( + tracename, + ron::to_string(trace) + .expect("Error serializing hashmap"), + ) + .expect("Can not dump to file"); + } } Option::None => { () @@ -90,6 +117,8 @@ where name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, phantom: PhantomData, + init_time: std::time::Instant::now(), + last_dump: None, } } #[allow(unused)] @@ -98,6 +127,8 @@ where name: Cow::from("Dumpsystemstate".to_string()), dumpfile: dumpfile, phantom: PhantomData, + init_time: std::time::Instant::now(), + last_dump: None, } } }