628 lines
22 KiB
Rust
628 lines
22 KiB
Rust
|
|
use libafl::SerdeAny;
|
|
/// Feedbacks organizing SystemStates as a graph
|
|
use libafl::inputs::HasBytesVec;
|
|
use libafl_bolts::rands::RandomSeed;
|
|
use libafl_bolts::rands::StdRand;
|
|
use libafl::mutators::Mutator;
|
|
use libafl::mutators::MutationResult;
|
|
use libafl::prelude::HasTargetBytes;
|
|
use libafl::prelude::UsesInput;
|
|
use libafl::state::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, state::HasMetadata};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use super::RefinedFreeRTOSSystemState;
|
|
use super::FreeRTOSSystemStateMetadata;
|
|
use super::observers::QemuSystemStateObserver;
|
|
use petgraph::prelude::DiGraph;
|
|
use petgraph::graph::NodeIndex;
|
|
use petgraph::Direction;
|
|
use std::cmp::Ordering;
|
|
|
|
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<u8>, // in the end any kind of input are bytes, regardless of type and lifetime
|
|
}
|
|
impl VariantTuple {
|
|
fn from(other: &RefinedFreeRTOSSystemState,input: Vec<u8>) -> Self {
|
|
VariantTuple{
|
|
start_tick: other.start_tick,
|
|
end_tick: other.end_tick,
|
|
input_counter: other.input_counter,
|
|
input: input,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
|
pub struct SysGraphNode
|
|
{
|
|
base: RefinedFreeRTOSSystemState,
|
|
pub variants: Vec<VariantTuple>,
|
|
}
|
|
impl SysGraphNode {
|
|
fn from(base: RefinedFreeRTOSSystemState, input: Vec<u8>) -> 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: &RefinedFreeRTOSSystemState, input: &Vec<u8>) -> 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: &RefinedFreeRTOSSystemState, input: &Vec<u8>) -> bool {
|
|
if &self.base!=other {return false;}
|
|
let interesting =
|
|
self.variants.iter().all(|x| x.end_tick-x.start_tick<other.end_tick-other.start_tick) || // longest variant
|
|
self.variants.iter().all(|x| x.end_tick-x.start_tick>other.end_tick-other.start_tick) || // shortest variant
|
|
self.variants.iter().all(|x| x.input_counter>other.input_counter) || // longest input
|
|
self.variants.iter().all(|x| x.input_counter<other.input_counter); // shortest input
|
|
if interesting {
|
|
let var = VariantTuple::from(other, input.clone());
|
|
self.variants.push(var);
|
|
}
|
|
return interesting;
|
|
}
|
|
pub fn get_taskname(&self) -> &str {
|
|
&self.base.current_task.0.task_name
|
|
}
|
|
pub fn get_input_counts(&self) -> Vec<u32> {
|
|
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.0.task_name,&self.base.current_task.1));
|
|
ret.push_str(";Rl:");
|
|
for i in &self.base.ready_list_after {
|
|
ret.push_str(&format!(";{}#{}",i.0.task_name,i.1));
|
|
}
|
|
ret.push_str(";Dl:");
|
|
for i in &self.base.delay_list_after {
|
|
ret.push_str(&format!(";{}#{}",i.0.task_name,i.1));
|
|
}
|
|
// println!("{}",ret);
|
|
ret
|
|
}
|
|
}
|
|
impl PartialEq for SysGraphNode {
|
|
fn eq(&self, other: &SysGraphNode) -> bool {
|
|
self.base==other.base
|
|
}
|
|
}
|
|
|
|
// Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata
|
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
|
pub struct SysGraphMetadata {
|
|
pub inner: Vec<NodeIndex>,
|
|
indices: Vec<usize>,
|
|
tcref: isize,
|
|
}
|
|
impl SysGraphMetadata {
|
|
pub fn new(inner: Vec<NodeIndex>) -> 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<CS> =
|
|
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,SysGraphMetadata>;
|
|
|
|
//============================= Graph Feedback
|
|
|
|
/// Improved System State Graph
|
|
#[derive(Serialize, Deserialize, Clone, Debug, SerdeAny)]
|
|
pub struct SysGraphFeedbackState
|
|
{
|
|
pub graph: DiGraph<SysGraphNode, ()>,
|
|
entrypoint: NodeIndex,
|
|
exit: NodeIndex,
|
|
name: String,
|
|
}
|
|
impl SysGraphFeedbackState
|
|
{
|
|
pub fn new() -> Self {
|
|
let mut graph = DiGraph::<SysGraphNode, ()>::new();
|
|
let mut entry = SysGraphNode::default();
|
|
entry.base.current_task.0.task_name="Start".to_string();
|
|
let mut exit = SysGraphNode::default();
|
|
exit.base.current_task.0.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: String::from("SysMap")}
|
|
}
|
|
fn insert(&mut self, list: Vec<RefinedFreeRTOSSystemState>, input: &Vec<u8>) {
|
|
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<RefinedFreeRTOSSystemState>], return true if the path was interesting
|
|
fn update(&mut self, list: &Vec<RefinedFreeRTOSSystemState>, input: &Vec<u8>) -> (bool, Vec<NodeIndex>) {
|
|
let mut current_index = self.entrypoint;
|
|
let mut novel = false;
|
|
let mut trace : Vec<NodeIndex> = vec![current_index];
|
|
for n in list {
|
|
let mut matching : Option<NodeIndex> = 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) -> &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.0.task_name="Start".to_string();
|
|
let mut exit = SysGraphNode::default();
|
|
exit.base.current_task.0.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: String,
|
|
last_trace: Option<Vec<NodeIndex>>,
|
|
}
|
|
impl SysMapFeedback {
|
|
pub fn new() -> Self {
|
|
Self {name: String::from("SysMapFeedback"), last_trace: None }
|
|
}
|
|
}
|
|
|
|
impl<S> Feedback<S> for SysMapFeedback
|
|
where
|
|
S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
|
|
S::Input: HasTargetBytes,
|
|
{
|
|
#[allow(clippy::wrong_self_convention)]
|
|
fn is_interesting<EM, OT>(
|
|
&mut self,
|
|
state: &mut S,
|
|
_manager: &mut EM,
|
|
_input: &S::Input,
|
|
observers: &OT,
|
|
_exit_kind: &ExitKind,
|
|
) -> Result<bool, Error>
|
|
where
|
|
EM: EventFirer<State = S>,
|
|
OT: ObserversTuple<S>,
|
|
{
|
|
let observer = observers.match_name::<QemuSystemStateObserver>("systemstate")
|
|
.expect("QemuSystemStateObserver not found");
|
|
let feedbackstate = match state
|
|
.named_metadata_map_mut()
|
|
.get_mut::<SysGraphFeedbackState>("SysMap") {
|
|
Some(s) => s,
|
|
None => {
|
|
let n=SysGraphFeedbackState::default();
|
|
state.named_metadata_map_mut().insert(n, "SysMap");
|
|
state.named_metadata_map_mut().get_mut::<SysGraphFeedbackState>("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<OT>(&mut self, _state: &mut S, _observers: &OT, testcase: &mut Testcase<S::Input>) -> 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) -> &str {
|
|
&self.name
|
|
}
|
|
}
|
|
|
|
//============================= Mutators
|
|
//=============================== Snippets
|
|
// pub struct RandGraphSnippetMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// phantom: PhantomData<(I, S)>,
|
|
// }
|
|
// impl<I, S> RandGraphSnippetMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// pub fn new() -> Self {
|
|
// RandGraphSnippetMutator{phantom: PhantomData}
|
|
// }
|
|
// }
|
|
// impl<I, S> Mutator<I, S> for RandGraphSnippetMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// fn mutate(
|
|
// &mut self,
|
|
// state: &mut S,
|
|
// input: &mut I,
|
|
// _stage_idx: i32
|
|
// ) -> Result<MutationResult, Error>
|
|
// {
|
|
// // 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::<SysGraphFeedbackState>("SysMap")
|
|
// .unwrap();
|
|
// let g = &feedbackstate.graph;
|
|
// let tmp = state.metadata().get::<SysGraphMetadata>();
|
|
// 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<u8>>= g[*trace.inner.last().unwrap()].variants.iter().map(|x| &x.input).collect();
|
|
// let mut snippet_collector = vec![];
|
|
// let mut per_input_counters = HashMap::<&Vec<u8>,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>,&[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<v.input_counter as usize {
|
|
// *x=v.input_counter as usize;
|
|
// per_node_snippets.insert(&v.input,&v.input[x_u..v.input_counter as usize]);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// snippet_collector.push(per_node_snippets);
|
|
// }
|
|
// let mut new_input : Vec<u8> = 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<usize>
|
|
// ) -> Result<(), Error> {
|
|
// Ok(())
|
|
// }
|
|
// }
|
|
|
|
// impl<I, S> Named for RandGraphSnippetMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// fn name(&self) -> &str {
|
|
// "RandGraphSnippetMutator"
|
|
// }
|
|
// }
|
|
// //=============================== Snippets
|
|
// pub struct RandInputSnippetMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// phantom: PhantomData<(I, S)>,
|
|
// }
|
|
// impl<I, S> RandInputSnippetMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// pub fn new() -> Self {
|
|
// RandInputSnippetMutator{phantom: PhantomData}
|
|
// }
|
|
// }
|
|
// impl<I, S> Mutator<I, S> for RandInputSnippetMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// fn mutate(
|
|
// &mut self,
|
|
// state: &mut S,
|
|
// input: &mut I,
|
|
// _stage_idx: i32
|
|
// ) -> Result<MutationResult, Error>
|
|
// {
|
|
// // 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::<SysGraphFeedbackState>("SysMap")
|
|
// .unwrap();
|
|
// let g = &feedbackstate.graph;
|
|
// let tmp = state.metadata().get::<SysGraphMetadata>();
|
|
// 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<u8>> = 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<usize>
|
|
// ) -> Result<(), Error> {
|
|
// Ok(())
|
|
// }
|
|
// }
|
|
|
|
// impl<I, S> Named for RandInputSnippetMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// fn name(&self) -> &str {
|
|
// "RandInputSnippetMutator"
|
|
// }
|
|
// }
|
|
// //=============================== Suffix
|
|
// pub struct RandGraphSuffixMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// phantom: PhantomData<(I, S)>,
|
|
// }
|
|
// impl<I, S> RandGraphSuffixMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// pub fn new() -> Self {
|
|
// RandGraphSuffixMutator{phantom: PhantomData}
|
|
// }
|
|
// }
|
|
// impl<I, S> Mutator<I, S> for RandGraphSuffixMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// fn mutate(
|
|
// &mut self,
|
|
// state: &mut S,
|
|
// input: &mut I,
|
|
// _stage_idx: i32
|
|
// ) -> Result<MutationResult, Error>
|
|
// {
|
|
// // 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::<SysGraphFeedbackState>("SysMap")
|
|
// .unwrap();
|
|
// let g = &feedbackstate.graph;
|
|
// let tmp = state.metadata().get::<SysGraphMetadata>();
|
|
// 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<u8> = (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<usize>
|
|
// ) -> Result<(), Error> {
|
|
// Ok(())
|
|
// }
|
|
// }
|
|
|
|
// impl<I, S> Named for RandGraphSuffixMutator<I, S>
|
|
// where
|
|
// I: Input + HasBytesVec,
|
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
|
// {
|
|
// fn name(&self) -> &str {
|
|
// "RandGraphSuffixMutator"
|
|
// }
|
|
// }
|