add RandGraphSnippetMutator

This commit is contained in:
Alwin Berger 2022-03-23 01:37:04 +01:00
parent 66babddb02
commit 4e3acf85ad
2 changed files with 124 additions and 3 deletions

View File

@ -1,5 +1,6 @@
//! A singlethreaded QEMU fuzzer that can auto-restart. //! A singlethreaded QEMU fuzzer that can auto-restart.
use wcet_qemu_sys::sysstate::graph::RandGraphSnippetMutator;
use wcet_qemu_sys::sysstate::graph::GraphMaximizerCorpusScheduler; use wcet_qemu_sys::sysstate::graph::GraphMaximizerCorpusScheduler;
use wcet_qemu_sys::sysstate::graph::SysMapFeedback; use wcet_qemu_sys::sysstate::graph::SysMapFeedback;
use wcet_qemu_sys::sysstate::graph::SysGraphFeedbackState; use wcet_qemu_sys::sysstate::graph::SysGraphFeedbackState;
@ -391,7 +392,10 @@ fn fuzz(
// let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); // let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new(&mut state, havoc_mutations().merge(tokens_mutations()), 5)?; let mutator = StdMOptMutator::new(&mut state, havoc_mutations()
.merge(tokens_mutations())
.merge(tuple_list!(RandGraphSnippetMutator::new())),
5)?;
// let power = PowerMutationalStage::new(mutator, PowerSchedule::FAST, &edges_observer); // let power = PowerMutationalStage::new(mutator, PowerSchedule::FAST, &edges_observer);
let mutation = StdMutationalStage::new(mutator); let mutation = StdMutationalStage::new(mutator);

View File

@ -1,5 +1,14 @@
/// Feedbacks organizing SystemStates as a graph /// 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 core::marker::PhantomData;
use libafl::state::HasCorpus;
use libafl::state::HasSolutions;
use libafl::state::HasRand;
use crate::worst::MaxExecsLenFavFactor; use crate::worst::MaxExecsLenFavFactor;
use libafl::corpus::MinimizerCorpusScheduler; use libafl::corpus::MinimizerCorpusScheduler;
use libafl::bolts::HasRefCnt; use libafl::bolts::HasRefCnt;
@ -32,6 +41,10 @@ use petgraph::graph::NodeIndex;
use petgraph::Direction; use petgraph::Direction;
use std::cmp::Ordering; use std::cmp::Ordering;
use libafl::bolts::rands::Rand;
use rand::SeedableRng;
use rand::seq::SliceRandom;
//============================= Data Structures //============================= Data Structures
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
struct VariantTuple struct VariantTuple
@ -100,12 +113,13 @@ impl PartialEq for SysGraphNode {
// Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata // Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct SysGraphMetadata { pub struct SysGraphMetadata {
indices: Vec<usize>, // Hashed enumeration of States inner: Vec<NodeIndex>,
indices: Vec<usize>,
tcref: isize, tcref: isize,
} }
impl SysGraphMetadata { impl SysGraphMetadata {
pub fn new(inner: Vec<NodeIndex>) -> Self{ pub fn new(inner: Vec<NodeIndex>) -> Self{
Self {indices: inner.into_iter().map(|x| x.index()).collect(), tcref: 0} Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0}
} }
} }
impl AsSlice<usize> for SysGraphMetadata { impl AsSlice<usize> for SysGraphMetadata {
@ -277,4 +291,107 @@ impl Named for SysMapFeedback
fn name(&self) -> &str { fn name(&self) -> &str {
&self.name &self.name
} }
}
//============================= Mutators
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> + HasFeedbackStates,
{
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.clone_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> + HasFeedbackStates,
{
fn name(&self) -> &str {
"RandGraphSnippetMutator"
}
} }