diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index 62345afb14..07a0e66ea1 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -214,7 +214,7 @@ impl HasRefCnt for FreeRTOSSystemStateMetadata { libafl_bolts::impl_serdeany!(FreeRTOSSystemStateMetadata); -#[derive(Default, Serialize, Deserialize, Clone)] +#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct AtomicBasicBlock { start: GuestAddr, ends: HashSet, @@ -249,6 +249,37 @@ impl fmt::Debug for AtomicBasicBlock { } } +impl PartialOrd for AtomicBasicBlock { + fn partial_cmp(&self, other: &AtomicBasicBlock) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for AtomicBasicBlock { + fn cmp(&self, other: &AtomicBasicBlock) -> std::cmp::Ordering { + if self.start.cmp(&other.start) == std::cmp::Ordering::Equal { + // If the start addresses are equal, compare by 'ends' + let end1 = if self.ends.len() == 1 { *self.ends.iter().next().unwrap() as u64 } else { + let mut temp = self.ends.iter().collect::>().into_iter().collect::>(); + temp.sort_unstable(); + let mut h = DefaultHasher::new(); + temp.hash(&mut h); + h.finish() + }; + let end2 = if other.ends.len() == 1 { *self.ends.iter().next().unwrap() as u64 } else { + let mut temp = other.ends.iter().collect::>().into_iter().collect::>(); + temp.sort_unstable(); + let mut h = DefaultHasher::new(); + temp.hash(&mut h); + h.finish() + }; + end1.cmp(&end2) + } else { + // If the start addresses are not equal, compare by 'start' + self.start.cmp(&other.start) + } + } +} fn get_task_names(trace: &Vec) -> HashSet { @@ -363,8 +394,9 @@ fn extract_abbs_from_trace(trace: &Vec) -> HashMap) -> Vec<(String, Rc, usize, u64)> { +/// returns (name, abb, index, ticks, Option) +fn trace_to_state_abb(trace: &Vec) -> (Vec<(String, Rc, usize, u64)>, Vec<(AtomicBasicBlock, u64)>) { + let mut abbs_in_exec_order : Vec<(usize,AtomicBasicBlock,u64)> = vec![]; // indices in trace where an abb ends, along with it's time let mut has_started : HashSet = HashSet::new(); let mut abb_begin_end : HashMap = HashMap::new(); let mut last_abb_of_task : HashMap = HashMap::new(); @@ -429,19 +461,23 @@ fn trace_to_state_abb(trace: &Vec) -> Vec<(String, R let abb = Rc::new(AtomicBasicBlock {start, ends: HashSet::from([end])}); // find intervalls where the abb is actually running, not preempted // count up exec time + let mut sum_of_pieces = 0; for i in s..e { if trace[i].current_task.0.task_name == curr_name { match trace[i].capture_point.0 { - CaptureEvent::APIEnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick));}, + CaptureEvent::APIEnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick)); sum_of_pieces+=trace[i+1].end_tick-trace[i].end_tick;}, CaptureEvent::ISRStart => (), - CaptureEvent::ISREnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick));}, + CaptureEvent::ISREnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick)); sum_of_pieces+=trace[i+1].end_tick-trace[i].end_tick;}, _ => panic!(), } } } + abbs_in_exec_order.push((e,(*abb).clone(), sum_of_pieces)); } + abbs_in_exec_order.sort_by_key(|x| x.0); + let abbs_in_exec_order : Vec<_> = abbs_in_exec_order.into_iter().map(|(_x,y,z)| (y,z)).collect(); chunks.sort_by_key(|x| x.2); - chunks + (chunks, abbs_in_exec_order) } libafl_bolts::impl_serdeany!(AtomicBasicBlock); \ No newline at end of file diff --git a/fuzzers/FRET/src/systemstate/observers.rs b/fuzzers/FRET/src/systemstate/observers.rs index 8091a5845f..f57089689e 100644 --- a/fuzzers/FRET/src/systemstate/observers.rs +++ b/fuzzers/FRET/src/systemstate/observers.rs @@ -44,7 +44,7 @@ where #[inline] fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> { - unsafe {self.last_run = post_process_trace(refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC));} + unsafe {self.last_run = remove_ineffective_isr(refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC));} self.last_input=_input.target_bytes().as_slice().to_owned(); Ok(()) } @@ -171,8 +171,8 @@ fn refine_system_states(input: &mut Vec) -> Vec) -> Vec { - // remove subsequent pairs of equal states where an ISRStart follows an ISREnd +fn remove_ineffective_isr(mut trace: Vec) -> Vec { + // remove subsequent pairs of equal states where an ISREnd follows an ISRStart. If the interrupt had no effect on the system we, are not interested. let mut ret : Vec = Vec::new(); ret.push(trace[0].clone()); let mut i = 1; diff --git a/fuzzers/FRET/src/systemstate/stg.rs b/fuzzers/FRET/src/systemstate/stg.rs index 28528a46f8..d4e86611dd 100644 --- a/fuzzers/FRET/src/systemstate/stg.rs +++ b/fuzzers/FRET/src/systemstate/stg.rs @@ -92,7 +92,7 @@ pub struct STGFeedbackState entrypoint: NodeIndex, exit: NodeIndex, // Metadata about aggregated traces. aggegated meaning, order has been removed - worst_observed_per_aggegated_path: HashMap,u64> + worst_observed_per_aggegated_path: HashMap,u64> } impl Default for STGFeedbackState { @@ -256,12 +256,13 @@ where } }; - let abbs = trace_to_state_abb(&observer.last_run); + let (abbs, ordered) = trace_to_state_abb(&observer.last_run); // println!("{:?}",abbs); - let (trace, _, mut interesting) = StgFeedback::update_stg(&observer.last_run, abbs, feedbackstate); + let (_trace, _, mut interesting) = StgFeedback::update_stg(&observer.last_run, abbs, feedbackstate); if INTEREST_AGGREGATE { + let (it1, _it2) : (Vec<_>, Vec<_>) = ordered.into_iter().unzip(); // aggegation by sorting, order of states is not relevant - let mut tmp = trace.clone(); + let mut tmp : Vec<_> = it1; tmp.sort(); if let Some(x) = feedbackstate.worst_observed_per_aggegated_path.get_mut(&tmp) { let t = clock_observer.last_runtime();