From acf9b04e70f64faf6107686979ed62c019ebc4b3 Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Thu, 20 Jun 2024 13:25:21 +0200 Subject: [PATCH] remove unused code --- fuzzers/FRET/src/clock.rs | 43 +- fuzzers/FRET/src/fuzzer.rs | 4 +- fuzzers/FRET/src/systemstate/feedbacks.rs | 31 +- fuzzers/FRET/src/systemstate/freertos.rs | 4 +- fuzzers/FRET/src/systemstate/graph.rs | 632 --------------------- fuzzers/FRET/src/systemstate/helpers.rs | 25 +- fuzzers/FRET/src/systemstate/mod.rs | 3 - fuzzers/FRET/src/systemstate/observers.rs | 75 ++- fuzzers/FRET/src/systemstate/schedulers.rs | 34 +- 9 files changed, 87 insertions(+), 764 deletions(-) delete mode 100644 fuzzers/FRET/src/systemstate/graph.rs diff --git a/fuzzers/FRET/src/clock.rs b/fuzzers/FRET/src/clock.rs index a770c4bdb9..d9a106d08c 100644 --- a/fuzzers/FRET/src/clock.rs +++ b/fuzzers/FRET/src/clock.rs @@ -1,41 +1,22 @@ -use hashbrown::{hash_map::Entry, HashMap}; -use libafl_bolts::{ - current_nanos, - rands::StdRand, - tuples::{tuple_list,MatchName}, - impl_serdeany, - Named, -}; +use libafl_bolts::Named; use libafl::{ - executors::{ExitKind}, - fuzzer::{StdFuzzer}, - inputs::{BytesInput, HasTargetBytes}, - observers::{Observer,VariableMapObserver}, - state::{StdState}, + executors::ExitKind, + observers::Observer, Error, common::HasNamedMetadata, observers::ObserversTuple, prelude::UsesInput, }; use serde::{Deserialize, Serialize}; -use std::{cell::UnsafeCell, cmp::max, env, fs::OpenOptions, io::Write, time::Instant}; +use std::{fs::OpenOptions, io::Write}; -use libafl_qemu::{ - emu, - emu::Emulator, - executor::QemuExecutor, - helpers::{QemuHelper, QemuHelperTuple, HasInstrumentationFilter}, -}; use libafl::events::EventFirer; use libafl::state::MaybeHasClientPerfMonitor; use libafl::prelude::State; -use libafl::inputs::Input; use libafl::feedbacks::Feedback; use libafl::SerdeAny; use libafl::common::HasMetadata; use libafl::corpus::testcase::Testcase; use core::{fmt::Debug, time::Duration}; -// use libafl::feedbacks::FeedbackState; -// use libafl::state::HasFeedbackStates; use std::time::{SystemTime, UNIX_EPOCH}; use std::path::PathBuf; use std::borrow::Cow; @@ -45,12 +26,12 @@ pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH; pub const QEMU_ICOUNT_SHIFT : u32 = 5; pub const QEMU_ISNS_PER_SEC : u32 = u32::pow(10, 9) / u32::pow(2, QEMU_ICOUNT_SHIFT); pub const QEMU_ISNS_PER_USEC : u32 = QEMU_ISNS_PER_SEC / 1000000; -pub const QEMU_NS_PER_ISN : u32 = 1 << QEMU_ICOUNT_SHIFT; -pub const TARGET_SYSCLK_FREQ : u32 = 25 * 1000 * 1000; -pub const TARGET_MHZ_PER_MIPS : f32 = TARGET_SYSCLK_FREQ as f32 / QEMU_ISNS_PER_SEC as f32; -pub const TARGET_MIPS_PER_MHZ : f32 = QEMU_ISNS_PER_SEC as f32 / TARGET_SYSCLK_FREQ as f32; -pub const TARGET_SYSCLK_PER_QEMU_SEC : u32 = (TARGET_SYSCLK_FREQ as f32 * TARGET_MIPS_PER_MHZ) as u32; -pub const QEMU_SYSCLK_PER_TARGET_SEC : u32 = (TARGET_SYSCLK_FREQ as f32 * TARGET_MHZ_PER_MIPS) as u32; +pub const _QEMU_NS_PER_ISN : u32 = 1 << QEMU_ICOUNT_SHIFT; +pub const _TARGET_SYSCLK_FREQ : u32 = 25 * 1000 * 1000; +pub const _TARGET_MHZ_PER_MIPS : f32 = _TARGET_SYSCLK_FREQ as f32 / QEMU_ISNS_PER_SEC as f32; +pub const _TARGET_MIPS_PER_MHZ : f32 = QEMU_ISNS_PER_SEC as f32 / _TARGET_SYSCLK_FREQ as f32; +pub const _TARGET_SYSCLK_PER_QEMU_SEC : u32 = (_TARGET_SYSCLK_FREQ as f32 * _TARGET_MIPS_PER_MHZ) as u32; +pub const _QEMU_SYSCLK_PER_TARGET_SEC : u32 = (_TARGET_SYSCLK_FREQ as f32 * _TARGET_MHZ_PER_MIPS) as u32; //========== Metadata #[derive(Debug, SerdeAny, Serialize, Deserialize)] @@ -244,7 +225,7 @@ where &mut self, _state: &mut S, _manager: &mut EM, - observers: &OT, + _observers: &OT, testcase: &mut Testcase, ) -> Result<(), Error> { *testcase.exec_time_mut() = self.exec_time; @@ -325,7 +306,7 @@ 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> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase) -> Result<(), Error> { // testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime}); Ok(()) } diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 54c0bef3fc..6f6ce09843 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -7,7 +7,7 @@ use libafl_bolts::{ core_affinity::Cores, current_nanos, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice }; use libafl::{ -common::{HasMetadata, HasNamedMetadata}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::ExitKind, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator +common::{HasMetadata, HasNamedMetadata}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::ExitKind, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::QueueScheduler, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator }; use libafl_qemu::{ edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf::EasyElf, emu::Emulator, GuestAddr, GuestPhysAddr, QemuExecutor, QemuFilterList, QemuHooks, Regs, StdInstrumentationFilter @@ -780,7 +780,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| { #[cfg(feature = "restarting")] { let mut shmem_provider = StdShMemProvider::new().unwrap(); - let (state, mut mgr) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) + let (state, mgr) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) { // The restarting state will spawn the same process again as child, then restarted it each time it crashes. Ok(res) => res, diff --git a/fuzzers/FRET/src/systemstate/feedbacks.rs b/fuzzers/FRET/src/systemstate/feedbacks.rs index 53783033ff..8c466d3e13 100644 --- a/fuzzers/FRET/src/systemstate/feedbacks.rs +++ b/fuzzers/FRET/src/systemstate/feedbacks.rs @@ -1,12 +1,9 @@ use libafl::SerdeAny; -use libafl_bolts::ownedref::OwnedSlice; -use libafl::inputs::BytesInput; use libafl::prelude::UsesInput; use libafl::common::HasNamedMetadata; use std::path::PathBuf; use crate::clock::QemuClockObserver; use libafl::corpus::Testcase; -use libafl_bolts::tuples::MatchName; use std::collections::hash_map::DefaultHasher; use std::hash::Hasher; use std::hash::Hash; @@ -17,17 +14,13 @@ use libafl::feedbacks::Feedback; use libafl_bolts::Named; use libafl::Error; use hashbrown::HashMap; -use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata}; +use libafl::{executors::ExitKind, observers::ObserversTuple, common::HasMetadata}; use serde::{Deserialize, Serialize}; use super::ExecInterval; use super::ReducedFreeRTOSSystemState; use super::FreeRTOSSystemStateMetadata; use super::observers::QemuSystemStateObserver; -use petgraph::prelude::DiGraph; -use petgraph::graph::NodeIndex; -use petgraph::Direction; -use std::cmp::Ordering; use std::borrow::Cow; //============================= Feedback @@ -71,10 +64,10 @@ where fn is_interesting( &mut self, state: &mut S, - manager: &mut EM, - input: &S::Input, + _manager: &mut EM, + _input: &S::Input, observers: &OT, - exit_kind: &ExitKind, + _exit_kind: &ExitKind, ) -> Result where EM: EventFirer, @@ -127,7 +120,7 @@ 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> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { let a = self.last_trace.take(); match a { Some(s) => testcase.metadata_map_mut().insert(FreeRTOSSystemStateMetadata::new(s)), @@ -177,11 +170,11 @@ where { fn is_interesting( &mut self, - state: &mut S, - manager: &mut EM, - input: &S::Input, + _state: &mut S, + _manager: &mut EM, + _input: &S::Input, observers: &OT, - exit_kind: &ExitKind, + _exit_kind: &ExitKind, ) -> Result where EM: EventFirer, @@ -203,7 +196,7 @@ 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> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase) -> Result<(), Error> { if !self.dump_metadata {return Ok(());} // let a = self.last_trace.take(); // match a { @@ -232,13 +225,15 @@ impl Named for DumpSystraceFeedback impl DumpSystraceFeedback { /// Creates a new [`DumpSystraceFeedback`] - #[must_use] + #[allow(unused)] pub fn new() -> Self { Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, dump_metadata: false, last_trace: None, last_states: None } } + #[allow(unused)] pub fn with_dump(dumpfile: Option) -> Self { Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: dumpfile, dump_metadata: false, last_trace: None, last_states: None} } + #[allow(unused)] pub fn metadata_only() -> Self { Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, dump_metadata: true, last_trace: None, last_states: None} } diff --git a/fuzzers/FRET/src/systemstate/freertos.rs b/fuzzers/FRET/src/systemstate/freertos.rs index 98d324923a..ff13f686db 100644 --- a/fuzzers/FRET/src/systemstate/freertos.rs +++ b/fuzzers/FRET/src/systemstate/freertos.rs @@ -1,7 +1,7 @@ -#![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,deref_nullptr)] +#![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,deref_nullptr,unused)] use serde::{Deserialize, Serialize}; // Manual Types -use libafl_qemu::{Emulator, Qemu}; +use libafl_qemu::Qemu; /*========== Start of generated Code =============*/ pub type char_ptr = ::std::os::raw::c_uint; diff --git a/fuzzers/FRET/src/systemstate/graph.rs b/fuzzers/FRET/src/systemstate/graph.rs deleted file mode 100644 index 84426fa269..0000000000 --- a/fuzzers/FRET/src/systemstate/graph.rs +++ /dev/null @@ -1,632 +0,0 @@ - -use libafl::SerdeAny; -/// Feedbacks organizing SystemStates as a graph -// use libafl::inputs::HasBytesVec; -use libafl_bolts::rands::random_seed; -use libafl_bolts::rands::StdRand; -use libafl::mutators::Mutator; -use libafl::mutators::MutationResult; -use libafl::prelude::HasTargetBytes; -use libafl::prelude::UsesInput; -use libafl::common::HasNamedMetadata; -use libafl::state::UsesState; -use libafl::prelude::State; -use core::marker::PhantomData; -use libafl::state::HasCorpus; -use libafl::state::HasSolutions; -use libafl::state::HasRand; -use crate::worst::MaxExecsLenFavFactor; -use crate::worst::MaxTimeFavFactor; -use libafl::schedulers::MinimizerScheduler; -use libafl_bolts::HasRefCnt; -use libafl_bolts::AsSlice; -use libafl_bolts::ownedref::OwnedSlice; -use libafl::inputs::BytesInput; -use std::path::PathBuf; -use crate::clock::QemuClockObserver; -use libafl::corpus::Testcase; -use libafl_bolts::tuples::MatchName; -use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; -use std::hash::Hash; -use libafl::events::EventFirer; -use libafl::state::MaybeHasClientPerfMonitor; -use libafl::feedbacks::Feedback; -use libafl_bolts::Named; -use libafl::Error; -use hashbrown::HashMap; -use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata}; -use serde::{Deserialize, Serialize}; - -use super::ExecInterval; -use super::ReducedFreeRTOSSystemState; -use super::FreeRTOSSystemStateMetadata; -use super::observers::QemuSystemStateObserver; -use petgraph::prelude::DiGraph; -use petgraph::graph::NodeIndex; -use petgraph::Direction; -use std::cmp::Ordering; -use std::borrow::Cow; - -use libafl_bolts::rands::Rand; - -//============================= Data Structures -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)] -pub struct VariantTuple -{ - pub start_tick: u64, - pub end_tick: u64, - input_counter: u32, - pub input: Vec, // in the end any kind of input are bytes, regardless of type and lifetime -} -impl VariantTuple { - fn from(other: &ReducedFreeRTOSSystemState,input: Vec) -> Self { - // VariantTuple{ - // start_tick: other.tick, - // end_tick: other.end_tick, - // input_counter: other.input_counter, - // input: input, - // } - todo!() - } -} - -#[derive(Serialize, Deserialize, Clone, Debug, Default)] -pub struct SysGraphNode -{ - base: ReducedFreeRTOSSystemState, - pub variants: Vec, -} -impl SysGraphNode { - fn from(base: ReducedFreeRTOSSystemState, input: Vec) -> Self { - SysGraphNode{variants: vec![VariantTuple::from(&base, input)], base:base } - } - /// unites the variants of this value with another, draining the other if the bases are equal - fn unite(&mut self, other: &mut SysGraphNode) -> bool { - if self!=other {return false;} - self.variants.append(&mut other.variants); - self.variants.dedup(); - return true; - } - /// add a Varint from a [`RefinedFreeRTOSSystemState`] - fn unite_raw(&mut self, other: &ReducedFreeRTOSSystemState, input: &Vec) -> bool { - if &self.base!=other {return false;} - self.variants.push(VariantTuple::from(other, input.clone())); - self.variants.dedup(); - return true; - } - /// add a Varint from a [`RefinedFreeRTOSSystemState`], if it's interesting - fn unite_interesting(&mut self, other: &ReducedFreeRTOSSystemState, input: &Vec) -> bool { - // if &self.base!=other {return false;} - // let interesting = - // self.variants.iter().all(|x| x.end_tick-x.start_tickother.end_tick-other.tick) || // shortest variant - // self.variants.iter().all(|x| x.input_counter>other.input_counter) || // longest input - // self.variants.iter().all(|x| x.input_counter &str { - &self.base.current_task.task_name - } - pub fn get_input_counts(&self) -> Vec { - self.variants.iter().map(|x| x.input_counter).collect() - } - pub fn pretty_print(&self) -> String { - let mut ret = String::new(); - ret.push_str(&format!("{}",&self.base.current_task.task_name)); - ret.push_str(";Rl:"); - for i in &self.base.ready_list_after { - ret.push_str(&format!(";{}",i.task_name)); - } - ret.push_str(";Dl:"); - for i in &self.base.delay_list_after { - ret.push_str(&format!(";{}",i.task_name)); - } - // println!("{}",ret); - ret - } -} -impl PartialEq for SysGraphNode { - fn eq(&self, other: &SysGraphNode) -> bool { - self.base==other.base - } -} - -// Wrapper around Vec to attach as Metadata -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub struct SysGraphMetadata { - pub inner: Vec, - indices: Vec, - tcref: isize, -} -impl SysGraphMetadata { - pub fn new(inner: Vec) -> Self{ - Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0} - } -} -// impl AsSlice for SysGraphMetadata { -// /// Convert the slice of system-states to a slice of hashes over enumerated states -// fn as_slice(&self) -> &[usize] { -// self.indices.as_slice() -// } - -// type Entry = usize; -// } - -impl HasRefCnt for SysGraphMetadata { - fn refcnt(&self) -> isize { - self.tcref - } - - fn refcnt_mut(&mut self) -> &mut isize { - &mut self.tcref - } -} - -libafl_bolts::impl_serdeany!(SysGraphMetadata); - -pub type GraphMaximizerCorpusScheduler = - MinimizerScheduler::State>,SysGraphMetadata,O>; - -//============================= Graph Feedback - -/// Improved System State Graph -#[derive(Serialize, Deserialize, Clone, Debug, SerdeAny)] -pub struct SysGraphFeedbackState -{ - pub graph: DiGraph, - entrypoint: NodeIndex, - exit: NodeIndex, - name: Cow<'static, str> -} -impl SysGraphFeedbackState -{ - pub fn new() -> Self { - let mut graph = DiGraph::::new(); - let mut entry = SysGraphNode::default(); - entry.base.current_task.task_name="Start".to_string(); - let mut exit = SysGraphNode::default(); - exit.base.current_task.task_name="End".to_string(); - let entry = graph.add_node(entry); - let exit = graph.add_node(exit); - Self {graph: graph, entrypoint: entry, exit: exit, name: Cow::from(String::from("SysMap"))} - } - fn insert(&mut self, list: Vec, input: &Vec) { - let mut current_index = self.entrypoint; - for n in list { - let mut done = false; - for i in self.graph.neighbors_directed(current_index, Direction::Outgoing) { - if n == self.graph[i].base { - done = true; - current_index = i; - break; - } - } - if !done { - let j = self.graph.add_node(SysGraphNode::from(n,input.clone())); - self.graph.add_edge(current_index, j, ()); - current_index = j; - } - } - } - /// Try adding a system state path from a [Vec], return true if the path was interesting - fn update(&mut self, list: &Vec, input: &Vec) -> (bool, Vec) { - let mut current_index = self.entrypoint; - let mut novel = false; - let mut trace : Vec = vec![current_index]; - for n in list { - let mut matching : Option = None; - for i in self.graph.node_indices() { - let tmp = &self.graph[i]; - if n == &tmp.base { - matching = Some(i); - break; - } - } - match matching { - None => { - novel = true; - let j = self.graph.add_node(SysGraphNode::from(n.clone(),input.clone())); - self.graph.update_edge(current_index, j, ()); - current_index = j; - }, - Some(i) => { - novel |= self.graph[i].unite_interesting(&n, input); - self.graph.update_edge(current_index, i, ()); - current_index = i; - } - } - trace.push(current_index); - } - if current_index != self.entrypoint { - self.graph.update_edge(current_index, self.exit, ()); // every path ends in the exit noded - } - return (novel, trace); - } -} -impl Named for SysGraphFeedbackState -{ - #[inline] - fn name(&self) -> &Cow<'static, str> { - &self.name - } -} -impl Default for SysGraphFeedbackState { - fn default() -> Self { - Self::new() - } -} -impl SysGraphFeedbackState -{ - fn reset(&mut self) -> Result<(), Error> { - self.graph.clear(); - let mut entry = SysGraphNode::default(); - entry.base.current_task.task_name="Start".to_string(); - let mut exit = SysGraphNode::default(); - exit.base.current_task.task_name="End".to_string(); - self.entrypoint = self.graph.add_node(entry); - self.exit = self.graph.add_node(exit); - Ok(()) - } -} - -/// A Feedback reporting novel System-State Transitions. Depends on [`QemuSystemStateObserver`] -#[derive(Serialize, Deserialize, Clone, Debug, Default)] -pub struct SysMapFeedback -{ - name: Cow<'static, str>, - last_trace: Option>, -} -impl SysMapFeedback { - pub fn new() -> Self { - Self {name: Cow::from(String::from("SysMapFeedback")), last_trace: None } - } -} - -impl Feedback for SysMapFeedback -where - S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata, - S::Input: HasTargetBytes, -{ - #[allow(clippy::wrong_self_convention)] - fn is_interesting( - &mut self, - state: &mut S, - _manager: &mut EM, - _input: &S::Input, - observers: &OT, - _exit_kind: &ExitKind, - ) -> Result - where - EM: EventFirer, - OT: ObserversTuple, - { - let observer = observers.match_name::("systemstate") - .expect("QemuSystemStateObserver not found"); - let feedbackstate = match state - .named_metadata_map_mut() - .get_mut::("SysMap") { - Some(s) => s, - None => { - let n=SysGraphFeedbackState::default(); - state.named_metadata_map_mut().insert("SysMap",n); - state.named_metadata_map_mut().get_mut::("SysMap").unwrap() - } - }; - let ret = feedbackstate.update(&observer.last_run, &observer.last_input); - self.last_trace = Some(ret.1); - Ok(ret.0) - } - - /// 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 a = self.last_trace.take(); - match a { - Some(s) => testcase.metadata_map_mut().insert(SysGraphMetadata::new(s)), - None => (), - } - Ok(()) - } - - /// Discard the stored metadata in case that the testcase is not added to the corpus - #[inline] - fn discard_metadata(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> { - self.last_trace = None; - Ok(()) - } -} -impl Named for SysMapFeedback -{ - #[inline] - fn name(&self) -> &Cow<'static, str> { - &self.name - } -} - -//============================= Mutators -//=============================== Snippets -// pub struct RandGraphSnippetMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// phantom: PhantomData<(I, S)>, -// } -// impl RandGraphSnippetMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// pub fn new() -> Self { -// RandGraphSnippetMutator{phantom: PhantomData} -// } -// } -// impl Mutator for RandGraphSnippetMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// fn mutate( -// &mut self, -// state: &mut S, -// input: &mut I, -// _stage_idx: i32 -// ) -> Result -// { -// // need our own random generator, because borrowing rules -// let mut myrand = StdRand::new(); -// let tmp = &mut state.rand_mut(); -// myrand.set_seed(tmp.next()); -// drop(tmp); - -// let feedbackstate = state -// .feedback_states() -// .match_name::("SysMap") -// .unwrap(); -// let g = &feedbackstate.graph; -// let tmp = state.metadata().get::(); -// if tmp.is_none() { // if there are no metadata it was probably not interesting anyways -// return Ok(MutationResult::Skipped); -// } -// let trace =tmp.expect("SysGraphMetadata not found"); -// // follow the path, extract snippets from last reads, find common snippets. -// // those are likley keys parts. choose random parts from other sibling traces -// let sibling_inputs : Vec<&Vec>= g[*trace.inner.last().unwrap()].variants.iter().map(|x| &x.input).collect(); -// let mut snippet_collector = vec![]; -// let mut per_input_counters = HashMap::<&Vec,usize>::new(); // ugly workaround to track multiple inputs -// for t in &trace.inner { -// let node = &g[*t]; -// let mut per_node_snippets = HashMap::<&Vec,&[u8]>::new(); -// for v in &node.variants { -// match per_input_counters.get_mut(&v.input) { -// None => { -// if sibling_inputs.iter().any(|x| *x==&v.input) { // only collect info about siblin inputs from target -// per_input_counters.insert(&v.input, v.input_counter.try_into().unwrap()); -// } -// }, -// Some(x) => { -// let x_u = *x; -// if x_u = vec![]; -// for c in snippet_collector { -// new_input.extend_from_slice(myrand.choose(c).1); -// } -// for i in new_input.iter().enumerate() { -// input.bytes_mut()[i.0]=*i.1; -// } - -// Ok(MutationResult::Mutated) -// } - -// fn post_exec( -// &mut self, -// _state: &mut S, -// _stage_idx: i32, -// _corpus_idx: Option -// ) -> Result<(), Error> { -// Ok(()) -// } -// } - -// impl Named for RandGraphSnippetMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// fn name(&self) -> &str { -// "RandGraphSnippetMutator" -// } -// } -// //=============================== Snippets -// pub struct RandInputSnippetMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// phantom: PhantomData<(I, S)>, -// } -// impl RandInputSnippetMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// pub fn new() -> Self { -// RandInputSnippetMutator{phantom: PhantomData} -// } -// } -// impl Mutator for RandInputSnippetMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// fn mutate( -// &mut self, -// state: &mut S, -// input: &mut I, -// _stage_idx: i32 -// ) -> Result -// { -// // need our own random generator, because borrowing rules -// let mut myrand = StdRand::new(); -// let tmp = &mut state.rand_mut(); -// myrand.set_seed(tmp.next()); -// drop(tmp); - -// let feedbackstate = state -// .feedback_states() -// .match_name::("SysMap") -// .unwrap(); -// let g = &feedbackstate.graph; -// let tmp = state.metadata().get::(); -// if tmp.is_none() { // if there are no metadata it was probably not interesting anyways -// return Ok(MutationResult::Skipped); -// } -// let trace = tmp.expect("SysGraphMetadata not found"); - -// let mut collection : Vec> = Vec::new(); -// let mut current_pointer : usize = 0; -// for t in &trace.inner { -// let node = &g[*t]; -// for v in &node.variants { -// if v.input == input.bytes() { -// if v.input_counter > current_pointer.try_into().unwrap() { -// collection.push(v.input[current_pointer..v.input_counter as usize].to_owned()); -// current_pointer = v.input_counter as usize; -// } -// break; -// } -// } -// } -// let index_to_mutate = myrand.below(collection.len() as u64) as usize; -// for i in 0..collection[index_to_mutate].len() { -// collection[index_to_mutate][i] = myrand.below(0xFF) as u8; -// } -// for i in collection.concat().iter().enumerate() { -// input.bytes_mut()[i.0]=*i.1; -// } - -// Ok(MutationResult::Mutated) -// } - -// fn post_exec( -// &mut self, -// _state: &mut S, -// _stage_idx: i32, -// _corpus_idx: Option -// ) -> Result<(), Error> { -// Ok(()) -// } -// } - -// impl Named for RandInputSnippetMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// fn name(&self) -> &str { -// "RandInputSnippetMutator" -// } -// } -// //=============================== Suffix -// pub struct RandGraphSuffixMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// phantom: PhantomData<(I, S)>, -// } -// impl RandGraphSuffixMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// pub fn new() -> Self { -// RandGraphSuffixMutator{phantom: PhantomData} -// } -// } -// impl Mutator for RandGraphSuffixMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// fn mutate( -// &mut self, -// state: &mut S, -// input: &mut I, -// _stage_idx: i32 -// ) -> Result -// { -// // need our own random generator, because borrowing rules -// let mut myrand = StdRand::new(); -// let tmp = &mut state.rand_mut(); -// myrand.set_seed(tmp.next()); -// drop(tmp); - -// let feedbackstate = state -// .feedback_states() -// .match_name::("SysMap") -// .unwrap(); -// let g = &feedbackstate.graph; -// let tmp = state.metadata().get::(); -// if tmp.is_none() { // if there are no metadata it was probably not interesting anyways -// return Ok(MutationResult::Skipped); -// } -// let trace =tmp.expect("SysGraphMetadata not found"); -// // follow the path, extract snippets from last reads, find common snippets. -// // those are likley keys parts. choose random parts from other sibling traces -// let inp_c_end = g[*trace.inner.last().unwrap()].base.input_counter; -// let mut num_to_reverse = myrand.below(trace.inner.len().try_into().unwrap()); -// for t in trace.inner.iter().rev() { -// let int_c_prefix = g[*t].base.input_counter; -// if int_c_prefix < inp_c_end { -// num_to_reverse-=1; -// if num_to_reverse<=0 { -// let mut new_input=input.bytes()[..(int_c_prefix as usize)].to_vec(); -// let mut ext : Vec = (int_c_prefix..inp_c_end).map(|_| myrand.next().to_le_bytes()).flatten().collect(); -// new_input.append(&mut ext); -// for i in new_input.iter().enumerate() { -// if input.bytes_mut().len()>i.0 { -// input.bytes_mut()[i.0]=*i.1; -// } -// else { break }; -// } -// break; -// } -// } -// } -// Ok(MutationResult::Mutated) -// } - -// fn post_exec( -// &mut self, -// _state: &mut S, -// _stage_idx: i32, -// _corpus_idx: Option -// ) -> Result<(), Error> { -// Ok(()) -// } -// } - -// impl Named for RandGraphSuffixMutator -// where -// I: Input + HasBytesVec, -// S: HasRand + HasMetadata + HasCorpus + HasSolutions, -// { -// fn name(&self) -> &str { -// "RandGraphSuffixMutator" -// } -// } \ No newline at end of file diff --git a/fuzzers/FRET/src/systemstate/helpers.rs b/fuzzers/FRET/src/systemstate/helpers.rs index db6f4aab48..ce121a72ca 100644 --- a/fuzzers/FRET/src/systemstate/helpers.rs +++ b/fuzzers/FRET/src/systemstate/helpers.rs @@ -1,21 +1,13 @@ -use std::cell::UnsafeCell; -use std::io::Write; use std::ops::Range; use hashbrown::HashMap; use libafl::prelude::ExitKind; use libafl::prelude::UsesInput; use libafl_qemu::read_user_reg_unchecked; -use libafl_qemu::Emulator; use libafl_qemu::GuestAddr; -use libafl_qemu::GuestPhysAddr; -use libafl_qemu::GuestReg; -use libafl_qemu::Qemu; use libafl_qemu::QemuHooks; -use libafl_qemu::edges::QemuEdgesMapMetadata; -use libafl_qemu::emu; -use libafl_qemu::hooks; use libafl_qemu::Hook; -// use crate::systemstate::extract_abbs_from_trace; +use libafl_qemu::helpers::{QemuHelper, QemuHelperTuple}; + use crate::systemstate::RawFreeRTOSSystemState; use crate::systemstate::CURRENT_SYSTEMSTATE_VEC; use crate::systemstate::NUM_PRIOS; @@ -26,18 +18,7 @@ use super::freertos::rtos_struct::*; use super::freertos; use super::CaptureEvent; -use libafl_qemu::{ - helpers::{QemuHelper, QemuHelperTuple}, - // edges::SAVED_JUMP, -}; -//============================= Struct definitions - -pub static mut INTR_OFFSET : Option = None; -pub static mut INTR_DONE : bool = true; - -// only used when inputs are injected -pub static mut NEXT_INPUT : Vec = Vec::new(); //============================= API symbols @@ -235,7 +216,7 @@ fn trigger_collection(emulator: &libafl_qemu::Qemu, edge: (GuestAddr, GuestAddr) // println!("{:?}",std::str::from_utf8(¤t_tcb.pcTaskName)); let critical : void_ptr = freertos::emu_lookup::lookup(emulator, h.critical_addr); let suspended : void_ptr = freertos::emu_lookup::lookup(emulator, h.scheduler_lock_addr); - let running : void_ptr = freertos::emu_lookup::lookup(emulator, h.scheduler_running_addr); + let _running : void_ptr = freertos::emu_lookup::lookup(emulator, h.scheduler_running_addr); systemstate.current_tcb = freertos::emu_lookup::lookup(emulator,curr_tcb_addr); // During ISRs it is only safe to extract structs if they are not currently being modified diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index 289164afb5..f14abf0aff 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -3,13 +3,11 @@ use std::collections::hash_map::DefaultHasher; use std::fmt; use hashbrown::HashSet; use libafl_bolts::HasRefCnt; -use libafl_bolts::AsSlice; use libafl_qemu::GuestAddr; use std::hash::Hasher; use std::hash::Hash; use hashbrown::HashMap; use serde::{Deserialize, Serialize}; -use std::rc::Rc; use freertos::TCB_t; @@ -17,7 +15,6 @@ pub mod freertos; pub mod helpers; pub mod observers; pub mod feedbacks; -pub mod graph; pub mod schedulers; pub mod stg; diff --git a/fuzzers/FRET/src/systemstate/observers.rs b/fuzzers/FRET/src/systemstate/observers.rs index f01cdeee0b..693a4dd732 100644 --- a/fuzzers/FRET/src/systemstate/observers.rs +++ b/fuzzers/FRET/src/systemstate/observers.rs @@ -1,4 +1,3 @@ -// use crate::systemstate::IRQ_INPUT_BYTES_NUMBER; use libafl::prelude::ExitKind; use libafl::{inputs::HasTargetBytes, prelude::UsesInput}; use libafl_bolts::HasLen; @@ -54,11 +53,11 @@ where fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> { // unsafe {self.last_run = invalidate_ineffective_isr(refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC));} unsafe { - let mut temp = refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC); + let temp = refine_system_states(CURRENT_SYSTEMSTATE_VEC.drain(..).collect()); // fix_broken_trace(&mut temp.1); self.last_run = temp.0.clone(); // println!("{:?}",temp); - let mut temp = states2intervals(temp.0, temp.1); + let temp = states2intervals(temp.0, temp.1); self.last_trace = temp.0; self.last_states = temp.1; self.success = temp.2; @@ -138,7 +137,7 @@ fn tcb_list_to_vec_cached(list: List_t, dump: &mut HashMap) -> ret } /// Drains a List of raw SystemStates to produce a refined trace -fn refine_system_states(input: &mut Vec) -> (Vec, Vec<(u64, CaptureEvent, String, (u32, u32))>) { +fn refine_system_states(mut input: Vec) -> (Vec, Vec<(u64, CaptureEvent, String, (u32, u32))>) { let mut ret = (Vec::<_>::new(), Vec::<_>::new()); for mut i in input.drain(..) { let cur = RefinedTCB::from_tcb_owned(i.current_tcb); @@ -354,39 +353,39 @@ fn add_abb_info(trace: &mut Vec, table: &HashMap, Option))>) { - for i in meta.iter_mut() { - if i.1 == CaptureEvent::APIStart && i.2.ends_with("FromISR") { - i.1 = CaptureEvent::ISREnd; - i.2 = "isr_starter".to_string(); - } - } -} +// /// restore the isr/api begin/end invariant +// fn fix_broken_trace(meta: &mut Vec<(u64, CaptureEvent, String, (Option, Option))>) { +// for i in meta.iter_mut() { +// if i.1 == CaptureEvent::APIStart && i.2.ends_with("FromISR") { +// i.1 = CaptureEvent::ISREnd; +// i.2 = "isr_starter".to_string(); +// } +// } +// } -/// invalidate subsequent intervals of equal states where an ISREnd follows an ISRStart. If the interrupt had no effect on the system we, are not interested. -fn invalidate_ineffective_isr(trace: &mut Vec) { - let mut i = 0; - while i < trace.len() - 1 { - if trace[i].is_valid() && - matches!(trace[i].start_capture.0, CaptureEvent::ISRStart) && matches!(trace[i].end_capture.0, CaptureEvent::ISREnd) && - trace[i].start_capture.1 == trace[i].end_capture.1 && trace[i].start_state == trace[i].end_state - { - trace[i].invaildate(); - } - } -} +// /// invalidate subsequent intervals of equal states where an ISREnd follows an ISRStart. If the interrupt had no effect on the system we, are not interested. +// fn invalidate_ineffective_isr(trace: &mut Vec) { +// let mut i = 0; +// while i < trace.len() - 1 { +// if trace[i].is_valid() && +// matches!(trace[i].start_capture.0, CaptureEvent::ISRStart) && matches!(trace[i].end_capture.0, CaptureEvent::ISREnd) && +// trace[i].start_capture.1 == trace[i].end_capture.1 && trace[i].start_state == trace[i].end_state +// { +// trace[i].invaildate(); +// } +// } +// } -/// merge a sequence of intervals of the same state+abb. jump over all invalid blocks. -fn merge_subsequent_abbs(trace: &mut Vec) { - let mut i = 1; - let mut lst_valid=0; - while i < trace.len() - 1 { - if trace[i].is_valid() { - let mut temp = trace[i].clone(); - trace[lst_valid].try_unite_with_later_interval(&mut temp); - trace[i] = temp; - lst_valid = i; - } - } -} \ No newline at end of file +// /// merge a sequence of intervals of the same state+abb. jump over all invalid blocks. +// fn merge_subsequent_abbs(trace: &mut Vec) { +// let mut i = 1; +// let mut lst_valid=0; +// while i < trace.len() - 1 { +// if trace[i].is_valid() { +// let mut temp = trace[i].clone(); +// trace[lst_valid].try_unite_with_later_interval(&mut temp); +// trace[i] = temp; +// lst_valid = i; +// } +// } +// } \ No newline at end of file diff --git a/fuzzers/FRET/src/systemstate/schedulers.rs b/fuzzers/FRET/src/systemstate/schedulers.rs index 6ef96054ad..30518c0de2 100644 --- a/fuzzers/FRET/src/systemstate/schedulers.rs +++ b/fuzzers/FRET/src/systemstate/schedulers.rs @@ -1,14 +1,14 @@ //! The Minimizer schedulers are a family of corpus schedulers that feed the fuzzer //! with testcases only from a subset of the total corpus. -use core::{marker::PhantomData}; -use std::{cmp::{max, min}, mem::swap, borrow::BorrowMut}; +use core::marker::PhantomData; +use std::{cmp::{max, min}, mem::swap}; use serde::{Deserialize, Serialize}; -use libafl_bolts::{rands::Rand, serdeany::SerdeAny, AsSlice, HasRefCnt, HasLen}; +use libafl_bolts::{rands::Rand, HasLen}; use libafl::{ - corpus::{Corpus, Testcase}, + corpus::Corpus, inputs::UsesInput, schedulers::{Scheduler, TestcaseScore, minimizer::DEFAULT_SKIP_NON_FAVORED_PROB }, state::{HasCorpus, HasRand, UsesState, State}, @@ -40,7 +40,7 @@ impl LongestTracesMetadata { #[derive(Debug, Clone)] pub struct LongestTraceScheduler { base: CS, - skip_non_favored_prob: usize, + skip_non_favored_prob: f64, } impl UsesState for LongestTraceScheduler @@ -104,7 +104,7 @@ where .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().below(100) < self.skip_non_favored_prob + } && state.rand_mut().coinflip(self.skip_non_favored_prob) { idx = self.base.next(state)?; } @@ -128,10 +128,11 @@ where par as u64 } } + #[allow(unused)] pub fn new(base: CS) -> Self { Self { base, - skip_non_favored_prob: (DEFAULT_SKIP_NON_FAVORED_PROB * 100.0) as usize, + skip_non_favored_prob: DEFAULT_SKIP_NON_FAVORED_PROB, } } } @@ -175,15 +176,15 @@ where /// if current_gen is empty, swap lists, sort by FavFactor, take top k and return first fn next(&mut self, state: &mut Self::State) -> Result { let mut to_remove : Vec<(usize, f64)> = vec![]; - let mut to_return : usize = 0; + let mut _to_return : usize = 0; let corpus_len = state.corpus().count(); - let mut current_len = 0; + let mut _current_len = 0; let gm = state.metadata_map_mut().get_mut::().expect("Corpus Scheduler empty"); // println!("index: {} curr: {:?} next: {:?} gen: {} corp: {}", gm.current_cursor, gm.current_gen.len(), gm.next_gen.len(), gm.gen, // c); match gm.current_gen.get(gm.current_cursor) { Some(c) => { - current_len = gm.current_gen.len(); + _current_len = gm.current_gen.len(); gm.current_cursor+=1; // println!("normal next: {}", (*c).0); return Ok((*c).0.into()) @@ -201,25 +202,25 @@ where // for i in 0..gm.current_gen.len() { // gm.current_gen[i] = (i, gm.current_gen[i].1); // } - to_return = gm.current_gen.get(0).unwrap().0; + _to_return = gm.current_gen.get(0).unwrap().0; // assert_eq!(to_return, 0); gm.current_cursor=1; gm.gen+=1; - current_len = gm.current_gen.len(); + _current_len = gm.current_gen.len(); } }; // removing these elements will move all indices left by to_remove.len() // to_remove.sort_by(|x,y| x.0.cmp(&(*y).0)); // to_remove.reverse(); let cm = state.corpus_mut(); - assert_eq!(corpus_len-to_remove.len(), current_len); - assert_ne!(current_len,0); + assert_eq!(corpus_len-to_remove.len(), _current_len); + assert_ne!(_current_len,0); for i in to_remove { cm.remove(i.0.into()).unwrap(); } - assert_eq!(cm.get(to_return.into()).is_ok(),true); + assert_eq!(cm.get(_to_return.into()).is_ok(),true); // println!("switch next: {to_return}"); - return Ok(to_return.into()); + return Ok(_to_return.into()); } /// Add the new input to the next generation @@ -267,6 +268,7 @@ where impl GenerationScheduler { + #[allow(unused)] pub fn new() -> Self { Self { phantom: PhantomData,