draft: add graph feedback
This commit is contained in:
parent
4587f442d0
commit
b812e994a6
@ -1,16 +1,21 @@
|
|||||||
|
|
||||||
|
use libafl::SerdeAny;
|
||||||
/// Feedbacks organizing SystemStates as a graph
|
/// Feedbacks organizing SystemStates as a graph
|
||||||
use libafl::inputs::HasBytesVec;
|
use libafl::inputs::HasBytesVec;
|
||||||
use libafl::bolts::rands::RandomSeed;
|
use libafl::bolts::rands::RandomSeed;
|
||||||
use libafl::bolts::rands::StdRand;
|
use libafl::bolts::rands::StdRand;
|
||||||
use libafl::mutators::Mutator;
|
use libafl::mutators::Mutator;
|
||||||
use libafl::mutators::MutationResult;
|
use libafl::mutators::MutationResult;
|
||||||
|
use libafl::prelude::HasTargetBytes;
|
||||||
|
use libafl::prelude::UsesInput;
|
||||||
|
use libafl::state::HasNamedMetadata;
|
||||||
|
use libafl::state::UsesState;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use libafl::state::HasCorpus;
|
use libafl::state::HasCorpus;
|
||||||
use libafl::state::HasSolutions;
|
use libafl::state::HasSolutions;
|
||||||
use libafl::state::HasRand;
|
use libafl::state::HasRand;
|
||||||
use crate::worst::MaxExecsLenFavFactor;
|
use crate::worst::MaxExecsLenFavFactor;
|
||||||
use libafl::corpus::MinimizerCorpusScheduler;
|
use libafl::schedulers::MinimizerScheduler;
|
||||||
use libafl::bolts::HasRefCnt;
|
use libafl::bolts::HasRefCnt;
|
||||||
use libafl::bolts::AsSlice;
|
use libafl::bolts::AsSlice;
|
||||||
use libafl::bolts::ownedref::OwnedSlice;
|
use libafl::bolts::ownedref::OwnedSlice;
|
||||||
@ -33,7 +38,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use super::RefinedFreeRTOSSystemState;
|
use super::RefinedFreeRTOSSystemState;
|
||||||
use super::FreeRTOSSystemStateMetadata;
|
use super::FreeRTOSSystemStateMetadata;
|
||||||
use super::observers::QemusystemstateObserver;
|
use super::observers::QemuSystemStateObserver;
|
||||||
use petgraph::prelude::DiGraph;
|
use petgraph::prelude::DiGraph;
|
||||||
use petgraph::graph::NodeIndex;
|
use petgraph::graph::NodeIndex;
|
||||||
use petgraph::Direction;
|
use petgraph::Direction;
|
||||||
@ -124,11 +129,13 @@ impl SysGraphMetadata {
|
|||||||
Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0}
|
Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl AsSlice<usize> for SysGraphMetadata {
|
impl AsSlice for SysGraphMetadata {
|
||||||
/// Convert the slice of system-states to a slice of hashes over enumerated states
|
/// Convert the slice of system-states to a slice of hashes over enumerated states
|
||||||
fn as_slice(&self) -> &[usize] {
|
fn as_slice(&self) -> &[usize] {
|
||||||
self.indices.as_slice()
|
self.indices.as_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Entry = usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasRefCnt for SysGraphMetadata {
|
impl HasRefCnt for SysGraphMetadata {
|
||||||
@ -143,13 +150,13 @@ impl HasRefCnt for SysGraphMetadata {
|
|||||||
|
|
||||||
libafl::impl_serdeany!(SysGraphMetadata);
|
libafl::impl_serdeany!(SysGraphMetadata);
|
||||||
|
|
||||||
pub type GraphMaximizerCorpusScheduler<CS, I, S> =
|
pub type GraphMaximizerCorpusScheduler<CS> =
|
||||||
MinimizerCorpusScheduler<CS, MaxExecsLenFavFactor<I>, I, SysGraphMetadata, S>;
|
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>,SysGraphMetadata>;
|
||||||
|
|
||||||
//============================= Graph Feedback
|
//============================= Graph Feedback
|
||||||
|
|
||||||
/// Improved System State Graph
|
/// Improved System State Graph
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Default, SerdeAny)]
|
||||||
pub struct SysGraphFeedbackState
|
pub struct SysGraphFeedbackState
|
||||||
{
|
{
|
||||||
pub graph: DiGraph<SysGraphNode, ()>,
|
pub graph: DiGraph<SysGraphNode, ()>,
|
||||||
@ -226,7 +233,7 @@ impl Named for SysGraphFeedbackState
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl FeedbackState for SysGraphFeedbackState
|
impl SysGraphFeedbackState
|
||||||
{
|
{
|
||||||
fn reset(&mut self) -> Result<(), Error> {
|
fn reset(&mut self) -> Result<(), Error> {
|
||||||
self.graph.clear();
|
self.graph.clear();
|
||||||
@ -253,28 +260,29 @@ impl SysMapFeedback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, S> Feedback<I, S> for SysMapFeedback
|
impl<S> Feedback<S> for SysMapFeedback
|
||||||
where
|
where
|
||||||
I: Input,
|
S: UsesInput + HasClientPerfMonitor + HasNamedMetadata,
|
||||||
S: HasClientPerfMonitor + HasFeedbackStates,
|
S::Input: HasTargetBytes,
|
||||||
{
|
{
|
||||||
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
_manager: &mut EM,
|
_manager: &mut EM,
|
||||||
_input: &I,
|
_input: &S::Input,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I>,
|
EM: EventFirer<State = S>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
let observer = observers.match_name::<QemusystemstateObserver>("systemstate")
|
let observer = observers.match_name::<QemuSystemStateObserver>("systemstate")
|
||||||
.expect("QemusystemstateObserver not found");
|
.expect("QemusystemstateObserver not found");
|
||||||
let feedbackstate = state
|
let feedbackstate = state
|
||||||
.feedback_states_mut()
|
.named_metadata_mut()
|
||||||
.match_name_mut::<SysGraphFeedbackState>("SysMap")
|
.get_mut::<SysGraphFeedbackState>("SysMap")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ret = feedbackstate.update(&observer.last_run, &observer.last_input);
|
let ret = feedbackstate.update(&observer.last_run, &observer.last_input);
|
||||||
self.last_trace = Some(ret.1);
|
self.last_trace = Some(ret.1);
|
||||||
@ -283,7 +291,7 @@ where
|
|||||||
|
|
||||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||||
#[inline]
|
#[inline]
|
||||||
fn append_metadata(&mut self, _state: &mut S, testcase: &mut Testcase<I>) -> Result<(), Error> {
|
fn append_metadata(&mut self, _state: &mut S, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
|
||||||
let a = self.last_trace.take();
|
let a = self.last_trace.take();
|
||||||
match a {
|
match a {
|
||||||
Some(s) => testcase.metadata_mut().insert(SysGraphMetadata::new(s)),
|
Some(s) => testcase.metadata_mut().insert(SysGraphMetadata::new(s)),
|
||||||
@ -294,7 +302,7 @@ where
|
|||||||
|
|
||||||
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
||||||
#[inline]
|
#[inline]
|
||||||
fn discard_metadata(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
fn discard_metadata(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
||||||
self.last_trace = None;
|
self.last_trace = None;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -309,282 +317,282 @@ impl Named for SysMapFeedback
|
|||||||
|
|
||||||
//============================= Mutators
|
//============================= Mutators
|
||||||
//=============================== Snippets
|
//=============================== Snippets
|
||||||
pub struct RandGraphSnippetMutator<I, S>
|
// pub struct RandGraphSnippetMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
phantom: PhantomData<(I, S)>,
|
// phantom: PhantomData<(I, S)>,
|
||||||
}
|
// }
|
||||||
impl<I, S> RandGraphSnippetMutator<I, S>
|
// impl<I, S> RandGraphSnippetMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
pub fn new() -> Self {
|
// pub fn new() -> Self {
|
||||||
RandGraphSnippetMutator{phantom: PhantomData}
|
// RandGraphSnippetMutator{phantom: PhantomData}
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
impl<I, S> Mutator<I, S> for RandGraphSnippetMutator<I, S>
|
// impl<I, S> Mutator<I, S> for RandGraphSnippetMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I> + HasFeedbackStates,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
fn mutate(
|
// fn mutate(
|
||||||
&mut self,
|
// &mut self,
|
||||||
state: &mut S,
|
// state: &mut S,
|
||||||
input: &mut I,
|
// input: &mut I,
|
||||||
_stage_idx: i32
|
// _stage_idx: i32
|
||||||
) -> Result<MutationResult, Error>
|
// ) -> Result<MutationResult, Error>
|
||||||
{
|
// {
|
||||||
// need our own random generator, because borrowing rules
|
// // need our own random generator, because borrowing rules
|
||||||
let mut myrand = StdRand::new();
|
// let mut myrand = StdRand::new();
|
||||||
let tmp = &mut state.rand_mut();
|
// let tmp = &mut state.rand_mut();
|
||||||
myrand.set_seed(tmp.next());
|
// myrand.set_seed(tmp.next());
|
||||||
drop(tmp);
|
// drop(tmp);
|
||||||
|
|
||||||
let feedbackstate = state
|
// let feedbackstate = state
|
||||||
.feedback_states()
|
// .feedback_states()
|
||||||
.match_name::<SysGraphFeedbackState>("SysMap")
|
// .match_name::<SysGraphFeedbackState>("SysMap")
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
let g = &feedbackstate.graph;
|
// let g = &feedbackstate.graph;
|
||||||
let tmp = state.metadata().get::<SysGraphMetadata>();
|
// let tmp = state.metadata().get::<SysGraphMetadata>();
|
||||||
if tmp.is_none() { // if there are no metadata it was probably not interesting anyways
|
// if tmp.is_none() { // if there are no metadata it was probably not interesting anyways
|
||||||
return Ok(MutationResult::Skipped);
|
// return Ok(MutationResult::Skipped);
|
||||||
}
|
// }
|
||||||
let trace =tmp.expect("SysGraphMetadata not found");
|
// let trace =tmp.expect("SysGraphMetadata not found");
|
||||||
// follow the path, extract snippets from last reads, find common snippets.
|
// // follow the path, extract snippets from last reads, find common snippets.
|
||||||
// those are likley keys parts. choose random parts from other sibling traces
|
// // 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 sibling_inputs : Vec<&Vec<u8>>= g[*trace.inner.last().unwrap()].variants.iter().map(|x| &x.input).collect();
|
||||||
let mut snippet_collector = vec![];
|
// let mut snippet_collector = vec![];
|
||||||
let mut per_input_counters = HashMap::<&Vec<u8>,usize>::new(); // ugly workaround to track multiple inputs
|
// let mut per_input_counters = HashMap::<&Vec<u8>,usize>::new(); // ugly workaround to track multiple inputs
|
||||||
for t in &trace.inner {
|
// for t in &trace.inner {
|
||||||
let node = &g[*t];
|
// let node = &g[*t];
|
||||||
let mut per_node_snippets = HashMap::<&Vec<u8>,&[u8]>::new();
|
// let mut per_node_snippets = HashMap::<&Vec<u8>,&[u8]>::new();
|
||||||
for v in &node.variants {
|
// for v in &node.variants {
|
||||||
match per_input_counters.get_mut(&v.input) {
|
// match per_input_counters.get_mut(&v.input) {
|
||||||
None => {
|
// None => {
|
||||||
if sibling_inputs.iter().any(|x| *x==&v.input) { // only collect info about siblin inputs from target
|
// 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());
|
// per_input_counters.insert(&v.input, v.input_counter.try_into().unwrap());
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
Some(x) => {
|
// Some(x) => {
|
||||||
let x_u = *x;
|
// let x_u = *x;
|
||||||
if x_u<v.input_counter as usize {
|
// if x_u<v.input_counter as usize {
|
||||||
*x=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]);
|
// per_node_snippets.insert(&v.input,&v.input[x_u..v.input_counter as usize]);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
snippet_collector.push(per_node_snippets);
|
// snippet_collector.push(per_node_snippets);
|
||||||
}
|
// }
|
||||||
let mut new_input : Vec<u8> = vec![];
|
// let mut new_input : Vec<u8> = vec![];
|
||||||
for c in snippet_collector {
|
// for c in snippet_collector {
|
||||||
new_input.extend_from_slice(myrand.choose(c).1);
|
// new_input.extend_from_slice(myrand.choose(c).1);
|
||||||
}
|
// }
|
||||||
for i in new_input.iter().enumerate() {
|
// for i in new_input.iter().enumerate() {
|
||||||
input.bytes_mut()[i.0]=*i.1;
|
// input.bytes_mut()[i.0]=*i.1;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(MutationResult::Mutated)
|
// Ok(MutationResult::Mutated)
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn post_exec(
|
// fn post_exec(
|
||||||
&mut self,
|
// &mut self,
|
||||||
_state: &mut S,
|
// _state: &mut S,
|
||||||
_stage_idx: i32,
|
// _stage_idx: i32,
|
||||||
_corpus_idx: Option<usize>
|
// _corpus_idx: Option<usize>
|
||||||
) -> Result<(), Error> {
|
// ) -> Result<(), Error> {
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<I, S> Named for RandGraphSnippetMutator<I, S>
|
// impl<I, S> Named for RandGraphSnippetMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I> + HasFeedbackStates,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
fn name(&self) -> &str {
|
// fn name(&self) -> &str {
|
||||||
"RandGraphSnippetMutator"
|
// "RandGraphSnippetMutator"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
//=============================== Snippets
|
// //=============================== Snippets
|
||||||
pub struct RandInputSnippetMutator<I, S>
|
// pub struct RandInputSnippetMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
phantom: PhantomData<(I, S)>,
|
// phantom: PhantomData<(I, S)>,
|
||||||
}
|
// }
|
||||||
impl<I, S> RandInputSnippetMutator<I, S>
|
// impl<I, S> RandInputSnippetMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
pub fn new() -> Self {
|
// pub fn new() -> Self {
|
||||||
RandInputSnippetMutator{phantom: PhantomData}
|
// RandInputSnippetMutator{phantom: PhantomData}
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
impl<I, S> Mutator<I, S> for RandInputSnippetMutator<I, S>
|
// impl<I, S> Mutator<I, S> for RandInputSnippetMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I> + HasFeedbackStates,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
fn mutate(
|
// fn mutate(
|
||||||
&mut self,
|
// &mut self,
|
||||||
state: &mut S,
|
// state: &mut S,
|
||||||
input: &mut I,
|
// input: &mut I,
|
||||||
_stage_idx: i32
|
// _stage_idx: i32
|
||||||
) -> Result<MutationResult, Error>
|
// ) -> Result<MutationResult, Error>
|
||||||
{
|
// {
|
||||||
// need our own random generator, because borrowing rules
|
// // need our own random generator, because borrowing rules
|
||||||
let mut myrand = StdRand::new();
|
// let mut myrand = StdRand::new();
|
||||||
let tmp = &mut state.rand_mut();
|
// let tmp = &mut state.rand_mut();
|
||||||
myrand.set_seed(tmp.next());
|
// myrand.set_seed(tmp.next());
|
||||||
drop(tmp);
|
// drop(tmp);
|
||||||
|
|
||||||
let feedbackstate = state
|
// let feedbackstate = state
|
||||||
.feedback_states()
|
// .feedback_states()
|
||||||
.match_name::<SysGraphFeedbackState>("SysMap")
|
// .match_name::<SysGraphFeedbackState>("SysMap")
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
let g = &feedbackstate.graph;
|
// let g = &feedbackstate.graph;
|
||||||
let tmp = state.metadata().get::<SysGraphMetadata>();
|
// let tmp = state.metadata().get::<SysGraphMetadata>();
|
||||||
if tmp.is_none() { // if there are no metadata it was probably not interesting anyways
|
// if tmp.is_none() { // if there are no metadata it was probably not interesting anyways
|
||||||
return Ok(MutationResult::Skipped);
|
// return Ok(MutationResult::Skipped);
|
||||||
}
|
// }
|
||||||
let trace = tmp.expect("SysGraphMetadata not found");
|
// let trace = tmp.expect("SysGraphMetadata not found");
|
||||||
|
|
||||||
let mut collection : Vec<Vec<u8>> = Vec::new();
|
// let mut collection : Vec<Vec<u8>> = Vec::new();
|
||||||
let mut current_pointer : usize = 0;
|
// let mut current_pointer : usize = 0;
|
||||||
for t in &trace.inner {
|
// for t in &trace.inner {
|
||||||
let node = &g[*t];
|
// let node = &g[*t];
|
||||||
for v in &node.variants {
|
// for v in &node.variants {
|
||||||
if v.input == input.bytes() {
|
// if v.input == input.bytes() {
|
||||||
if v.input_counter > current_pointer.try_into().unwrap() {
|
// if v.input_counter > current_pointer.try_into().unwrap() {
|
||||||
collection.push(v.input[current_pointer..v.input_counter as usize].to_owned());
|
// collection.push(v.input[current_pointer..v.input_counter as usize].to_owned());
|
||||||
current_pointer = v.input_counter as usize;
|
// current_pointer = v.input_counter as usize;
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
let index_to_mutate = myrand.below(collection.len() as u64) as usize;
|
// let index_to_mutate = myrand.below(collection.len() as u64) as usize;
|
||||||
for i in 0..collection[index_to_mutate].len() {
|
// for i in 0..collection[index_to_mutate].len() {
|
||||||
collection[index_to_mutate][i] = myrand.below(0xFF) as u8;
|
// collection[index_to_mutate][i] = myrand.below(0xFF) as u8;
|
||||||
}
|
// }
|
||||||
for i in collection.concat().iter().enumerate() {
|
// for i in collection.concat().iter().enumerate() {
|
||||||
input.bytes_mut()[i.0]=*i.1;
|
// input.bytes_mut()[i.0]=*i.1;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(MutationResult::Mutated)
|
// Ok(MutationResult::Mutated)
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn post_exec(
|
// fn post_exec(
|
||||||
&mut self,
|
// &mut self,
|
||||||
_state: &mut S,
|
// _state: &mut S,
|
||||||
_stage_idx: i32,
|
// _stage_idx: i32,
|
||||||
_corpus_idx: Option<usize>
|
// _corpus_idx: Option<usize>
|
||||||
) -> Result<(), Error> {
|
// ) -> Result<(), Error> {
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<I, S> Named for RandInputSnippetMutator<I, S>
|
// impl<I, S> Named for RandInputSnippetMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I> + HasFeedbackStates,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
fn name(&self) -> &str {
|
// fn name(&self) -> &str {
|
||||||
"RandInputSnippetMutator"
|
// "RandInputSnippetMutator"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
//=============================== Suffix
|
// //=============================== Suffix
|
||||||
pub struct RandGraphSuffixMutator<I, S>
|
// pub struct RandGraphSuffixMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
phantom: PhantomData<(I, S)>,
|
// phantom: PhantomData<(I, S)>,
|
||||||
}
|
// }
|
||||||
impl<I, S> RandGraphSuffixMutator<I, S>
|
// impl<I, S> RandGraphSuffixMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
pub fn new() -> Self {
|
// pub fn new() -> Self {
|
||||||
RandGraphSuffixMutator{phantom: PhantomData}
|
// RandGraphSuffixMutator{phantom: PhantomData}
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
impl<I, S> Mutator<I, S> for RandGraphSuffixMutator<I, S>
|
// impl<I, S> Mutator<I, S> for RandGraphSuffixMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I> + HasFeedbackStates,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
fn mutate(
|
// fn mutate(
|
||||||
&mut self,
|
// &mut self,
|
||||||
state: &mut S,
|
// state: &mut S,
|
||||||
input: &mut I,
|
// input: &mut I,
|
||||||
_stage_idx: i32
|
// _stage_idx: i32
|
||||||
) -> Result<MutationResult, Error>
|
// ) -> Result<MutationResult, Error>
|
||||||
{
|
// {
|
||||||
// need our own random generator, because borrowing rules
|
// // need our own random generator, because borrowing rules
|
||||||
let mut myrand = StdRand::new();
|
// let mut myrand = StdRand::new();
|
||||||
let tmp = &mut state.rand_mut();
|
// let tmp = &mut state.rand_mut();
|
||||||
myrand.set_seed(tmp.next());
|
// myrand.set_seed(tmp.next());
|
||||||
drop(tmp);
|
// drop(tmp);
|
||||||
|
|
||||||
let feedbackstate = state
|
// let feedbackstate = state
|
||||||
.feedback_states()
|
// .feedback_states()
|
||||||
.match_name::<SysGraphFeedbackState>("SysMap")
|
// .match_name::<SysGraphFeedbackState>("SysMap")
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
let g = &feedbackstate.graph;
|
// let g = &feedbackstate.graph;
|
||||||
let tmp = state.metadata().get::<SysGraphMetadata>();
|
// let tmp = state.metadata().get::<SysGraphMetadata>();
|
||||||
if tmp.is_none() { // if there are no metadata it was probably not interesting anyways
|
// if tmp.is_none() { // if there are no metadata it was probably not interesting anyways
|
||||||
return Ok(MutationResult::Skipped);
|
// return Ok(MutationResult::Skipped);
|
||||||
}
|
// }
|
||||||
let trace =tmp.expect("SysGraphMetadata not found");
|
// let trace =tmp.expect("SysGraphMetadata not found");
|
||||||
// follow the path, extract snippets from last reads, find common snippets.
|
// // follow the path, extract snippets from last reads, find common snippets.
|
||||||
// those are likley keys parts. choose random parts from other sibling traces
|
// // 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 inp_c_end = g[*trace.inner.last().unwrap()].base.input_counter;
|
||||||
let mut num_to_reverse = myrand.below(trace.inner.len().try_into().unwrap());
|
// let mut num_to_reverse = myrand.below(trace.inner.len().try_into().unwrap());
|
||||||
for t in trace.inner.iter().rev() {
|
// for t in trace.inner.iter().rev() {
|
||||||
let int_c_prefix = g[*t].base.input_counter;
|
// let int_c_prefix = g[*t].base.input_counter;
|
||||||
if int_c_prefix < inp_c_end {
|
// if int_c_prefix < inp_c_end {
|
||||||
num_to_reverse-=1;
|
// num_to_reverse-=1;
|
||||||
if num_to_reverse<=0 {
|
// if num_to_reverse<=0 {
|
||||||
let mut new_input=input.bytes()[..(int_c_prefix as usize)].to_vec();
|
// 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();
|
// let mut ext : Vec<u8> = (int_c_prefix..inp_c_end).map(|_| myrand.next().to_le_bytes()).flatten().collect();
|
||||||
new_input.append(&mut ext);
|
// new_input.append(&mut ext);
|
||||||
for i in new_input.iter().enumerate() {
|
// for i in new_input.iter().enumerate() {
|
||||||
if input.bytes_mut().len()>i.0 {
|
// if input.bytes_mut().len()>i.0 {
|
||||||
input.bytes_mut()[i.0]=*i.1;
|
// input.bytes_mut()[i.0]=*i.1;
|
||||||
}
|
// }
|
||||||
else { break };
|
// else { break };
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Ok(MutationResult::Mutated)
|
// Ok(MutationResult::Mutated)
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn post_exec(
|
// fn post_exec(
|
||||||
&mut self,
|
// &mut self,
|
||||||
_state: &mut S,
|
// _state: &mut S,
|
||||||
_stage_idx: i32,
|
// _stage_idx: i32,
|
||||||
_corpus_idx: Option<usize>
|
// _corpus_idx: Option<usize>
|
||||||
) -> Result<(), Error> {
|
// ) -> Result<(), Error> {
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<I, S> Named for RandGraphSuffixMutator<I, S>
|
// impl<I, S> Named for RandGraphSuffixMutator<I, S>
|
||||||
where
|
// where
|
||||||
I: Input + HasBytesVec,
|
// I: Input + HasBytesVec,
|
||||||
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I> + HasFeedbackStates,
|
// S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
|
||||||
{
|
// {
|
||||||
fn name(&self) -> &str {
|
// fn name(&self) -> &str {
|
||||||
"RandGraphSuffixMutator"
|
// "RandGraphSuffixMutator"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
@ -13,7 +13,7 @@ pub mod freertos;
|
|||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
pub mod observers;
|
pub mod observers;
|
||||||
pub mod feedbacks;
|
pub mod feedbacks;
|
||||||
// pub mod graph;
|
pub mod graph;
|
||||||
// pub mod mutators;
|
// pub mod mutators;
|
||||||
|
|
||||||
#[cfg(feature = "fuzz_interrupt")]
|
#[cfg(feature = "fuzz_interrupt")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user