diff --git a/fuzzers/FRET/src/systemstate/helpers.rs b/fuzzers/FRET/src/systemstate/helpers.rs index 9177805f28..de0379c738 100644 --- a/fuzzers/FRET/src/systemstate/helpers.rs +++ b/fuzzers/FRET/src/systemstate/helpers.rs @@ -1,7 +1,7 @@ use hashbrown::HashMap; use libafl_bolts::prelude::{SerdeAny, SerdeAnyMap}; use libafl_qemu::{elf::EasyElf, read_user_reg_unchecked, GuestAddr, GuestPhysAddr}; -use std::{cmp::min, hash::{DefaultHasher, Hash, Hasher}, ops::Range}; +use std::{borrow::Cow, cmp::min, hash::{DefaultHasher, Hash, Hasher}, ops::Range}; use crate::{ fuzzer::{DO_NUM_INTERRUPT, FIRST_INT}, @@ -76,7 +76,7 @@ pub fn get_function_range(elf: &EasyElf, symbol: &str) -> Option( - ranges: &'a Vec<(String, Range)>, + ranges: &'a Vec<(Cow<'static, str>, Range)>, addr: GuestAddr, ) -> Option<&'a std::ops::Range> { for (_, r) in ranges { @@ -193,8 +193,8 @@ where #[allow(unused)] pub fn abb_profile( mut intervals: Vec, -) -> HashMap> { - let mut ret: HashMap> = HashMap::new(); +) -> HashMap, HashMap> { + let mut ret: HashMap, HashMap> = HashMap::new(); intervals.sort_by_key(|x| x.get_task_name_unchecked()); intervals .chunk_by_mut(|x, y| x.get_task_name_unchecked() == y.get_task_name_unchecked()) diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index f61fd7d9af..3ddd8e0f48 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -9,6 +9,7 @@ use std::hash::Hash; use hashbrown::HashMap; use serde::{Deserialize, Serialize}; use itertools::Itertools; +use std::borrow::Cow; pub mod helpers; pub mod feedbacks; @@ -56,8 +57,8 @@ pub struct ExecInterval { pub end_tick: u64, pub start_state: u64, pub end_state: u64, - pub start_capture: (CaptureEvent, String), - pub end_capture: (CaptureEvent, String), + pub start_capture: (CaptureEvent, Cow<'static, str>), + pub end_capture: (CaptureEvent, Cow<'static, str>), pub level: u8, // tick_spend_preempted: u64, pub abb: Option @@ -93,11 +94,11 @@ impl ExecInterval { return (self.start_state, self.abb.as_ref().expect("ABB not set").get_hash()) } - pub fn get_task_name(&self) -> Option { + pub fn get_task_name(&self) -> Option> { self.abb.as_ref().map(|x| x.instance_name.clone()).flatten() } - pub fn get_task_name_unchecked(&self) -> String { - self.get_task_name().unwrap_or_else(|| "unknown".to_string()) + pub fn get_task_name_unchecked(&self) -> Cow<'static, str> { + self.get_task_name().unwrap_or_else(|| Cow::Owned("unknown".to_owned())) } pub fn is_abb_end(&self) -> bool { @@ -117,7 +118,7 @@ pub struct AtomicBasicBlock { ends: HashSet, level: u8, instance_id: usize, - instance_name: Option, + instance_name: Option>, } impl PartialEq for AtomicBasicBlock { @@ -146,7 +147,7 @@ impl fmt::Display for AtomicBasicBlock { for end in &self.ends { ends_str.push_str(&format!("0x{:#x}, ", end)); } - write!(f, "ABB {} {{ level: {}, start: 0x{:#x}, ends: [{}]}}", &self.instance_name.as_ref().unwrap_or(&"".to_string()), self.level, self.start, ends_str.trim().trim_matches(',')) + write!(f, "ABB {} {{ level: {}, start: 0x{:#x}, ends: [{}]}}", &self.instance_name.as_ref().unwrap_or(&Cow::Owned("".to_owned())), self.level, self.start, ends_str.trim().trim_matches(',')) } } impl fmt::Debug for AtomicBasicBlock { @@ -155,7 +156,7 @@ impl fmt::Debug for AtomicBasicBlock { for end in &self.ends { ends_str.push_str(&format!("{:#x}, ", end)); } - write!(f, "ABB {} {{ level: {}, start: 0x{:#x}, ends: [{}]}}", &self.instance_name.as_ref().unwrap_or(&"".to_string()), self.level, self.start, ends_str.trim().trim_matches(',')) + write!(f, "ABB {} {{ level: {}, start: 0x{:#x}, ends: [{}]}}", &self.instance_name.as_ref().unwrap_or(&Cow::Owned("".to_owned())), self.level, self.start, ends_str.trim().trim_matches(',')) } } diff --git a/fuzzers/FRET/src/systemstate/stg.rs b/fuzzers/FRET/src/systemstate/stg.rs index ef4d125d59..454093dc38 100644 --- a/fuzzers/FRET/src/systemstate/stg.rs +++ b/fuzzers/FRET/src/systemstate/stg.rs @@ -108,7 +108,7 @@ where pub struct STGEdge { pub event: CaptureEvent, - pub name: String, + pub name: Cow<'static, str>, pub worst: Option<(u64, Vec<(u32, u8)>)>, } @@ -126,7 +126,7 @@ impl STGEdge { short } pub fn color_print(&self) -> String { - let mut short = self.name.clone(); + let mut short = self.name.to_string(); short.push_str(match self.event { CaptureEvent::APIStart => "\", color=\"blue", CaptureEvent::APIEnd => "\", color=\"black", @@ -556,7 +556,7 @@ where } // every path terminates at the end if !fbs.graph.neighbors_directed(return_node_trace[return_node_trace.len()-1].0, Direction::Outgoing).any(|x| x == fbs.exitpoint) { - let mut e__ = STGEdge { event: CaptureEvent::End, name: String::from("End"), worst: None }; + let mut e__ = STGEdge { event: CaptureEvent::End, name: Cow::Borrowed("End"), worst: None }; if let Some((time, accesses)) = instance_time.get_mut(&trace[trace.len()-1].abb.as_ref().unwrap().instance_id) { e__.worst = Some((*time, accesses.clone())); } diff --git a/fuzzers/FRET/src/systemstate/target_os/freertos/mod.rs b/fuzzers/FRET/src/systemstate/target_os/freertos/mod.rs index 4e890b2af0..05f885ccf0 100644 --- a/fuzzers/FRET/src/systemstate/target_os/freertos/mod.rs +++ b/fuzzers/FRET/src/systemstate/target_os/freertos/mod.rs @@ -2,6 +2,7 @@ use libafl_qemu::GuestAddr; use qemu_module::{FreeRTOSSystemStateHelper, MEM_READ}; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; use crate::{ impl_emu_lookup, @@ -195,23 +196,23 @@ fn trigger_collection( match event { CaptureEvent::APIStart => { - let s = h.api_fn_addrs.get(&edge.1).unwrap(); - systemstate.capture_point = (CaptureEvent::APIStart, s.to_string()); + let s : &Cow<'static, str> = h.api_fn_addrs.get(&edge.1).unwrap(); + systemstate.capture_point = (CaptureEvent::APIStart, s.clone()); } CaptureEvent::APIEnd => { - let s = h.api_fn_addrs.get(&edge.0).unwrap(); - systemstate.capture_point = (CaptureEvent::APIEnd, s.to_string()); + let s : &Cow<'static, str> = h.api_fn_addrs.get(&edge.0).unwrap(); + systemstate.capture_point = (CaptureEvent::APIEnd, s.clone()); } CaptureEvent::ISRStart => { - let s = h.isr_fn_addrs.get(&edge.1).unwrap(); - systemstate.capture_point = (CaptureEvent::ISRStart, s.to_string()); + let s : &Cow<'static, str> = h.isr_fn_addrs.get(&edge.1).unwrap(); + systemstate.capture_point = (CaptureEvent::ISRStart, s.clone()); } CaptureEvent::ISREnd => { - let s = h.isr_fn_addrs.get(&edge.0).unwrap(); - systemstate.capture_point = (CaptureEvent::ISREnd, s.to_string()); + let s : &Cow<'static, str> = h.isr_fn_addrs.get(&edge.0).unwrap(); + systemstate.capture_point = (CaptureEvent::ISREnd, s.clone()); } CaptureEvent::End => { - systemstate.capture_point = (CaptureEvent::End, "".to_string()); + systemstate.capture_point = (CaptureEvent::End, Cow::Borrowed("")); } CaptureEvent::Undefined => (), } @@ -302,7 +303,7 @@ pub struct RawFreeRTOSSystemState { read_invalid: bool, input_counter: u32, edge: (GuestAddr, GuestAddr), - capture_point: (CaptureEvent, String), + capture_point: (CaptureEvent, Cow<'static, str>), mem_reads: Vec<(u32, u8)>, } /// List of system state dumps from EmulatorModules @@ -459,7 +460,7 @@ impl fmt::Display for FreeRTOSSystemState { #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub(crate)struct FreeRTOSSystemStateContext { pub qemu_tick: u64, - pub capture_point: (CaptureEvent, String), + pub capture_point: (CaptureEvent, Cow<'static, str>), pub edge: (GuestAddr, GuestAddr), pub mem_reads: Vec<(u32, u8)>, } diff --git a/fuzzers/FRET/src/systemstate/target_os/freertos/post_processing.rs b/fuzzers/FRET/src/systemstate/target_os/freertos/post_processing.rs index f90cbd51ac..558299eb8a 100644 --- a/fuzzers/FRET/src/systemstate/target_os/freertos/post_processing.rs +++ b/fuzzers/FRET/src/systemstate/target_os/freertos/post_processing.rs @@ -124,7 +124,7 @@ pub(crate) fn refine_system_states( }); ret.1.push(FreeRTOSSystemStateContext { qemu_tick: i.qemu_tick, - capture_point: (i.capture_point.0, i.capture_point.1.to_string()), + capture_point: (i.capture_point.0, i.capture_point.1), edge: i.edge, mem_reads: i.mem_reads, }); @@ -328,7 +328,7 @@ pub(crate) fn add_abb_info( }, instance_id: id_count, instance_name: if trace[i].level < 2 { - Some(curr_name.clone().clone()) + Some(Cow::Owned(curr_name.to_owned())) } else { None }, @@ -352,7 +352,7 @@ pub(crate) fn add_abb_info( 2 }, instance_id: id_count, - instance_name: Some(curr_name.clone().clone()), + instance_name: Some(Cow::Owned(curr_name.to_owned())), }))); id_count += 1; open_abb_at_this_ret_addr_and_task.insert( @@ -390,7 +390,7 @@ pub(crate) fn add_abb_info( }, instance_id: id_count, instance_name: if trace[i].level < 1 { - Some(curr_name.clone().clone()) + Some(Cow::Owned(curr_name.to_owned())) } else { None }, @@ -474,7 +474,7 @@ pub(crate) fn get_releases( // A timed release is SysTickHandler isr block that moves a task from the delay list to the ready list. if i.start_capture.0 == CaptureEvent::ISRStart && (i.start_capture.1 == "xPortSysTickHandler" - || USR_ISR_SYMBOLS.contains(&i.start_capture.1.as_str())) + || USR_ISR_SYMBOLS.contains(&&*i.start_capture.1)) { // detect race-conditions, get start and end state from the nearest valid intervals if states diff --git a/fuzzers/FRET/src/systemstate/target_os/freertos/qemu_module.rs b/fuzzers/FRET/src/systemstate/target_os/freertos/qemu_module.rs index 7057a28afa..99b306a152 100644 --- a/fuzzers/FRET/src/systemstate/target_os/freertos/qemu_module.rs +++ b/fuzzers/FRET/src/systemstate/target_os/freertos/qemu_module.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::ops::Range; use freertos::FreeRTOSTraceMetadata; @@ -31,11 +32,11 @@ pub struct FreeRTOSSystemStateHelper { // Address of the application code pub app_range: Range, // Address of API functions - pub api_fn_addrs: HashMap, - pub api_fn_ranges: Vec<(String, std::ops::Range)>, + pub api_fn_addrs: HashMap>, + pub api_fn_ranges: Vec<(Cow<'static, str>, std::ops::Range)>, // Address of interrupt routines - pub isr_fn_addrs: HashMap, - pub isr_fn_ranges: Vec<(String, std::ops::Range)>, + pub isr_fn_addrs: HashMap>, + pub isr_fn_ranges: Vec<(Cow<'static, str>, std::ops::Range)>, // Address of input memory pub input_mem: Range, // FreeRTOS specific addresses @@ -59,9 +60,9 @@ impl FreeRTOSSystemStateHelper { ) -> Self { let app_range = target_ranges.get("APP_CODE").unwrap().clone(); - let api_fn_ranges : Vec<_> = target_groups.get("API_FN").unwrap().iter().sorted_by_key(|x|x.1.start).map(|(n,r)| (n.clone(),r.clone())).collect(); + let api_fn_ranges : Vec<_> = target_groups.get("API_FN").unwrap().iter().sorted_by_key(|x|x.1.start).map(|(n,r)| (Cow::Borrowed(Box::leak(n.clone().into_boxed_str())),r.clone())).collect(); let api_fn_addrs = api_fn_ranges.iter().map(|(n,r)| (r.start,n.clone())).collect(); - let isr_fn_ranges : Vec<_> = target_groups.get("ISR_FN").unwrap().iter().sorted_by_key(|x|x.1.start).map(|(n,r)| (n.clone(),r.clone())).collect(); + let isr_fn_ranges : Vec<_> = target_groups.get("ISR_FN").unwrap().iter().sorted_by_key(|x|x.1.start).map(|(n,r)| (Cow::Borrowed(Box::leak(n.clone().into_boxed_str())),r.clone())).collect(); let isr_fn_addrs = isr_fn_ranges.iter().map(|(n,r)| (r.start,n.clone())).collect(); let input_mem = target_symbols.get("FUZZ_INPUT").map(|x| *x..(*x+unsafe{MAX_INPUT_SIZE as GuestAddr})).unwrap(); @@ -170,7 +171,7 @@ where let pc = c.read_reg::(15).unwrap(); let last = current_systemstate_vec.last_mut().unwrap(); last.edge = (pc, 0); - last.capture_point =(CaptureEvent::End, "Breakpoint".to_string()); + last.capture_point =(CaptureEvent::End, Cow::Borrowed("Breakpoint")); // Find the first ISREnd of vPortSVCHandler (start of the first task) and drop anything before unsafe { let mut index = 0; diff --git a/fuzzers/FRET/src/systemstate/target_os/mod.rs b/fuzzers/FRET/src/systemstate/target_os/mod.rs index 9e3d81844e..4d40465ad9 100644 --- a/fuzzers/FRET/src/systemstate/target_os/mod.rs +++ b/fuzzers/FRET/src/systemstate/target_os/mod.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::hash_map::DefaultHasher; use std::fmt; use hashbrown::HashSet; @@ -81,7 +82,7 @@ pub trait SystemTraceData: Serialize + Sized + for<'a> Deserialize<'a> + Default fn select_abb_profile( &self, select_task: Option, - ) -> HashMap> { + ) -> HashMap, HashMap> { if let Some(select_task) = select_task.as_ref() { // Task selected, only profile this task let wjptybrt = self.worst_jobs_per_task_by_response_time();