change interrupt injection timing, stg scheduler
This commit is contained in:
parent
5342812cf7
commit
c533b7e184
@ -22,6 +22,10 @@ do_hash_notify_state = []
|
||||
trace_stg = [ "observe_systemstate" ]
|
||||
# feedbacks
|
||||
feed_stg = [ "trace_stg", "observe_systemstate" ]
|
||||
# feed_stg_edge = [ "feed_stg"]
|
||||
feed_stg_pathhash = [ "feed_stg"]
|
||||
feed_stg_abbhash = [ "feed_stg"]
|
||||
feed_stg_aggregatehash = [ "feed_stg"]
|
||||
feed_longest = [ ]
|
||||
feed_afl = [ "observe_edges" ]
|
||||
feed_genetic = []
|
||||
@ -32,6 +36,10 @@ gensize_100 = [ ]
|
||||
sched_genetic = []
|
||||
sched_afl = []
|
||||
sched_stg = []
|
||||
# sched_stg_edge = ['sched_stg'] # every edge in the stg
|
||||
sched_stg_pathhash = ['sched_stg'] # every path in the stg
|
||||
sched_stg_abbhash = ['sched_stg'] # every path of abbs
|
||||
sched_stg_aggregatehash = ['sched_stg'] # every aggregated path (order independent)
|
||||
# overall_configs
|
||||
config_genetic = ["gensize_100","feed_genetic","sched_genetic"]
|
||||
config_afl = ["feed_afl","sched_afl","observe_hitcounts"]
|
||||
|
@ -2,7 +2,7 @@ import csv
|
||||
import os
|
||||
def_flags="--no-default-features --features std,snapshot_restore,singlecore,restarting,do_hash_notify_state"
|
||||
remote="timedump_253048_1873f6_all/"
|
||||
RUNTIME=7600
|
||||
RUNTIME=1800
|
||||
TARGET_REPS_A=2
|
||||
TARGET_REPS_B=2
|
||||
NUM_NODES=2
|
||||
@ -244,6 +244,47 @@ rule all_new:
|
||||
expand("timedump/{fuzzer}/{target}#{num}.time", fuzzer=['random', 'feedgeneration100', 'frafl', 'stg'], target=['waters', 'watersv2', 'interact'],num=range(0,2)),
|
||||
expand("timedump/{fuzzer}/{target}#{num}.time", fuzzer=['random_int', 'feedgeneration100_int', 'frafl_int', 'stg_int'], target=['waters_int', 'watersv2_int', 'interact_int'],num=range(0,3))
|
||||
|
||||
rule build_stgpath:
|
||||
output:
|
||||
directory("bins/target_stgpath_int")
|
||||
shell:
|
||||
"cargo build --target-dir {output} {def_flags},config_stg,sched_stg_pathhash,feed_stg_pathhash"
|
||||
|
||||
rule build_stgabb:
|
||||
output:
|
||||
directory("bins/target_stgabb_int")
|
||||
shell:
|
||||
"cargo build --target-dir {output} {def_flags},config_stg,sched_stg_abbhash,feed_stg_abbhash"
|
||||
|
||||
rule build_stgaggregate:
|
||||
output:
|
||||
directory("bins/target_stgaggregate_int")
|
||||
shell:
|
||||
"cargo build --target-dir {output} {def_flags},config_stg,sched_stg_aggregatehash,feed_stg_aggregatehash"
|
||||
|
||||
rule build_stgpath_int:
|
||||
output:
|
||||
directory("bins/target_stgpath_int")
|
||||
shell:
|
||||
"cargo build --target-dir {output} {def_flags},config_stg,fuzz_int,sched_stg_pathhash,feed_stg_pathhash"
|
||||
|
||||
rule build_stgabb_int:
|
||||
output:
|
||||
directory("bins/target_stgabb_int")
|
||||
shell:
|
||||
"cargo build --target-dir {output} {def_flags},config_stg,fuzz_int,sched_stg_abbhash,feed_stg_abbhash"
|
||||
|
||||
rule build_stgaggregate_int:
|
||||
output:
|
||||
directory("bins/target_stgaggregate_int")
|
||||
shell:
|
||||
"cargo build --target-dir {output} {def_flags},config_stg,fuzz_int,sched_stg_aggregatehash,feed_stg_aggregatehash"
|
||||
|
||||
rule custom_test:
|
||||
input:
|
||||
expand("timedump/{fuzzer}/{target}#{num}.time", fuzzer=['stgpath', 'stgabb', 'stgaggregate'], target=['waters','watersv2','interact'],num=range(0,2)),
|
||||
expand("timedump/{fuzzer}/{target}#{num}.time", fuzzer=['stgpath_int', 'stgabb_int', 'stgaggregate_int'], target=['waters_int','watersv2_int','interact_int'],num=range(0,2)),
|
||||
|
||||
|
||||
rule all_bins:
|
||||
input:
|
||||
|
@ -14,7 +14,7 @@ use libafl_qemu::{
|
||||
};
|
||||
use rand::{SeedableRng, StdRng, Rng};
|
||||
use crate::{
|
||||
clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP}, mutational::{InterruptShiftStage, MINIMUM_INTER_ARRIVAL_TIME}, qemustate::QemuStateRestoreHelper, systemstate::{self, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}, stg::{GraphMaximizerCorpusScheduler}, helpers::{QemuSystemStateHelper, ISR_SYMBOLS}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeStateMaximizerCorpusScheduler}
|
||||
clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP}, mutational::{InterruptShiftStage, MINIMUM_INTER_ARRIVAL_TIME, input_bytes_to_interrupt_times}, qemustate::QemuStateRestoreHelper, systemstate::{self, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}, stg::{GraphMaximizerCorpusScheduler}, helpers::{QemuSystemStateHelper, ISR_SYMBOLS}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeStateMaximizerCorpusScheduler}
|
||||
};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use clap::{Parser, Subcommand};
|
||||
@ -29,7 +29,7 @@ use crate::systemstate::stg::STGFeedbackState;
|
||||
|
||||
pub static mut RNG_SEED: u64 = 1;
|
||||
|
||||
pub static mut LIMIT : u32 = u32::MAX>>1;
|
||||
pub static mut LIMIT : u32 = u32::MAX;
|
||||
pub const FIRST_INT : u32 = 500000;
|
||||
|
||||
pub const MAX_NUM_INTERRUPT: usize = 32;
|
||||
@ -439,22 +439,12 @@ pub fn fuzz() {
|
||||
unsafe {
|
||||
#[cfg(feature = "fuzz_int")]
|
||||
{
|
||||
let mut start_tick : u32 = 0;
|
||||
for i in 0..DO_NUM_INTERRUPT {
|
||||
let mut t : [u8; 4] = [0,0,0,0];
|
||||
if len > (i+1)*4 {
|
||||
for j in 0 as usize..4 as usize {
|
||||
t[j]=buf[i*4+j];
|
||||
}
|
||||
if i == 0 || true {
|
||||
unsafe {start_tick = u32::from_le_bytes(t) % LIMIT + FIRST_INT;}
|
||||
} else {
|
||||
start_tick = u32::saturating_add(start_tick,max(unsafe{MINIMUM_INTER_ARRIVAL_TIME},u32::from_le_bytes(t)));
|
||||
}
|
||||
libafl_interrupt_offsets[i] = start_tick;
|
||||
libafl_num_interrupts = i+1;
|
||||
}
|
||||
let times = input_bytes_to_interrupt_times(buf);
|
||||
for (i,t) in times.iter().enumerate() {
|
||||
libafl_interrupt_offsets[i] = *t;
|
||||
}
|
||||
libafl_num_interrupts = times.len();
|
||||
|
||||
if buf.len() > libafl_num_interrupts*4 {
|
||||
buf = &buf[libafl_num_interrupts*4..];
|
||||
len = buf.len();
|
||||
@ -500,7 +490,7 @@ pub fn fuzz() {
|
||||
#[cfg(feature = "observer_hitcounts")]
|
||||
let edges_observer = HitcountsMapObserver::new(edges_observer);
|
||||
|
||||
#[cfg(feature = "feed_stg")]
|
||||
#[cfg(feature = "observe_systemstate")]
|
||||
let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice(
|
||||
"stg",
|
||||
stg_map_mut_slice(),
|
||||
@ -542,9 +532,9 @@ pub fn fuzz() {
|
||||
#[cfg(feature = "trace_stg")]
|
||||
let mut feedback = feedback_or!(
|
||||
feedback,
|
||||
StgFeedback::default()
|
||||
StgFeedback::new(if cli.dump_graph {cli.dump_name.clone()} else {None})
|
||||
);
|
||||
#[cfg(feature = "feed_stg")]
|
||||
#[cfg(feature = "feed_stg_edge")]
|
||||
let mut feedback = feedback_or!(
|
||||
feedback,
|
||||
MaxMapFeedback::tracking(&stg_coverage_observer, true, true)
|
||||
@ -642,7 +632,7 @@ pub fn fuzz() {
|
||||
if let Some(se) = seed {
|
||||
unsafe {
|
||||
let mut rng = StdRng::seed_from_u64(se);
|
||||
for i in 0..20 {
|
||||
for i in 0..1000 {
|
||||
let inp = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
|
||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
|
||||
}
|
||||
|
@ -20,6 +20,33 @@ pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*ms*/ * 62500;
|
||||
// 1ms = 62500 insn
|
||||
// 1us = 62.5 insn
|
||||
|
||||
pub fn input_bytes_to_interrupt_times(buf: &[u8]) -> Vec<u32> {
|
||||
let len = buf.len();
|
||||
let mut start_tick : u32 = 0;
|
||||
let mut ret = Vec::with_capacity(DO_NUM_INTERRUPT);
|
||||
for i in 0..DO_NUM_INTERRUPT {
|
||||
let mut t : [u8; 4] = [0,0,0,0];
|
||||
if len > (i+1)*4 {
|
||||
for j in 0usize..4usize {
|
||||
t[j]=buf[i*4+j];
|
||||
}
|
||||
unsafe {start_tick = max(u32::from_le_bytes(t), FIRST_INT);}
|
||||
ret.push(start_tick);
|
||||
} else {break;}
|
||||
}
|
||||
ret.sort_unstable();
|
||||
// obey the minimum inter arrival time while maintaining the sort
|
||||
for i in 0..ret.len()-1 {
|
||||
for j in i+1..ret.len()-1 {
|
||||
if ret[j]-ret[i] < unsafe{MINIMUM_INTER_ARRIVAL_TIME} {
|
||||
ret[j] = u32::saturating_add(ret[i],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||
} else {break;}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
//======================= Custom mutator
|
||||
|
||||
/// The default mutational stage
|
||||
@ -64,39 +91,29 @@ where
|
||||
let mut newinput = _input.input_mut().as_mut().unwrap().clone();
|
||||
// let mut tmpinput = _input.input_mut().as_mut().unwrap().clone();
|
||||
let mut do_rerun = false;
|
||||
if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
|
||||
{
|
||||
// need our own random generator, because borrowing rules
|
||||
let mut myrand = StdRand::new();
|
||||
let mut target_bytes : Vec<u8> = vec![];
|
||||
{
|
||||
let input = _input.input_mut().as_ref().unwrap();
|
||||
target_bytes = input.bytes().to_vec();
|
||||
let tmp = &mut state.rand_mut();
|
||||
myrand.set_seed(tmp.next());
|
||||
target_bytes = input.bytes().to_vec();
|
||||
}
|
||||
|
||||
// produce a slice of absolute interrupt times
|
||||
let mut interrupt_offsets : [u32; 32] = [0u32; 32];
|
||||
let mut interrupt_offsets : [u32; 32] = [u32::MAX; 32];
|
||||
let mut num_interrupts : usize = 0;
|
||||
{
|
||||
let mut start_tick : u32 = 0;
|
||||
for i in 0..DO_NUM_INTERRUPT {
|
||||
let mut t : [u8; 4] = [0,0,0,0];
|
||||
if target_bytes.len() > (i+1)*4 {
|
||||
for j in 0 as usize..4 as usize {
|
||||
t[j]=target_bytes[i*4+j];
|
||||
let times = input_bytes_to_interrupt_times(&target_bytes);
|
||||
for (i,t) in times.iter().enumerate() {
|
||||
interrupt_offsets[i] = *t;
|
||||
}
|
||||
if i == 0 || true {
|
||||
start_tick = u32::saturating_add(u32::from_le_bytes(t),FIRST_INT);
|
||||
} else {
|
||||
start_tick = u32::saturating_add(start_tick,max(unsafe{MINIMUM_INTER_ARRIVAL_TIME},u32::from_le_bytes(t)));
|
||||
num_interrupts = times.len();
|
||||
}
|
||||
interrupt_offsets[i] = start_tick;
|
||||
num_interrupts = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
interrupt_offsets.sort();
|
||||
interrupt_offsets.sort_unstable();
|
||||
|
||||
// println!("Vor Mutator: {:?}", interrupt_offsets[0..num_interrupts].to_vec());
|
||||
// let num_i = min(target_bytes.len() / 4, DO_NUM_INTERRUPT);
|
||||
@ -105,6 +122,17 @@ where
|
||||
// let mut suffix : Vec<u8> = vec![];
|
||||
#[cfg(feature = "trace_stg")]
|
||||
{
|
||||
if myrand.between(1,100) <= 25 { // 0.5*0.25 = 12.5% of the time fully randomize all interrupts
|
||||
do_rerun = true;
|
||||
let metadata = state.metadata_map();
|
||||
let hist = metadata.get::<IcHist>().unwrap();
|
||||
let maxtick : u64 = hist.1.0;
|
||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
||||
let mut numbers : Vec<u32> = vec![];
|
||||
for i in 0..num_interrupts {
|
||||
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64)).try_into().expect("ticks > u32")));
|
||||
}
|
||||
} else {
|
||||
let feedbackstate = match state
|
||||
.named_metadata_map_mut()
|
||||
.get_mut::<STGFeedbackState>("stgfeedbackstate") {
|
||||
@ -215,8 +243,11 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "trace_stg"))]
|
||||
{
|
||||
if myrand.between(1,100) <= 25 { // we have no hint if interrupt times will change anything
|
||||
do_rerun = true;
|
||||
let metadata = state.metadata_map();
|
||||
let hist = metadata.get::<IcHist>().unwrap();
|
||||
let maxtick : u64 = hist.1.0;
|
||||
@ -226,6 +257,7 @@ where
|
||||
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64)).try_into().expect("ticks > u32")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut n : Vec<u8> = vec![];
|
||||
n = [prefix.concat(), suffix].concat();
|
||||
|
@ -59,6 +59,10 @@ use std::rc::Rc;
|
||||
|
||||
use libafl_bolts::rands::Rand;
|
||||
|
||||
use crate::clock::FUZZ_START_TIMESTAMP;
|
||||
use std::time::SystemTime;
|
||||
use std::{fs::OpenOptions, io::Write};
|
||||
|
||||
//============================= Data Structures
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Default, Hash)]
|
||||
pub struct STGNode
|
||||
@ -147,7 +151,9 @@ pub struct STGFeedbackState
|
||||
entrypoint: NodeIndex,
|
||||
exitpoint: NodeIndex,
|
||||
// Metadata about aggregated traces. aggegated meaning, order has been removed
|
||||
worst_observed_per_aggegated_path: HashMap<Vec<AtomicBasicBlock>,u64>
|
||||
worst_observed_per_aggegated_path: HashMap<Vec<AtomicBasicBlock>,u64>,
|
||||
worst_observed_per_abb_path: HashMap<u64,u64>,
|
||||
worst_observed_per_stg_path: HashMap<u64,u64>
|
||||
}
|
||||
|
||||
impl Default for STGFeedbackState {
|
||||
@ -176,6 +182,8 @@ impl Default for STGFeedbackState {
|
||||
entrypoint,
|
||||
exitpoint,
|
||||
worst_observed_per_aggegated_path: HashMap::new(),
|
||||
worst_observed_per_abb_path: HashMap::new(),
|
||||
worst_observed_per_stg_path: HashMap::new(),
|
||||
systemstate_index,
|
||||
state_abb_hash_index
|
||||
}
|
||||
@ -195,16 +203,35 @@ impl Named for STGFeedbackState
|
||||
pub struct STGNodeMetadata {
|
||||
pub nodes: Vec<NodeIndex>,
|
||||
pub edges: Vec<EdgeIndex>,
|
||||
pub abbs: Vec<AtomicBasicBlock>,
|
||||
pub intervals: Vec<ExecInterval>,
|
||||
indices: Vec<usize>,
|
||||
tcref: isize,
|
||||
}
|
||||
impl STGNodeMetadata {
|
||||
pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, intervals: Vec<ExecInterval>) -> Self{
|
||||
let mut indices : Vec<_> = edges.iter().map(|x| x.index()).collect();
|
||||
pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, abbs: Vec<AtomicBasicBlock>, intervals: Vec<ExecInterval>) -> Self{
|
||||
let mut indices : Vec<_> = vec![];
|
||||
#[cfg(all(feature = "sched_stg",not(any(feature = "sched_stg_pathhash",feature = "sched_stg_abbhash",feature = "sched_stg_aggregatehash"))))]
|
||||
{
|
||||
indices = edges.iter().map(|x| x.index()).collect();
|
||||
indices.sort_unstable();
|
||||
indices.dedup();
|
||||
Self {indices, intervals, nodes, edges, tcref: 0}
|
||||
}
|
||||
#[cfg(feature = "sched_stg_pathhash")]
|
||||
{
|
||||
indices.push(get_generic_hash(&edges) as usize);
|
||||
}
|
||||
#[cfg(feature = "sched_stg_abbhash")]
|
||||
{
|
||||
indices.push(get_generic_hash(&abbs) as usize);
|
||||
}
|
||||
#[cfg(feature = "sched_stg_aggregatehash")]
|
||||
{
|
||||
let mut _abbs = abbs.clone();
|
||||
_abbs.sort_unstable();
|
||||
indices.push(get_generic_hash(&_abbs) as usize);
|
||||
}
|
||||
Self {indices, intervals, nodes, abbs, edges, tcref: 0}
|
||||
}
|
||||
}
|
||||
impl AsSlice for STGNodeMetadata {
|
||||
@ -247,18 +274,29 @@ pub struct StgFeedback
|
||||
last_node_trace: Option<Vec<NodeIndex>>,
|
||||
last_edge_trace: Option<Vec<EdgeIndex>>,
|
||||
last_intervals: Option<Vec<ExecInterval>>,
|
||||
last_abbs: Option<Vec<AtomicBasicBlock>>,
|
||||
dump_path: Option<PathBuf>
|
||||
}
|
||||
#[cfg(feature = "feed_stg")]
|
||||
const INTEREST_EDGE : bool = true;
|
||||
#[cfg(feature = "feed_stg")]
|
||||
const INTEREST_NODE : bool = true;
|
||||
#[cfg(feature = "feed_stg")]
|
||||
#[cfg(feature = "feed_stg_pathhash")]
|
||||
const INTEREST_PATH : bool = true;
|
||||
#[cfg(feature = "feed_stg_abbhash")]
|
||||
const INTEREST_ABBPATH : bool = true;
|
||||
#[cfg(feature = "feed_stg_aggregatehash")]
|
||||
const INTEREST_AGGREGATE : bool = true;
|
||||
|
||||
#[cfg(not(feature = "feed_stg"))]
|
||||
const INTEREST_EDGE : bool = false;
|
||||
#[cfg(not(feature = "feed_stg"))]
|
||||
const INTEREST_NODE : bool = false;
|
||||
#[cfg(not(feature = "feed_stg"))]
|
||||
#[cfg(not(feature = "feed_stg_pathhash"))]
|
||||
const INTEREST_PATH : bool = false;
|
||||
#[cfg(not(feature = "feed_stg_abbhash"))]
|
||||
const INTEREST_ABBPATH : bool = false;
|
||||
#[cfg(not(feature = "feed_stg_aggregatehash"))]
|
||||
const INTEREST_AGGREGATE : bool = false;
|
||||
fn set_observer_map(trace : &Vec<EdgeIndex>) {
|
||||
unsafe {
|
||||
@ -273,9 +311,22 @@ fn set_observer_map(trace : &Vec<EdgeIndex>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_generic_hash<H>(input: &H) -> u64
|
||||
where
|
||||
H: Hash,
|
||||
{
|
||||
let mut s = DefaultHasher::new();
|
||||
input.hash(&mut s);
|
||||
s.finish()
|
||||
}
|
||||
|
||||
impl StgFeedback {
|
||||
pub fn new() -> Self {
|
||||
Self {name: String::from("STGFeedback"), last_node_trace: None, last_edge_trace: None, last_intervals: None }
|
||||
pub fn new(dump_name: Option<PathBuf>) -> Self {
|
||||
// Self {name: String::from("STGFeedback"), last_node_trace: None, last_edge_trace: None, last_intervals: None }
|
||||
let mut s = Self::default();
|
||||
s.dump_path = dump_name.map(|x| x.with_extension("stgsize"));
|
||||
s
|
||||
}
|
||||
|
||||
/// params:
|
||||
@ -287,10 +338,11 @@ impl StgFeedback {
|
||||
/// newly discovered node?
|
||||
/// side effect:
|
||||
/// the graph gets new nodes and edge
|
||||
fn update_stg_interval(trace: &Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeRTOSSystemState>, fbs: &mut STGFeedbackState) -> (Vec<NodeIndex>, Vec<EdgeIndex>, bool) {
|
||||
fn update_stg_interval(trace: &Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeRTOSSystemState>, fbs: &mut STGFeedbackState) -> (Vec<NodeIndex>, Vec<EdgeIndex>, bool, bool) {
|
||||
let mut return_node_trace = vec![fbs.entrypoint];
|
||||
let mut return_edge_trace = vec![];
|
||||
let mut interesting = false;
|
||||
let mut updated = false;
|
||||
// add all missing state+abb combinations to the graph
|
||||
for (i,interval) in trace.iter().enumerate() { // Iterate intervals
|
||||
let node = STGNode {base: table[&interval.start_state].clone(), abb: interval.abb.as_ref().unwrap().clone()};
|
||||
@ -305,6 +357,7 @@ impl StgFeedback {
|
||||
fbs.stgnode_index.insert(h_node, idx);
|
||||
fbs.state_abb_hash_index.insert(h, idx);
|
||||
interesting |= INTEREST_NODE;
|
||||
updated = true;
|
||||
idx
|
||||
};
|
||||
// connect in graph if edge not present
|
||||
@ -315,6 +368,7 @@ impl StgFeedback {
|
||||
let e_ = fbs.graph.add_edge(return_node_trace[return_node_trace.len()-1], next_idx, STGEdge{event: interval.start_capture.0, name: interval.start_capture.1.clone()});
|
||||
return_edge_trace.push(e_);
|
||||
interesting |= INTEREST_EDGE;
|
||||
updated = true;
|
||||
}
|
||||
return_node_trace.push(next_idx);
|
||||
/*
|
||||
@ -330,11 +384,12 @@ impl StgFeedback {
|
||||
let e_ = fbs.graph.add_edge(return_node_trace[return_node_trace.len()-1], fbs.exitpoint, STGEdge { event: CaptureEvent::End, name: String::from("End") });
|
||||
return_edge_trace.push(e_);
|
||||
interesting |= INTEREST_EDGE;
|
||||
updated = true;
|
||||
}
|
||||
return_node_trace.push(fbs.exitpoint);
|
||||
#[cfg(feature = "feed_stg")]
|
||||
set_observer_map(&return_edge_trace);
|
||||
(return_node_trace, return_edge_trace, interesting)
|
||||
(return_node_trace, return_edge_trace, interesting, updated)
|
||||
}
|
||||
|
||||
fn abbs_in_exec_order(trace: &Vec<ExecInterval>) -> Vec<AtomicBasicBlock> {
|
||||
@ -382,23 +437,55 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
let (nodetrace, edgetrace, mut interesting) = StgFeedback::update_stg_interval(&observer.last_trace, &observer.last_states, feedbackstate);
|
||||
let (nodetrace, edgetrace, mut interesting, mut updated) = StgFeedback::update_stg_interval(&observer.last_trace, &observer.last_states, feedbackstate);
|
||||
|
||||
{
|
||||
let h = get_generic_hash(&edgetrace);
|
||||
if let Some(x) = feedbackstate.worst_observed_per_stg_path.get_mut(&h) {
|
||||
let t = clock_observer.last_runtime();
|
||||
if t > *x {
|
||||
*x = t;
|
||||
interesting |= INTEREST_PATH;
|
||||
}
|
||||
} else {
|
||||
feedbackstate.worst_observed_per_stg_path.insert(h, clock_observer.last_runtime());
|
||||
updated = true;
|
||||
interesting |= INTEREST_PATH;
|
||||
}
|
||||
}
|
||||
|
||||
if INTEREST_AGGREGATE {
|
||||
let mut tmp = StgFeedback::abbs_in_exec_order(&observer.last_trace);
|
||||
if INTEREST_AGGREGATE || INTEREST_ABBPATH {
|
||||
if INTEREST_ABBPATH {
|
||||
let h = get_generic_hash(&tmp);
|
||||
// order of execution is relevant
|
||||
if let Some(x) = feedbackstate.worst_observed_per_abb_path.get_mut(&h) {
|
||||
let t = clock_observer.last_runtime();
|
||||
if t > *x {
|
||||
*x = t;
|
||||
interesting |= INTEREST_ABBPATH;
|
||||
}
|
||||
} else {
|
||||
feedbackstate.worst_observed_per_abb_path.insert(h, clock_observer.last_runtime());
|
||||
interesting |= INTEREST_ABBPATH;
|
||||
}
|
||||
}
|
||||
if INTEREST_AGGREGATE {
|
||||
// aggegation by sorting, order of states is not relevant
|
||||
tmp.sort();
|
||||
if let Some(x) = feedbackstate.worst_observed_per_aggegated_path.get_mut(&tmp) {
|
||||
let mut _tmp = tmp.clone();
|
||||
_tmp.sort();
|
||||
if let Some(x) = feedbackstate.worst_observed_per_aggegated_path.get_mut(&_tmp) {
|
||||
let t = clock_observer.last_runtime();
|
||||
if t > *x {
|
||||
*x = t;
|
||||
interesting |= INTEREST_AGGREGATE;
|
||||
}
|
||||
} else {
|
||||
feedbackstate.worst_observed_per_aggegated_path.insert(tmp, clock_observer.last_runtime());
|
||||
feedbackstate.worst_observed_per_aggegated_path.insert(_tmp, clock_observer.last_runtime());
|
||||
interesting |= INTEREST_AGGREGATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let out = feedbackstate.graph.map(|i,x| x.pretty_print(), |_,_| "");
|
||||
// let outs = Dot::with_config(&out, &[Config::EdgeNoLabel]).to_string();
|
||||
@ -407,17 +494,31 @@ where
|
||||
self.last_node_trace = Some(nodetrace);
|
||||
self.last_edge_trace = Some(edgetrace);
|
||||
self.last_intervals = Some(observer.last_trace.clone());
|
||||
self.last_abbs = Some(tmp);
|
||||
|
||||
if let Some(dp) = &self.dump_path {
|
||||
if updated {
|
||||
let timestamp = SystemTime::now().duration_since(unsafe {FUZZ_START_TIMESTAMP}).unwrap().as_millis();
|
||||
let mut file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(dp).expect("Could not open stgsize");
|
||||
writeln!(file, "{},{},{},{},{}", feedbackstate.graph.edge_count(), feedbackstate.graph.node_count(), feedbackstate.worst_observed_per_aggegated_path.len(),feedbackstate.worst_observed_per_stg_path.len(), timestamp).expect("Write to dump failed");
|
||||
}
|
||||
}
|
||||
Ok(interesting)
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
fn append_metadata<OT>(&mut self, _state: &mut S, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
|
||||
let nodes = self.last_node_trace.take();
|
||||
let edges = self.last_edge_trace.take();
|
||||
let abbs = self.last_abbs.take();
|
||||
match nodes {
|
||||
Some(s) => testcase.metadata_map_mut().insert(STGNodeMetadata::new(s, edges.unwrap(), self.last_intervals.take().unwrap())),
|
||||
Some(s) => testcase.metadata_map_mut().insert(STGNodeMetadata::new(s, edges.unwrap(), abbs.unwrap(), self.last_intervals.take().unwrap())),
|
||||
None => (),
|
||||
}
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user