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" ]
|
trace_stg = [ "observe_systemstate" ]
|
||||||
# feedbacks
|
# feedbacks
|
||||||
feed_stg = [ "trace_stg", "observe_systemstate" ]
|
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_longest = [ ]
|
||||||
feed_afl = [ "observe_edges" ]
|
feed_afl = [ "observe_edges" ]
|
||||||
feed_genetic = []
|
feed_genetic = []
|
||||||
@ -32,6 +36,10 @@ gensize_100 = [ ]
|
|||||||
sched_genetic = []
|
sched_genetic = []
|
||||||
sched_afl = []
|
sched_afl = []
|
||||||
sched_stg = []
|
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
|
# overall_configs
|
||||||
config_genetic = ["gensize_100","feed_genetic","sched_genetic"]
|
config_genetic = ["gensize_100","feed_genetic","sched_genetic"]
|
||||||
config_afl = ["feed_afl","sched_afl","observe_hitcounts"]
|
config_afl = ["feed_afl","sched_afl","observe_hitcounts"]
|
||||||
|
@ -2,7 +2,7 @@ import csv
|
|||||||
import os
|
import os
|
||||||
def_flags="--no-default-features --features std,snapshot_restore,singlecore,restarting,do_hash_notify_state"
|
def_flags="--no-default-features --features std,snapshot_restore,singlecore,restarting,do_hash_notify_state"
|
||||||
remote="timedump_253048_1873f6_all/"
|
remote="timedump_253048_1873f6_all/"
|
||||||
RUNTIME=7600
|
RUNTIME=1800
|
||||||
TARGET_REPS_A=2
|
TARGET_REPS_A=2
|
||||||
TARGET_REPS_B=2
|
TARGET_REPS_B=2
|
||||||
NUM_NODES=2
|
NUM_NODES=2
|
||||||
@ -243,6 +243,47 @@ rule all_new:
|
|||||||
input:
|
input:
|
||||||
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', '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))
|
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:
|
rule all_bins:
|
||||||
|
@ -14,7 +14,7 @@ use libafl_qemu::{
|
|||||||
};
|
};
|
||||||
use rand::{SeedableRng, StdRng, Rng};
|
use rand::{SeedableRng, StdRng, Rng};
|
||||||
use crate::{
|
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 std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
@ -29,7 +29,7 @@ use crate::systemstate::stg::STGFeedbackState;
|
|||||||
|
|
||||||
pub static mut RNG_SEED: u64 = 1;
|
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 FIRST_INT : u32 = 500000;
|
||||||
|
|
||||||
pub const MAX_NUM_INTERRUPT: usize = 32;
|
pub const MAX_NUM_INTERRUPT: usize = 32;
|
||||||
@ -439,22 +439,12 @@ pub fn fuzz() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
#[cfg(feature = "fuzz_int")]
|
#[cfg(feature = "fuzz_int")]
|
||||||
{
|
{
|
||||||
let mut start_tick : u32 = 0;
|
let times = input_bytes_to_interrupt_times(buf);
|
||||||
for i in 0..DO_NUM_INTERRUPT {
|
for (i,t) in times.iter().enumerate() {
|
||||||
let mut t : [u8; 4] = [0,0,0,0];
|
libafl_interrupt_offsets[i] = *t;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
libafl_num_interrupts = times.len();
|
||||||
|
|
||||||
if buf.len() > libafl_num_interrupts*4 {
|
if buf.len() > libafl_num_interrupts*4 {
|
||||||
buf = &buf[libafl_num_interrupts*4..];
|
buf = &buf[libafl_num_interrupts*4..];
|
||||||
len = buf.len();
|
len = buf.len();
|
||||||
@ -500,7 +490,7 @@ pub fn fuzz() {
|
|||||||
#[cfg(feature = "observer_hitcounts")]
|
#[cfg(feature = "observer_hitcounts")]
|
||||||
let edges_observer = HitcountsMapObserver::new(edges_observer);
|
let edges_observer = HitcountsMapObserver::new(edges_observer);
|
||||||
|
|
||||||
#[cfg(feature = "feed_stg")]
|
#[cfg(feature = "observe_systemstate")]
|
||||||
let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice(
|
let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice(
|
||||||
"stg",
|
"stg",
|
||||||
stg_map_mut_slice(),
|
stg_map_mut_slice(),
|
||||||
@ -542,9 +532,9 @@ pub fn fuzz() {
|
|||||||
#[cfg(feature = "trace_stg")]
|
#[cfg(feature = "trace_stg")]
|
||||||
let mut feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
feedback,
|
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!(
|
let mut feedback = feedback_or!(
|
||||||
feedback,
|
feedback,
|
||||||
MaxMapFeedback::tracking(&stg_coverage_observer, true, true)
|
MaxMapFeedback::tracking(&stg_coverage_observer, true, true)
|
||||||
@ -642,7 +632,7 @@ pub fn fuzz() {
|
|||||||
if let Some(se) = seed {
|
if let Some(se) = seed {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut rng = StdRng::seed_from_u64(se);
|
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]);
|
let inp = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
|
||||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
|
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
|
// 1ms = 62500 insn
|
||||||
// 1us = 62.5 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
|
//======================= Custom mutator
|
||||||
|
|
||||||
/// The default mutational stage
|
/// The default mutational stage
|
||||||
@ -64,39 +91,29 @@ where
|
|||||||
let mut newinput = _input.input_mut().as_mut().unwrap().clone();
|
let mut newinput = _input.input_mut().as_mut().unwrap().clone();
|
||||||
// let mut tmpinput = _input.input_mut().as_mut().unwrap().clone();
|
// let mut tmpinput = _input.input_mut().as_mut().unwrap().clone();
|
||||||
let mut do_rerun = false;
|
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
|
// need our own random generator, because borrowing rules
|
||||||
let mut myrand = StdRand::new();
|
let mut myrand = StdRand::new();
|
||||||
let mut target_bytes : Vec<u8> = vec![];
|
let mut target_bytes : Vec<u8> = vec![];
|
||||||
{
|
{
|
||||||
let input = _input.input_mut().as_ref().unwrap();
|
let input = _input.input_mut().as_ref().unwrap();
|
||||||
|
target_bytes = input.bytes().to_vec();
|
||||||
let tmp = &mut state.rand_mut();
|
let tmp = &mut state.rand_mut();
|
||||||
myrand.set_seed(tmp.next());
|
myrand.set_seed(tmp.next());
|
||||||
target_bytes = input.bytes().to_vec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// produce a slice of absolute interrupt times
|
// 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 num_interrupts : usize = 0;
|
||||||
{
|
{
|
||||||
let mut start_tick : u32 = 0;
|
let times = input_bytes_to_interrupt_times(&target_bytes);
|
||||||
for i in 0..DO_NUM_INTERRUPT {
|
for (i,t) in times.iter().enumerate() {
|
||||||
let mut t : [u8; 4] = [0,0,0,0];
|
interrupt_offsets[i] = *t;
|
||||||
if target_bytes.len() > (i+1)*4 {
|
|
||||||
for j in 0 as usize..4 as usize {
|
|
||||||
t[j]=target_bytes[i*4+j];
|
|
||||||
}
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
interrupt_offsets[i] = start_tick;
|
|
||||||
num_interrupts = i+1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
num_interrupts = times.len();
|
||||||
}
|
}
|
||||||
interrupt_offsets.sort();
|
interrupt_offsets.sort_unstable();
|
||||||
|
|
||||||
// println!("Vor Mutator: {:?}", interrupt_offsets[0..num_interrupts].to_vec());
|
// println!("Vor Mutator: {:?}", interrupt_offsets[0..num_interrupts].to_vec());
|
||||||
// let num_i = min(target_bytes.len() / 4, DO_NUM_INTERRUPT);
|
// let num_i = min(target_bytes.len() / 4, DO_NUM_INTERRUPT);
|
||||||
@ -105,125 +122,140 @@ where
|
|||||||
// let mut suffix : Vec<u8> = vec![];
|
// let mut suffix : Vec<u8> = vec![];
|
||||||
#[cfg(feature = "trace_stg")]
|
#[cfg(feature = "trace_stg")]
|
||||||
{
|
{
|
||||||
let feedbackstate = match state
|
if myrand.between(1,100) <= 25 { // 0.5*0.25 = 12.5% of the time fully randomize all interrupts
|
||||||
.named_metadata_map_mut()
|
do_rerun = true;
|
||||||
.get_mut::<STGFeedbackState>("stgfeedbackstate") {
|
let metadata = state.metadata_map();
|
||||||
Some(s) => s,
|
let hist = metadata.get::<IcHist>().unwrap();
|
||||||
None => {
|
let maxtick : u64 = hist.1.0;
|
||||||
panic!("STGfeedbackstate not visible")
|
// 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")));
|
||||||
let tmp = _input.metadata_map().get::<STGNodeMetadata>();
|
|
||||||
if tmp.is_some() {
|
|
||||||
let trace = tmp.expect("STGNodeMetadata not found");
|
|
||||||
|
|
||||||
// calculate hits and identify snippets
|
|
||||||
let mut last_m = false;
|
|
||||||
let mut marks : Vec<(&ExecInterval, usize, usize)>= vec![]; // 1: got interrupted, 2: interrupt handler
|
|
||||||
for i in 0..trace.intervals.len() {
|
|
||||||
let curr = &trace.intervals[i];
|
|
||||||
let m = interrupt_offsets[0..num_interrupts].iter().any(|x| (curr.start_tick..curr.end_tick).contains(&(*x as u64)));
|
|
||||||
if m {
|
|
||||||
marks.push((curr, i, 1));
|
|
||||||
// println!("1: {}",curr.current_task.0.task_name);
|
|
||||||
} else if last_m {
|
|
||||||
marks.push((curr, i, 2));
|
|
||||||
// println!("2: {}",curr.current_task.0.task_name);
|
|
||||||
} else {
|
|
||||||
marks.push((curr, i, 0));
|
|
||||||
}
|
}
|
||||||
last_m = m;
|
} else {
|
||||||
}
|
let feedbackstate = match state
|
||||||
for i in 0..num_interrupts {
|
.named_metadata_map_mut()
|
||||||
// bounds based on minimum inter-arrival time
|
.get_mut::<STGFeedbackState>("stgfeedbackstate") {
|
||||||
let mut lb = 0;
|
Some(s) => s,
|
||||||
let mut ub : u32 = marks[marks.len()-1].0.end_tick.try_into().expect("ticks > u32");
|
None => {
|
||||||
if i > 0 {
|
panic!("STGfeedbackstate not visible")
|
||||||
lb = u32::saturating_add(interrupt_offsets[i-1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
|
||||||
}
|
|
||||||
if i < num_interrupts-1 {
|
|
||||||
ub = u32::saturating_sub(interrupt_offsets[i+1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
|
||||||
}
|
|
||||||
// get old hit and handler
|
|
||||||
let old_hit = marks.iter().filter(
|
|
||||||
|x| x.0.start_tick < (interrupt_offsets[i] as u64) && (interrupt_offsets[i] as u64) < x.0.end_tick
|
|
||||||
).next();
|
|
||||||
let old_handler = match old_hit {
|
|
||||||
Some(s) => if s.1 < num_interrupts-1 && s.1 < marks.len()-1 {
|
|
||||||
Some(marks[s.1+1])
|
|
||||||
} else {None},
|
|
||||||
None => None
|
|
||||||
};
|
|
||||||
// find reachable alternatives
|
|
||||||
let alternatives : Vec<_> = marks.iter().filter(|x|
|
|
||||||
x.2 != 2 &&
|
|
||||||
(
|
|
||||||
x.0.start_tick < (lb as u64) && (lb as u64) < x.0.end_tick
|
|
||||||
|| x.0.start_tick < (ub as u64) && (ub as u64) < x.0.end_tick )
|
|
||||||
).collect();
|
|
||||||
// in cases there are no alternatives
|
|
||||||
if alternatives.len() == 0 {
|
|
||||||
if old_hit.is_none() {
|
|
||||||
// choose something random
|
|
||||||
let untouched : Vec<_> = marks.iter().filter(
|
|
||||||
|x| x.2 == 0
|
|
||||||
).collect();
|
|
||||||
if untouched.len() > 0 {
|
|
||||||
let tmp = interrupt_offsets[i];
|
|
||||||
let choice = myrand.choose(untouched);
|
|
||||||
interrupt_offsets[i] = myrand.between(choice.0.start_tick, choice.0.end_tick)
|
|
||||||
.try_into().expect("tick > u32");
|
|
||||||
do_rerun = true;
|
|
||||||
}
|
}
|
||||||
// println!("no alternatives, choose random i: {} {} -> {}",i,tmp,interrupt_offsets[i]);
|
};
|
||||||
|
|
||||||
|
let tmp = _input.metadata_map().get::<STGNodeMetadata>();
|
||||||
|
if tmp.is_some() {
|
||||||
|
let trace = tmp.expect("STGNodeMetadata not found");
|
||||||
|
|
||||||
|
// calculate hits and identify snippets
|
||||||
|
let mut last_m = false;
|
||||||
|
let mut marks : Vec<(&ExecInterval, usize, usize)>= vec![]; // 1: got interrupted, 2: interrupt handler
|
||||||
|
for i in 0..trace.intervals.len() {
|
||||||
|
let curr = &trace.intervals[i];
|
||||||
|
let m = interrupt_offsets[0..num_interrupts].iter().any(|x| (curr.start_tick..curr.end_tick).contains(&(*x as u64)));
|
||||||
|
if m {
|
||||||
|
marks.push((curr, i, 1));
|
||||||
|
// println!("1: {}",curr.current_task.0.task_name);
|
||||||
|
} else if last_m {
|
||||||
|
marks.push((curr, i, 2));
|
||||||
|
// println!("2: {}",curr.current_task.0.task_name);
|
||||||
|
} else {
|
||||||
|
marks.push((curr, i, 0));
|
||||||
|
}
|
||||||
|
last_m = m;
|
||||||
|
}
|
||||||
|
for i in 0..num_interrupts {
|
||||||
|
// bounds based on minimum inter-arrival time
|
||||||
|
let mut lb = 0;
|
||||||
|
let mut ub : u32 = marks[marks.len()-1].0.end_tick.try_into().expect("ticks > u32");
|
||||||
|
if i > 0 {
|
||||||
|
lb = u32::saturating_add(interrupt_offsets[i-1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||||
|
}
|
||||||
|
if i < num_interrupts-1 {
|
||||||
|
ub = u32::saturating_sub(interrupt_offsets[i+1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||||
|
}
|
||||||
|
// get old hit and handler
|
||||||
|
let old_hit = marks.iter().filter(
|
||||||
|
|x| x.0.start_tick < (interrupt_offsets[i] as u64) && (interrupt_offsets[i] as u64) < x.0.end_tick
|
||||||
|
).next();
|
||||||
|
let old_handler = match old_hit {
|
||||||
|
Some(s) => if s.1 < num_interrupts-1 && s.1 < marks.len()-1 {
|
||||||
|
Some(marks[s.1+1])
|
||||||
|
} else {None},
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
// find reachable alternatives
|
||||||
|
let alternatives : Vec<_> = marks.iter().filter(|x|
|
||||||
|
x.2 != 2 &&
|
||||||
|
(
|
||||||
|
x.0.start_tick < (lb as u64) && (lb as u64) < x.0.end_tick
|
||||||
|
|| x.0.start_tick < (ub as u64) && (ub as u64) < x.0.end_tick )
|
||||||
|
).collect();
|
||||||
|
// in cases there are no alternatives
|
||||||
|
if alternatives.len() == 0 {
|
||||||
|
if old_hit.is_none() {
|
||||||
|
// choose something random
|
||||||
|
let untouched : Vec<_> = marks.iter().filter(
|
||||||
|
|x| x.2 == 0
|
||||||
|
).collect();
|
||||||
|
if untouched.len() > 0 {
|
||||||
|
let tmp = interrupt_offsets[i];
|
||||||
|
let choice = myrand.choose(untouched);
|
||||||
|
interrupt_offsets[i] = myrand.between(choice.0.start_tick, choice.0.end_tick)
|
||||||
|
.try_into().expect("tick > u32");
|
||||||
|
do_rerun = true;
|
||||||
|
}
|
||||||
|
// println!("no alternatives, choose random i: {} {} -> {}",i,tmp,interrupt_offsets[i]);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// do nothing
|
||||||
|
// println!("no alternatives, do nothing i: {} {}",i,interrupt_offsets[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let replacement = myrand.choose(alternatives);
|
||||||
|
if (old_hit.map_or(false, |x| x == replacement)) {
|
||||||
|
// use the old value
|
||||||
|
// println!("chose old value, do nothing i: {} {}",i,interrupt_offsets[i]);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
// do nothing
|
let extra = if (old_hit.map_or(false, |x| x.1 < replacement.1)) {
|
||||||
// println!("no alternatives, do nothing i: {} {}",i,interrupt_offsets[i]);
|
// move futher back, respect old_handler
|
||||||
continue;
|
old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick)
|
||||||
|
} else { 0 };
|
||||||
|
let tmp = interrupt_offsets[i];
|
||||||
|
interrupt_offsets[i] = (myrand.between(replacement.0.start_tick,
|
||||||
|
replacement.0.end_tick) + extra).try_into().expect("ticks > u32");
|
||||||
|
// println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
||||||
|
do_rerun = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let replacement = myrand.choose(alternatives);
|
let mut numbers : Vec<u32> = interrupt_offsets[0..num_interrupts].to_vec();
|
||||||
if (old_hit.map_or(false, |x| x == replacement)) {
|
numbers.sort();
|
||||||
// use the old value
|
// println!("Mutator: {:?}", numbers);
|
||||||
// println!("chose old value, do nothing i: {} {}",i,interrupt_offsets[i]);
|
// let mut start : u32 = 0;
|
||||||
continue;
|
// for i in 0..numbers.len() {
|
||||||
} else {
|
// let tmp = numbers[i];
|
||||||
let extra = if (old_hit.map_or(false, |x| x.1 < replacement.1)) {
|
// numbers[i] = numbers[i]-start;
|
||||||
// move futher back, respect old_handler
|
// start = tmp;
|
||||||
old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick)
|
// }
|
||||||
} else { 0 };
|
for i in 0..numbers.len() {
|
||||||
let tmp = interrupt_offsets[i];
|
prefix.push(u32::to_le_bytes(numbers[i]));
|
||||||
interrupt_offsets[i] = (myrand.between(replacement.0.start_tick,
|
}
|
||||||
replacement.0.end_tick) + extra).try_into().expect("ticks > u32");
|
|
||||||
// println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
|
||||||
do_rerun = true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let mut numbers : Vec<u32> = interrupt_offsets[0..num_interrupts].to_vec();
|
|
||||||
numbers.sort();
|
|
||||||
// println!("Mutator: {:?}", numbers);
|
|
||||||
// let mut start : u32 = 0;
|
|
||||||
// for i in 0..numbers.len() {
|
|
||||||
// let tmp = numbers[i];
|
|
||||||
// numbers[i] = numbers[i]-start;
|
|
||||||
// start = tmp;
|
|
||||||
// }
|
|
||||||
for i in 0..numbers.len() {
|
|
||||||
prefix.push(u32::to_le_bytes(numbers[i]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "trace_stg"))]
|
#[cfg(not(feature = "trace_stg"))]
|
||||||
{
|
{
|
||||||
let metadata = state.metadata_map();
|
if myrand.between(1,100) <= 25 { // we have no hint if interrupt times will change anything
|
||||||
let hist = metadata.get::<IcHist>().unwrap();
|
do_rerun = true;
|
||||||
let maxtick : u64 = hist.1.0;
|
let metadata = state.metadata_map();
|
||||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
let hist = metadata.get::<IcHist>().unwrap();
|
||||||
let mut numbers : Vec<u32> = vec![];
|
let maxtick : u64 = hist.1.0;
|
||||||
for i in 0..num_interrupts {
|
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
||||||
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64)).try_into().expect("ticks > u32")));
|
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")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,10 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use libafl_bolts::rands::Rand;
|
use libafl_bolts::rands::Rand;
|
||||||
|
|
||||||
|
use crate::clock::FUZZ_START_TIMESTAMP;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
use std::{fs::OpenOptions, io::Write};
|
||||||
|
|
||||||
//============================= Data Structures
|
//============================= Data Structures
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Default, Hash)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Default, Hash)]
|
||||||
pub struct STGNode
|
pub struct STGNode
|
||||||
@ -147,7 +151,9 @@ pub struct STGFeedbackState
|
|||||||
entrypoint: NodeIndex,
|
entrypoint: NodeIndex,
|
||||||
exitpoint: NodeIndex,
|
exitpoint: NodeIndex,
|
||||||
// Metadata about aggregated traces. aggegated meaning, order has been removed
|
// 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 {
|
impl Default for STGFeedbackState {
|
||||||
@ -176,6 +182,8 @@ impl Default for STGFeedbackState {
|
|||||||
entrypoint,
|
entrypoint,
|
||||||
exitpoint,
|
exitpoint,
|
||||||
worst_observed_per_aggegated_path: HashMap::new(),
|
worst_observed_per_aggegated_path: HashMap::new(),
|
||||||
|
worst_observed_per_abb_path: HashMap::new(),
|
||||||
|
worst_observed_per_stg_path: HashMap::new(),
|
||||||
systemstate_index,
|
systemstate_index,
|
||||||
state_abb_hash_index
|
state_abb_hash_index
|
||||||
}
|
}
|
||||||
@ -195,16 +203,35 @@ impl Named for STGFeedbackState
|
|||||||
pub struct STGNodeMetadata {
|
pub struct STGNodeMetadata {
|
||||||
pub nodes: Vec<NodeIndex>,
|
pub nodes: Vec<NodeIndex>,
|
||||||
pub edges: Vec<EdgeIndex>,
|
pub edges: Vec<EdgeIndex>,
|
||||||
|
pub abbs: Vec<AtomicBasicBlock>,
|
||||||
pub intervals: Vec<ExecInterval>,
|
pub intervals: Vec<ExecInterval>,
|
||||||
indices: Vec<usize>,
|
indices: Vec<usize>,
|
||||||
tcref: isize,
|
tcref: isize,
|
||||||
}
|
}
|
||||||
impl STGNodeMetadata {
|
impl STGNodeMetadata {
|
||||||
pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, intervals: Vec<ExecInterval>) -> Self{
|
pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, abbs: Vec<AtomicBasicBlock>, intervals: Vec<ExecInterval>) -> Self{
|
||||||
let mut indices : Vec<_> = edges.iter().map(|x| x.index()).collect();
|
let mut indices : Vec<_> = vec![];
|
||||||
indices.sort_unstable();
|
#[cfg(all(feature = "sched_stg",not(any(feature = "sched_stg_pathhash",feature = "sched_stg_abbhash",feature = "sched_stg_aggregatehash"))))]
|
||||||
indices.dedup();
|
{
|
||||||
Self {indices, intervals, nodes, edges, tcref: 0}
|
indices = edges.iter().map(|x| x.index()).collect();
|
||||||
|
indices.sort_unstable();
|
||||||
|
indices.dedup();
|
||||||
|
}
|
||||||
|
#[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 {
|
impl AsSlice for STGNodeMetadata {
|
||||||
@ -247,18 +274,29 @@ pub struct StgFeedback
|
|||||||
last_node_trace: Option<Vec<NodeIndex>>,
|
last_node_trace: Option<Vec<NodeIndex>>,
|
||||||
last_edge_trace: Option<Vec<EdgeIndex>>,
|
last_edge_trace: Option<Vec<EdgeIndex>>,
|
||||||
last_intervals: Option<Vec<ExecInterval>>,
|
last_intervals: Option<Vec<ExecInterval>>,
|
||||||
|
last_abbs: Option<Vec<AtomicBasicBlock>>,
|
||||||
|
dump_path: Option<PathBuf>
|
||||||
}
|
}
|
||||||
#[cfg(feature = "feed_stg")]
|
#[cfg(feature = "feed_stg")]
|
||||||
const INTEREST_EDGE : bool = true;
|
const INTEREST_EDGE : bool = true;
|
||||||
#[cfg(feature = "feed_stg")]
|
#[cfg(feature = "feed_stg")]
|
||||||
const INTEREST_NODE : bool = true;
|
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;
|
const INTEREST_AGGREGATE : bool = true;
|
||||||
|
|
||||||
#[cfg(not(feature = "feed_stg"))]
|
#[cfg(not(feature = "feed_stg"))]
|
||||||
const INTEREST_EDGE : bool = false;
|
const INTEREST_EDGE : bool = false;
|
||||||
#[cfg(not(feature = "feed_stg"))]
|
#[cfg(not(feature = "feed_stg"))]
|
||||||
const INTEREST_NODE : bool = false;
|
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;
|
const INTEREST_AGGREGATE : bool = false;
|
||||||
fn set_observer_map(trace : &Vec<EdgeIndex>) {
|
fn set_observer_map(trace : &Vec<EdgeIndex>) {
|
||||||
unsafe {
|
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 {
|
impl StgFeedback {
|
||||||
pub fn new() -> Self {
|
pub fn new(dump_name: Option<PathBuf>) -> Self {
|
||||||
Self {name: String::from("STGFeedback"), last_node_trace: None, last_edge_trace: None, last_intervals: None }
|
// 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:
|
/// params:
|
||||||
@ -287,10 +338,11 @@ impl StgFeedback {
|
|||||||
/// newly discovered node?
|
/// newly discovered node?
|
||||||
/// side effect:
|
/// side effect:
|
||||||
/// the graph gets new nodes and edge
|
/// 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_node_trace = vec![fbs.entrypoint];
|
||||||
let mut return_edge_trace = vec![];
|
let mut return_edge_trace = vec![];
|
||||||
let mut interesting = false;
|
let mut interesting = false;
|
||||||
|
let mut updated = false;
|
||||||
// add all missing state+abb combinations to the graph
|
// add all missing state+abb combinations to the graph
|
||||||
for (i,interval) in trace.iter().enumerate() { // Iterate intervals
|
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()};
|
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.stgnode_index.insert(h_node, idx);
|
||||||
fbs.state_abb_hash_index.insert(h, idx);
|
fbs.state_abb_hash_index.insert(h, idx);
|
||||||
interesting |= INTEREST_NODE;
|
interesting |= INTEREST_NODE;
|
||||||
|
updated = true;
|
||||||
idx
|
idx
|
||||||
};
|
};
|
||||||
// connect in graph if edge not present
|
// 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()});
|
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_);
|
return_edge_trace.push(e_);
|
||||||
interesting |= INTEREST_EDGE;
|
interesting |= INTEREST_EDGE;
|
||||||
|
updated = true;
|
||||||
}
|
}
|
||||||
return_node_trace.push(next_idx);
|
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") });
|
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_);
|
return_edge_trace.push(e_);
|
||||||
interesting |= INTEREST_EDGE;
|
interesting |= INTEREST_EDGE;
|
||||||
|
updated = true;
|
||||||
}
|
}
|
||||||
return_node_trace.push(fbs.exitpoint);
|
return_node_trace.push(fbs.exitpoint);
|
||||||
#[cfg(feature = "feed_stg")]
|
#[cfg(feature = "feed_stg")]
|
||||||
set_observer_map(&return_edge_trace);
|
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> {
|
fn abbs_in_exec_order(trace: &Vec<ExecInterval>) -> Vec<AtomicBasicBlock> {
|
||||||
@ -382,21 +437,53 @@ 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);
|
||||||
|
|
||||||
if INTEREST_AGGREGATE {
|
{
|
||||||
let mut tmp = StgFeedback::abbs_in_exec_order(&observer.last_trace);
|
let h = get_generic_hash(&edgetrace);
|
||||||
// aggegation by sorting, order of states is not relevant
|
if let Some(x) = feedbackstate.worst_observed_per_stg_path.get_mut(&h) {
|
||||||
tmp.sort();
|
|
||||||
if let Some(x) = feedbackstate.worst_observed_per_aggegated_path.get_mut(&tmp) {
|
|
||||||
let t = clock_observer.last_runtime();
|
let t = clock_observer.last_runtime();
|
||||||
if t > *x {
|
if t > *x {
|
||||||
*x = t;
|
*x = t;
|
||||||
interesting |= INTEREST_AGGREGATE;
|
interesting |= INTEREST_PATH;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
feedbackstate.worst_observed_per_aggegated_path.insert(tmp, clock_observer.last_runtime());
|
feedbackstate.worst_observed_per_stg_path.insert(h, clock_observer.last_runtime());
|
||||||
interesting |= INTEREST_AGGREGATE;
|
updated = true;
|
||||||
|
interesting |= INTEREST_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
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());
|
||||||
|
interesting |= INTEREST_AGGREGATE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,17 +494,31 @@ where
|
|||||||
self.last_node_trace = Some(nodetrace);
|
self.last_node_trace = Some(nodetrace);
|
||||||
self.last_edge_trace = Some(edgetrace);
|
self.last_edge_trace = Some(edgetrace);
|
||||||
self.last_intervals = Some(observer.last_trace.clone());
|
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)
|
Ok(interesting)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<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 nodes = self.last_node_trace.take();
|
||||||
let edges = self.last_edge_trace.take();
|
let edges = self.last_edge_trace.take();
|
||||||
|
let abbs = self.last_abbs.take();
|
||||||
match nodes {
|
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 => (),
|
None => (),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user