From 013f3db487eb46dd15086a991382224a87ce02e2 Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Tue, 29 Oct 2024 14:07:52 +0100 Subject: [PATCH] implement STGSnippetStage, fix missing metadata --- fuzzers/FRET/Cargo.toml | 1 + fuzzers/FRET/src/fuzzer.rs | 7 +- fuzzers/FRET/src/systemstate/feedbacks.rs | 6 +- fuzzers/FRET/src/systemstate/mod.rs | 25 +++++- fuzzers/FRET/src/systemstate/mutational.rs | 97 +++++++++++++++++----- fuzzers/FRET/src/systemstate/observers.rs | 22 ++--- fuzzers/FRET/src/systemstate/schedulers.rs | 2 +- fuzzers/FRET/src/systemstate/stg.rs | 85 +++++++++++++++---- libafl/src/schedulers/minimizer.rs | 2 +- 9 files changed, 185 insertions(+), 62 deletions(-) diff --git a/fuzzers/FRET/Cargo.toml b/fuzzers/FRET/Cargo.toml index b3742608e9..d302c6fc11 100644 --- a/fuzzers/FRET/Cargo.toml +++ b/fuzzers/FRET/Cargo.toml @@ -70,3 +70,4 @@ clap = { version = "4.4.11", features = ["derive"] } csv = "1.3.0" log = "0.4" simple_moving_average = "1.0.2" +itertools = "0.13.0" diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 92d9f9d233..71d107e910 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -15,7 +15,7 @@ edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf:: }; use rand::{SeedableRng, StdRng, Rng}; use crate::{ - systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, time::{ + systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, STGSnippetStage}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, time::{ clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP, QEMU_ICOUNT_SHIFT, QEMU_ISNS_PER_USEC}, qemustate::QemuStateRestoreHelper, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeProbMassScheduler, TimeStateMaximizerCorpusScheduler} } }; @@ -478,7 +478,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { #[cfg(feature = "sched_afl",)] let scheduler = TimeMaximizerCorpusScheduler::new(&edges_observer,TimeProbMassScheduler::new()); #[cfg(feature = "sched_stg")] - let scheduler = GraphMaximizerCorpusScheduler::new(&stg_coverage_observer,TimeProbMassScheduler::new()); + let scheduler = GraphMaximizerCorpusScheduler::non_metadata_removing(&stg_coverage_observer,TimeProbMassScheduler::new()); #[cfg(feature = "sched_genetic")] let scheduler = GenerationScheduler::new(); @@ -520,7 +520,8 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { let mutator = StdScheduledMutator::new(mutations); let stages = (systemstate::report::SchedulerStatsStage::default(),()); - let mut stages = (StdMutationalStage::new(mutator), stages); + let stages = (StdMutationalStage::new(mutator), stages); + let mut stages = (STGSnippetStage::new(input_addr), stages); #[cfg(feature = "fuzz_int")] let mut stages = (InterruptShiftStage::new(&interrupt_config), stages); diff --git a/fuzzers/FRET/src/systemstate/feedbacks.rs b/fuzzers/FRET/src/systemstate/feedbacks.rs index 132b5a0468..5abc2e1ddb 100644 --- a/fuzzers/FRET/src/systemstate/feedbacks.rs +++ b/fuzzers/FRET/src/systemstate/feedbacks.rs @@ -192,9 +192,9 @@ where let names : Vec = observer.last_run.iter().map(|x| x.current_task.task_name.clone()).collect(); match &self.dumpfile { Some(s) => { - let per_task_metadata = if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(x.2.clone()) == observer.select_task).max_by(|a,b| (a.1-a.0).cmp(&(b.1-b.0))) { + let per_task_metadata = if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(&x.name) == observer.select_task.as_ref()).max_by(|a,b| (a.response-a.release).cmp(&(b.response-b.release))) { // extract computation time spent in each task and abb - let t : Vec<_> = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.1 && x.end_tick > worst_instance.0 ).cloned().collect(); + let t : Vec<_> = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.response && x.end_tick > worst_instance.release ).cloned().collect(); // task_name -> addr -> (count, time) let mut ret : HashMap> = HashMap::new(); let mut t2 = t.clone(); @@ -212,7 +212,7 @@ where } }); }); - dbg!(&ret); + // dbg!(&ret); ret } else {HashMap::new()}; std::fs::write(s,ron::to_string(&(&observer.last_trace,&observer.last_states,&observer.job_instances,per_task_metadata)).expect("Error serializing hashmap")).expect("Can not dump to file"); diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index 6f781c1239..47bdf8e1a1 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -8,6 +8,7 @@ use std::hash::Hasher; use std::hash::Hash; use hashbrown::HashMap; use serde::{Deserialize, Serialize}; +use itertools::Itertools; use freertos::TCB_t; @@ -452,18 +453,34 @@ impl TaskJob { self.hash_cache } } - pub fn try_update(&mut self, other: &mut JobInstance) -> bool { - assert_eq!(self.get_hash(), other.get_hash()); + pub fn try_update(&mut self, other: &JobInstance) -> bool { + assert_eq!(self.get_hash(), other.get_hash_cached()); let mut ret = false; if other.exec_ticks > self.woet_ticks { self.woet_ticks = other.exec_ticks; self.woet_per_abb = other.ticks_per_abb.clone(); - other.mem_reads.sort_by(|a,b| a.0.cmp(&b.0)); - self.worst_bytes = other.mem_reads.iter().map(|x| x.1).collect(); + self.worst_bytes = other.mem_reads.iter().sorted_by(|a,b| a.0.cmp(&b.0)).map(|x| x.1).collect(); ret = true; } ret } + pub fn from_instance(input: &JobInstance) -> Self { + let c = input.get_hash_cached(); + Self { + name: input.name.clone(), + worst_bytes: input.mem_reads.iter().map(|x| x.1.clone()).collect(), + woet_ticks: input.exec_ticks, + woet_per_abb: input.ticks_per_abb.clone(), + abbs: input.abbs.clone(), + hash_cache: c + } + } + pub fn map_bytes_onto(&self, input: &JobInstance, offset: Option) -> Vec<(u32,u8)> { + if input.mem_reads.len() == 0 {return vec![];} + let ret = input.mem_reads.iter().take(self.worst_bytes.len()).enumerate().filter_map(|(idx,(addr,oldbyte))| if self.worst_bytes[idx]!=*oldbyte {Some((*addr-offset.unwrap_or_default(), self.worst_bytes[idx]))} else {None}).collect(); + // eprintln!("Mapped: {:?}", ret); + ret + } } diff --git a/fuzzers/FRET/src/systemstate/mutational.rs b/fuzzers/FRET/src/systemstate/mutational.rs index d1472cd779..2e3518d290 100644 --- a/fuzzers/FRET/src/systemstate/mutational.rs +++ b/fuzzers/FRET/src/systemstate/mutational.rs @@ -9,7 +9,7 @@ use libafl_bolts::{rands::{ random_seed, Rand, StdRand }, Named}; use libafl::{ - common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, events::{Event, EventFirer, LogSeverity}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, prelude::{new_hash_feedback, AggregatorOps, CorpusId, MutationResult, Mutator, UserStats, UserStatsValue, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error + common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, events::{Event, EventFirer, EventProcessor, LogSeverity}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, prelude::{new_hash_feedback, AggregatorOps, CorpusId, MutationResult, Mutator, UserStats, UserStatsValue, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error }; use libafl::prelude::State; use petgraph::{graph::NodeIndex, graph::{self, DiGraph}}; @@ -19,7 +19,7 @@ use std::borrow::Cow; use simple_moving_average::SMA; -use super::stg::{STGEdge, STGNode}; +use super::{stg::{STGEdge, STGNode}, JobInstance}; // pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC; // one isn per 2**4 ns @@ -88,7 +88,7 @@ pub fn try_force_new_branches(interrupt_ticks : &[u32], fbs: &STGFeedbackState, for (num,&interrupt_time) in interrupt_ticks.iter().enumerate() { let lower_bound = if num==0 {FIRST_INT} else {interrupt_ticks[num-1].saturating_add(config.1 * QEMU_ISNS_PER_USEC)}; let next = if interrupt_ticks.len()>num+1 {interrupt_ticks[num+1]} else {u32::MAX}; - for exec_interval in meta.intervals.iter().filter(|x| x.start_tick >= lower_bound as u64 && x.start_tick < next as u64) { + for exec_interval in meta.intervals().iter().filter(|x| x.start_tick >= lower_bound as u64 && x.start_tick < next as u64) { if !(exec_interval.start_capture.0==CaptureEvent::ISRStart) { // shortcut to skip interrupt handers without node lookup let node_index = fbs.state_abb_hash_index.get(&exec_interval.get_hash_index()).unwrap(); if !has_interrupt_handler_non_systick(&fbs.graph, node_index.clone()) { @@ -306,8 +306,8 @@ where // calculate hits and identify snippets let mut last_m = false; let mut marks : Vec<(&ExecInterval, usize, usize)>= vec![]; // 1: got interrupted, 2: interrupt handler - for i in 0..trace.intervals.len() { - let curr = &trace.intervals[i]; + for i in 0..trace.intervals().len() { + let curr = &trace.intervals()[i]; let m = old_interrupt_times.iter().any(|x| (curr.start_tick..curr.end_tick).contains(&(*x as u64))); if m { marks.push((curr, i, 1)); @@ -323,7 +323,7 @@ where for i in 0..old_interrupt_times.len() { // bounds based on minimum inter-arrival time let mut lb = FIRST_INT; - let mut ub : u32 = trace.intervals[trace.intervals.len()-1].end_tick.try_into().expect("ticks > u32"); + let mut ub : u32 = trace.intervals()[trace.intervals().len()-1].end_tick.try_into().expect("ticks > u32"); if i > 0 { // use the new times, because changes to preceding timings are not accounted for yet lb = u32::saturating_add(new_interrupt_times[i-1], interrup_config.1 * QEMU_ISNS_PER_USEC); @@ -453,18 +453,23 @@ where pub fn try_worst_snippets(bytes : &[u8], fbs: &STGFeedbackState, meta: &STGNodeMetadata) -> Option> { let mut new = false; let mut ret = Vec::new(); - for (num,interval) in meta.intervals.iter().enumerate() { + for (num,interval) in meta.intervals().iter().enumerate() { todo!(); } if new {Some(ret)} else {None} } +static mut num_snippet_stage_execs : u64 = 0; +static mut num_snippet_rerun : u64 = 0; +static mut num_snippet_success : u64 = 0; + /// The default mutational stage #[derive(Clone, Debug, Default)] pub struct STGSnippetStage { #[allow(clippy::type_complexity)] phantom: PhantomData<(E, EM, Z)>, + input_addr: u32 } impl STGSnippetStage @@ -474,8 +479,36 @@ where Z: Evaluator, Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand, { - pub fn new() -> Self { - Self { phantom: PhantomData } + pub fn new(input_addr: u32) -> Self { + Self { phantom: PhantomData, input_addr } + } +} + +impl STGSnippetStage +where + E: UsesState, + EM: UsesState, + EM: EventFirer, + Z: Evaluator, + Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata, + ::Input: Input, + Z::State: UsesInput>, + I: HasMutatorBytes + Default +{ + fn report_stats(&self, state: &mut as UsesState>::State, manager: &mut EM) { + unsafe { + let _ = manager.fire( + state, + Event::UpdateUserStats { + name: Cow::from("STGSnippetStage"), + value: UserStats::new( + UserStatsValue::String(Cow::from(format!("{} -> {}/{} {:.1}% ", num_snippet_stage_execs, num_snippet_success, num_snippet_rerun, num_snippet_success as f32 * 100.0 / num_snippet_rerun as f32))), + AggregatorOps::None, + ), + phantom: PhantomData, + }, + ); + } } } @@ -500,24 +533,46 @@ where let mut myrand = StdRand::new(); myrand.set_seed(state.rand_mut().next()); + let mut do_rerun = false; + let current_case = state.current_testcase()?; let old_input = current_case.input().as_ref().unwrap(); let mut new_input = old_input.clone(); - if let Some(bytes) = old_input.parts_by_name("bytes").next() { - let new_bytes = new_input.parts_by_name("bytes").next(); - if let Some(meta) = current_case.metadata_map().get::() { - let feedbackstate = match state - .named_metadata_map() - .get::("stgfeedbackstate") { - Some(s) => s, - Option::None => { - panic!("STGfeedbackstate not visible") + let new_bytes = new_input.parts_by_name_mut("bytes").next().expect("bytes not found in multipart input").1.bytes_mut(); + // dbg!(current_case.metadata_map()); + // eprintln!("Run mutator {}", current_case.metadata_map().get::().is_some()); + if let Some(meta) = current_case.metadata_map().get::() { + let feedbackstate = match state + .named_metadata_map() + .get::("stgfeedbackstate") { + Some(s) => s, + Option::None => { + panic!("STGfeedbackstate not visible") + } + }; + // Maximize all snippets + // dbg!(meta.jobs().len()); + for jobinst in meta.jobs().iter() { + match feedbackstate.worst_task_jobs.get(&jobinst.get_hash_cached()) { + Some(worst) => { + let new = worst.map_bytes_onto(jobinst, Some(self.input_addr)); + do_rerun |= new.len() > 0; + for (addr, byte) in new { + new_bytes[addr as usize] = byte; } - }; - todo!(); + }, + Option::None => {} + } } - } + drop(current_case); + unsafe {num_snippet_stage_execs+=1;} + if do_rerun { + unsafe {num_snippet_rerun+=1;} + let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, new_input)?; + if corpus_idx.is_some() { unsafe{num_snippet_success+=1; self.report_stats(state, manager);}} + + } else if {unsafe{num_snippet_stage_execs}} % 5 == 0 {self.report_stats(state, manager);} Ok(()) } diff --git a/fuzzers/FRET/src/systemstate/observers.rs b/fuzzers/FRET/src/systemstate/observers.rs index f08b604e74..4c30b6bcc9 100644 --- a/fuzzers/FRET/src/systemstate/observers.rs +++ b/fuzzers/FRET/src/systemstate/observers.rs @@ -41,9 +41,9 @@ pub struct QemuSystemStateObserver pub last_trace: Vec, pub last_reads: Vec>, pub last_input: I, - pub job_instances: Vec<(u64, u64, String)>, + pub job_instances: Vec, pub do_report: bool, - pub worst_job_instances: HashMap, + pub worst_job_instances: HashMap, pub select_task: Option, pub success: bool, name: Cow<'static, str>, @@ -96,18 +96,18 @@ where hash_cache: 0 } }).collect::>(); - println!("Instances: {:?}",&job_instances); + // println!("Instances: {:?}",&job_instances); + self.job_instances = job_instances; let observer = &self; - let mut worst_case_per_task = HashMap::new(); + let mut worst_case_per_task : HashMap = HashMap::new(); observer.job_instances.iter().for_each(|x| { - let time = x.1-x.0; - if worst_case_per_task.get(&x.2).is_some() { - let old = worst_case_per_task.get_mut(&x.2).unwrap(); - if time > *old { - *old=time; + if worst_case_per_task.get(&x.name).is_some() { + let old = worst_case_per_task.get_mut(&x.name).unwrap(); + if x.exec_ticks > old.exec_ticks { + old.exec_ticks=x.exec_ticks; } } else { - worst_case_per_task.insert(x.2.clone(), time); + worst_case_per_task.insert(x.name.clone(), x.clone()); } }); self.worst_job_instances = worst_case_per_task; @@ -160,7 +160,7 @@ where I: Default { Self{last_run: vec![], last_trace: vec![], last_reads: vec![], last_input: I::default(), worst_job_instances: HashMap::new(), do_report: false, select_task: select_task.clone(), name: Cow::from("systemstate".to_string()), last_states: HashMap::new(), success: false, job_instances: vec![]} } pub fn last_runtime(&self) -> u64 { - self.select_task.as_ref().map(|x| self.worst_job_instances.get(x).unwrap_or(&0).clone()).unwrap_or(unsafe{libafl_qemu::sys::icount_get_raw()}) + self.select_task.as_ref().map(|x| self.worst_job_instances.get(x).map(|y| y.response-y.release).unwrap_or(0).clone()).unwrap_or(unsafe{libafl_qemu::sys::icount_get_raw()}) } } impl Default for QemuSystemStateObserver diff --git a/fuzzers/FRET/src/systemstate/schedulers.rs b/fuzzers/FRET/src/systemstate/schedulers.rs index f735bf9d2a..401364dbbb 100644 --- a/fuzzers/FRET/src/systemstate/schedulers.rs +++ b/fuzzers/FRET/src/systemstate/schedulers.rs @@ -101,7 +101,7 @@ where .get(idx)? .borrow() .metadata_map() - .get::().map_or(0, |x| x.nodes.len()); + .get::().map_or(0, |x| x.nodes().len()); let m = self.get_update_trace_length(state,l); state.rand_mut().below(m as usize) > l } && state.rand_mut().coinflip(self.skip_non_favored_prob) diff --git a/fuzzers/FRET/src/systemstate/stg.rs b/fuzzers/FRET/src/systemstate/stg.rs index f67a709edf..77185d4a94 100644 --- a/fuzzers/FRET/src/systemstate/stg.rs +++ b/fuzzers/FRET/src/systemstate/stg.rs @@ -29,8 +29,10 @@ use serde::{Deserialize, Serialize}; use super::AtomicBasicBlock; use super::CaptureEvent; use super::ExecInterval; +use super::JobInstance; use super::ReducedFreeRTOSSystemState; use super::observers::QemuSystemStateObserver; +use super::TaskJob; use petgraph::prelude::DiGraph; use petgraph::graph::NodeIndex; use petgraph::Direction; @@ -151,7 +153,9 @@ pub struct STGFeedbackState worst_observed_per_aggegated_path: HashMap,u64>, worst_observed_per_abb_path: HashMap, worst_observed_per_stg_path: HashMap, - worst_abb_exec_count: HashMap + worst_abb_exec_count: HashMap, + // Metadata about job instances + pub worst_task_jobs: HashMap, } impl Default for STGFeedbackState { @@ -185,7 +189,8 @@ impl Default for STGFeedbackState { worst_observed_per_stg_path: HashMap::new(), worst_abb_exec_count: HashMap::new(), systemstate_index, - state_abb_hash_index + state_abb_hash_index, + worst_task_jobs: HashMap::new(), } } } @@ -201,17 +206,18 @@ impl Named for STGFeedbackState // Wrapper around Vec to attach as Metadata #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct STGNodeMetadata { - pub nodes: Vec, - pub edges: Vec, - pub abbs: u64, - pub aggregate: u64, - pub top_abb_counts: Vec, - pub intervals: Vec, + nodes: Vec, + edges: Vec, + abbs: u64, + aggregate: u64, + top_abb_counts: Vec, + intervals: Vec, + jobs: Vec, indices: Vec, tcref: isize, } impl STGNodeMetadata { - pub fn new(nodes: Vec, edges: Vec, abbs: u64, aggregate: u64, top_abb_counts: Vec, intervals: Vec) -> Self{ + pub fn new(nodes: Vec, edges: Vec, abbs: u64, aggregate: u64, top_abb_counts: Vec, intervals: Vec, jobs: Vec) -> Self { #[allow(unused)] let mut indices : Vec<_> = vec![]; #[cfg(all(feature = "sched_stg",not(any(feature = "sched_stg_pathhash",feature = "sched_stg_abbhash",feature = "sched_stg_aggregatehash"))))] @@ -233,7 +239,35 @@ impl STGNodeMetadata { // indices.push(aggregate as usize); indices = top_abb_counts.iter().map(|x| (*x) as usize).collect(); } - Self {indices, intervals, nodes, abbs, aggregate, top_abb_counts, edges, tcref: 0} + Self {indices, intervals, jobs, nodes, abbs, aggregate, top_abb_counts, edges, tcref: 0} + } + + pub fn nodes(&self) -> &Vec { + &self.nodes + } + + pub fn edges(&self) -> &Vec { + &self.edges + } + + pub fn abbs(&self) -> u64 { + self.abbs + } + + pub fn aggregate(&self) -> u64 { + self.aggregate + } + + pub fn top_abb_counts(&self) -> &Vec { + &self.top_abb_counts + } + + pub fn intervals(&self) -> &Vec { + &self.intervals + } + + pub fn jobs(&self) -> &Vec { + &self.jobs } } @@ -317,6 +351,7 @@ pub struct StgFeedback last_abbs_hash: Option, // only set, if it was interesting last_aggregate_hash: Option, // only set, if it was interesting last_top_abb_hashes: Option>, // only set, if it was interesting + last_job_trace: Option>, // only set, if it was interesting dump_path: Option } #[cfg(feature = "feed_stg")] @@ -340,6 +375,9 @@ const INTEREST_PATH : bool = false; const INTEREST_ABBPATH : bool = false; #[cfg(not(feature = "feed_stg_aggregatehash"))] const INTEREST_AGGREGATE : bool = false; + +const INTEREST_JOB_INSTANCE : bool = true; + fn set_observer_map(trace : &Vec) { unsafe { for i in 0..MAX_STG_NUM { @@ -526,8 +564,23 @@ where } }; + // --------------------------------- Update STG let (nodetrace, edgetrace, mut interesting, mut updated) = StgFeedback::update_stg_interval(&observer.last_trace, &observer.last_reads, &observer.last_states, feedbackstate); + // --------------------------------- Update job instances + for i in observer.worst_job_instances.iter() { + interesting |= INTEREST_JOB_INSTANCE && if let Some(x) = feedbackstate.worst_task_jobs.get_mut(&i.1.get_hash_cached()) { + // eprintln!("Job instance already present"); + x.try_update(i.1) + } else { + // eprintln!("New Job instance"); + feedbackstate.worst_task_jobs.insert(i.1.get_hash_cached(), TaskJob::from_instance(&i.1)); + true + } + }; + self.last_job_trace = Some(observer.job_instances.clone()); + // dbg!(&observer.job_instances); + { let h = get_generic_hash(&edgetrace); if let Some(x) = feedbackstate.worst_observed_per_stg_path.get_mut(&h) { @@ -547,8 +600,8 @@ where let tmp = StgFeedback::abbs_in_exec_order(&observer.last_trace); #[cfg(feature = "trace_job_response_times")] let tmp = { - if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(x.2.clone()) == observer.select_task).max_by(|a,b| (a.1-a.0).cmp(&(b.1-b.0))) { - let t = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.1 && x.end_tick > worst_instance.0 ).cloned().collect(); + if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(x.name.clone()) == observer.select_task).max_by(|a,b| (a.response-a.release).cmp(&(b.response-b.release))) { + let t = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.response && x.end_tick > worst_instance.release ).cloned().collect(); StgFeedback::abbs_in_exec_order(&t) } else { if observer.select_task.is_none() { // if nothing was selected, just take the whole trace, otherwise there is nothing interesting here @@ -633,12 +686,8 @@ where /// Append to the testcase the generated metadata in case of a new corpus item #[inline] fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { - let nodes = self.last_node_trace.take(); - let edges = self.last_edge_trace.take(); - match nodes { - Some(s) => testcase.metadata_map_mut().insert(STGNodeMetadata::new(s, edges.unwrap(), self.last_abbs_hash.take().unwrap_or_default(), self.last_aggregate_hash.take().unwrap_or_default(), self.last_top_abb_hashes.take().unwrap_or_default(), self.last_intervals.take().unwrap())), - Option::None => (), - } + let meta = STGNodeMetadata::new(self.last_node_trace.take().unwrap_or_default(), self.last_edge_trace.take().unwrap_or_default(), self.last_abbs_hash.take().unwrap_or_default(), self.last_aggregate_hash.take().unwrap_or_default(), self.last_top_abb_hashes.take().unwrap_or_default(), self.last_intervals.take().unwrap_or_default(), self.last_job_trace.take().unwrap_or_default()); + testcase.metadata_map_mut().insert(meta); Ok(()) } diff --git a/libafl/src/schedulers/minimizer.rs b/libafl/src/schedulers/minimizer.rs index 71ca7f0763..320780e466 100644 --- a/libafl/src/schedulers/minimizer.rs +++ b/libafl/src/schedulers/minimizer.rs @@ -342,7 +342,7 @@ where .map .insert(elem, idx); } - println!("Number of interesting corpus elements: {}", state.metadata_map_mut().get::().unwrap().get_number()); + // println!("Number of interesting corpus elements: {}", state.metadata_map_mut().get::().unwrap().get_number()); Ok(()) }