refactor interrupt mutation
This commit is contained in:
parent
835d1e1a79
commit
8165fd7cfc
@ -27,15 +27,15 @@ use super::stg::{STGEdge, STGNode};
|
|||||||
|
|
||||||
pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize,u32)) -> Vec<u32> {
|
pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize,u32)) -> Vec<u32> {
|
||||||
let len = buf.len();
|
let len = buf.len();
|
||||||
let mut start_tick : u32 = 0;
|
let mut start_tick;
|
||||||
let mut ret = Vec::with_capacity(DO_NUM_INTERRUPT);
|
let mut ret = Vec::with_capacity(min(DO_NUM_INTERRUPT, len/4));
|
||||||
for i in 0..DO_NUM_INTERRUPT {
|
for i in 0..DO_NUM_INTERRUPT {
|
||||||
let mut t : [u8; 4] = [0,0,0,0];
|
let mut buf4b : [u8; 4] = [0,0,0,0];
|
||||||
if len > (i+1)*4 {
|
if len >= (i+1)*4 {
|
||||||
for j in 0usize..4usize {
|
for j in 0usize..4usize {
|
||||||
t[j]=buf[i*4+j];
|
buf4b[j]=buf[i*4+j];
|
||||||
}
|
}
|
||||||
start_tick = u32::from_le_bytes(t);
|
start_tick = u32::from_le_bytes(buf4b);
|
||||||
if start_tick < FIRST_INT {start_tick=0;}
|
if start_tick < FIRST_INT {start_tick=0;}
|
||||||
ret.push(start_tick);
|
ret.push(start_tick);
|
||||||
} else {break;}
|
} else {break;}
|
||||||
@ -53,6 +53,14 @@ pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize,u32)) -> Vec<u3
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn interrupt_times_to_input_bytes(interrupt_times: &[u32]) -> Vec<u8> {
|
||||||
|
let mut ret = Vec::with_capacity(interrupt_times.len()*4);
|
||||||
|
for i in interrupt_times {
|
||||||
|
ret.extend(u32::to_le_bytes(*i));
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//======================= Custom mutator
|
//======================= Custom mutator
|
||||||
|
|
||||||
@ -136,260 +144,234 @@ where
|
|||||||
myrand.set_seed(state.rand_mut().next());
|
myrand.set_seed(state.rand_mut().next());
|
||||||
|
|
||||||
|
|
||||||
let mut loopcount = 0;
|
let mut rerun_count = 0; // count how many times we rerun the executor
|
||||||
let mut loopbound = 50;
|
// Try many times to find a mutation that is not already in the corpus
|
||||||
loop {
|
let loopbound = 50;
|
||||||
|
for _ in 0..loopbound {
|
||||||
|
// Choose which isr to mutate
|
||||||
let interrup_config = match myrand.choose(&self.interrup_config) {
|
let interrup_config = match myrand.choose(&self.interrup_config) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
Option::None => return Ok(())
|
Option::None => return Ok(())
|
||||||
};
|
};
|
||||||
let name = format!("isr_{}_times", interrup_config.0);
|
let name = format!("isr_{}_times", interrup_config.0);
|
||||||
// manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?;
|
// manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?;
|
||||||
loopbound-=1;
|
|
||||||
let current_case = state.current_testcase()?;
|
|
||||||
let old_input = current_case.input().as_ref().unwrap();
|
|
||||||
let old_interrupt_times = old_input.parts_by_name(&name).next();
|
|
||||||
let mut new_input = old_input.clone();
|
|
||||||
|
|
||||||
let mut new_interrupt_times : &mut I = if new_input.parts_by_name(&name).next().is_some() {
|
let curr_case = state.current_testcase()?;
|
||||||
new_input.parts_by_name_mut(&name).next().unwrap()
|
let curr_input = curr_case.input().as_ref().unwrap();
|
||||||
} else {
|
|
||||||
new_input.add_part(String::from(&name), I::default()); new_input.parts_by_name_mut(&name).next().unwrap()
|
|
||||||
}.1;
|
|
||||||
let mut do_rerun = false;
|
|
||||||
// if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
|
|
||||||
{
|
|
||||||
|
|
||||||
// produce a slice of absolute interrupt times
|
let mut new_input = curr_input.clone();
|
||||||
let mut interrupt_offsets : [u32; MAX_NUM_INTERRUPT] = [u32::MAX; MAX_NUM_INTERRUPT];
|
let new_interrupt_part : &mut I = if new_input.parts_by_name(&name).next().is_some() {
|
||||||
let mut num_interrupts : usize = 0;
|
new_input.parts_by_name_mut(&name).next().unwrap()
|
||||||
|
} else {
|
||||||
|
new_input.add_part(String::from(&name), I::default()); new_input.parts_by_name_mut(&name).next().unwrap()
|
||||||
|
}.1;
|
||||||
|
let old_interrupt_times = input_bytes_to_interrupt_times(new_interrupt_part.bytes(), *interrup_config);
|
||||||
|
let mut new_interrupt_times = Vec::with_capacity(MAX_NUM_INTERRUPT);
|
||||||
|
let mut do_rerun = false;
|
||||||
|
// if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
|
||||||
{
|
{
|
||||||
let t = input_bytes_to_interrupt_times(new_interrupt_times.bytes(), *interrup_config);
|
#[cfg(feature = "mutate_stg")]
|
||||||
for i in 0..t.len() {interrupt_offsets[i]=t[i];}
|
|
||||||
num_interrupts=t.len();
|
|
||||||
}
|
|
||||||
interrupt_offsets.sort_unstable();
|
|
||||||
|
|
||||||
// println!("Vor Mutator: {:?}", interrupt_offsets[0..num_interrupts].to_vec());
|
|
||||||
let mut prefix : Vec<[u8; 4]> = vec![];
|
|
||||||
// let mut suffix : Vec<u8> = vec![];
|
|
||||||
#[cfg(feature = "mutate_stg")]
|
|
||||||
{
|
|
||||||
let metadata = state.metadata_map();
|
|
||||||
let hist = metadata.get::<IcHist>().unwrap();
|
|
||||||
let maxtick : u64 = hist.1.0;
|
|
||||||
drop(hist);
|
|
||||||
{
|
{
|
||||||
let choice = myrand.between(1,100);
|
let metadata = state.metadata_map();
|
||||||
if choice <= 25 || *interrupt_offsets.get(0).unwrap_or(&u32::MAX) as u64 > maxtick { // 0.5*0.25 = 12.5% of the time fully randomize all interrupts
|
let maxtick = {metadata.get::<IcHist>().unwrap().1.0};
|
||||||
do_rerun = true;
|
drop(new_interrupt_part.drain(..).collect::<Vec<u8>>());
|
||||||
// let metadata = state.metadata_map();
|
{
|
||||||
let hist = metadata.get::<IcHist>().unwrap();
|
let choice = myrand.between(1,100);
|
||||||
let maxtick : u64 = hist.1.0;
|
if choice <= 25 || *old_interrupt_times.get(0).unwrap_or(&u32::MAX) as u64 > maxtick { // 0.5*0.25 = 12.5% of the time fully randomize all interrupts
|
||||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
do_rerun = true;
|
||||||
let mut numbers : Vec<u32> = vec![];
|
let hist = metadata.get::<IcHist>().unwrap();
|
||||||
for i in 0..myrand.between(0,2*min(MAX_NUM_INTERRUPT, maxtick as usize / (interrup_config.1 as usize * QEMU_ISNS_PER_USEC as usize))) {
|
let maxtick : u64 = hist.1.0;
|
||||||
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64) as usize).try_into().expect("ticks > u32")));
|
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
||||||
|
for _ in 0..myrand.between(0,min(MAX_NUM_INTERRUPT, (maxtick as usize * 3) / (interrup_config.1 as usize * QEMU_ISNS_PER_USEC as usize * 2))) {
|
||||||
|
new_interrupt_times.push(myrand.between(0, min(maxtick, u32::MAX as u64) as usize).try_into().expect("ticks > u32"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if choice <= 75 { // 0.5 * 0.25 = 12.5% of cases
|
||||||
else if choice <= 75 { // 0.5 * 0.25 = 12.5% of cases
|
let feedbackstate = match state
|
||||||
let feedbackstate = match state
|
.named_metadata_map()
|
||||||
.named_metadata_map()
|
.get::<STGFeedbackState>("stgfeedbackstate") {
|
||||||
.get::<STGFeedbackState>("stgfeedbackstate") {
|
Some(s) => s,
|
||||||
Some(s) => s,
|
Option::None => {
|
||||||
Option::None => {
|
panic!("STGfeedbackstate not visible")
|
||||||
panic!("STGfeedbackstate not visible")
|
}
|
||||||
|
};
|
||||||
|
if let Some(meta) = curr_case.metadata_map().get::<STGNodeMetadata>() {
|
||||||
|
if let Some(t) = try_force_new_branches(&old_interrupt_times, feedbackstate, meta, *interrup_config) {
|
||||||
|
do_rerun = true;
|
||||||
|
new_interrupt_times=t;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
if let Some(meta) = current_case.metadata_map().get::<STGNodeMetadata>() {
|
// let tmp = current_case.metadata_map().get::<STGNodeMetadata>();
|
||||||
if let Some(t) = try_force_new_branches(&interrupt_offsets, feedbackstate, meta, *interrup_config) {
|
// if tmp.is_some() {
|
||||||
do_rerun = true;
|
// let trace = tmp.expect("STGNodeMetadata not found");
|
||||||
for i in 0..t.len() {
|
// let mut node_indices = vec![];
|
||||||
if i<num_interrupts {
|
// for i in (0..trace.intervals.len()).into_iter() {
|
||||||
interrupt_offsets[i]=t[i];
|
// if let Some(abb) = &trace.intervals[i].abb {
|
||||||
} else {break;}
|
// if let Some(idx) = feedbackstate.state_abb_hash_index.get(&(trace.intervals[i].start_state,abb.get_hash())) {
|
||||||
|
// node_indices.push(Some(idx));
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// node_indices.push(None);
|
||||||
|
// }
|
||||||
|
// // let mut marks : HashMap<u32, usize>= HashMap::new(); // interrupt -> block hit
|
||||||
|
// // for i in 0..trace.intervals.len() {
|
||||||
|
// // let curr = &trace.intervals[i];
|
||||||
|
// // let m = interrupt_offsets[0..num_interrupts].iter().filter(|x| (curr.start_tick..curr.end_tick).contains(&((**x) as u64)));
|
||||||
|
// // for k in m {
|
||||||
|
// // marks.insert(*k,i);
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // walk backwards trough the trace and try moving the interrupt to a block that does not have an outgoing interrupt edge or ist already hit by a predecessor
|
||||||
|
// for i in (0..num_interrupts).rev() {
|
||||||
|
// let mut lb = FIRST_INT;
|
||||||
|
// let mut ub : u32 = trace.intervals[trace.intervals.len()-1].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});
|
||||||
|
// }
|
||||||
|
// let alternatives : Vec<_> = (0..trace.intervals.len()).filter(|x|
|
||||||
|
// node_indices[*x].is_some() &&
|
||||||
|
// (trace.intervals[*x].start_tick < (lb as u64) && (lb as u64) < trace.intervals[*x].end_tick
|
||||||
|
// || trace.intervals[*x].start_tick > (lb as u64) && trace.intervals[*x].start_tick < (ub as u64))
|
||||||
|
// ).collect();
|
||||||
|
// let not_yet_hit : Vec<_> = alternatives.iter().filter(
|
||||||
|
// |x| feedbackstate.graph.edges_directed(*node_indices[**x].unwrap(), petgraph::Direction::Outgoing).any(|y| y.weight().event != CaptureEvent::ISRStart)).collect();
|
||||||
|
// if not_yet_hit.len() > 0 {
|
||||||
|
// let replacement = &trace.intervals[*myrand.choose(not_yet_hit).unwrap()];
|
||||||
|
// interrupt_offsets[i] = (myrand.between(replacement.start_tick as usize,
|
||||||
|
// replacement.end_tick as usize)).try_into().expect("ticks > u32");
|
||||||
|
// // println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
||||||
|
// do_rerun = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
else { // old version of the alternative search
|
||||||
|
new_interrupt_times = old_interrupt_times.clone();
|
||||||
|
let tmp = curr_case.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 = old_interrupt_times.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..old_interrupt_times.len() {
|
||||||
}
|
// bounds based on minimum inter-arrival time
|
||||||
}
|
let mut lb = FIRST_INT;
|
||||||
// let tmp = current_case.metadata_map().get::<STGNodeMetadata>();
|
let mut ub : u32 = trace.intervals[trace.intervals.len()-1].end_tick.try_into().expect("ticks > u32");
|
||||||
// if tmp.is_some() {
|
if i > 0 {
|
||||||
// let trace = tmp.expect("STGNodeMetadata not found");
|
// use the new times, because changes to preceding timings are not accounted for yet
|
||||||
// let mut node_indices = vec![];
|
lb = u32::saturating_add(new_interrupt_times[i-1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||||
// for i in (0..trace.intervals.len()).into_iter() {
|
}
|
||||||
// if let Some(abb) = &trace.intervals[i].abb {
|
if i < old_interrupt_times.len()-1 {
|
||||||
// if let Some(idx) = feedbackstate.state_abb_hash_index.get(&(trace.intervals[i].start_state,abb.get_hash())) {
|
ub = u32::saturating_sub(new_interrupt_times[i+1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||||
// node_indices.push(Some(idx));
|
}
|
||||||
// continue;
|
// get old hit and handler
|
||||||
// }
|
let old_hit = marks.iter().filter(
|
||||||
// }
|
|x| x.0.start_tick < (old_interrupt_times[i] as u64) && (old_interrupt_times[i] as u64) < x.0.end_tick
|
||||||
// node_indices.push(None);
|
).next();
|
||||||
// }
|
let old_handler = match old_hit {
|
||||||
// // let mut marks : HashMap<u32, usize>= HashMap::new(); // interrupt -> block hit
|
Some(s) => if s.1 < old_interrupt_times.len()-1 && s.1 < marks.len()-1 {
|
||||||
// // for i in 0..trace.intervals.len() {
|
Some(marks[s.1+1])
|
||||||
// // let curr = &trace.intervals[i];
|
} else {None},
|
||||||
// // let m = interrupt_offsets[0..num_interrupts].iter().filter(|x| (curr.start_tick..curr.end_tick).contains(&((**x) as u64)));
|
None => None
|
||||||
// // for k in m {
|
};
|
||||||
// // marks.insert(*k,i);
|
// find reachable alternatives
|
||||||
// // }
|
let alternatives : Vec<_> = marks.iter().filter(|x|
|
||||||
// // }
|
x.2 != 2 &&
|
||||||
// // walk backwards trough the trace and try moving the interrupt to a block that does not have an outgoing interrupt edge or ist already hit by a predecessor
|
(
|
||||||
// for i in (0..num_interrupts).rev() {
|
x.0.start_tick < (lb as u64) && (lb as u64) < x.0.end_tick
|
||||||
// let mut lb = FIRST_INT;
|
|| x.0.start_tick > (lb as u64) && x.0.start_tick < (ub as u64))
|
||||||
// let mut ub : u32 = trace.intervals[trace.intervals.len()-1].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});
|
|
||||||
// }
|
|
||||||
// let alternatives : Vec<_> = (0..trace.intervals.len()).filter(|x|
|
|
||||||
// node_indices[*x].is_some() &&
|
|
||||||
// (trace.intervals[*x].start_tick < (lb as u64) && (lb as u64) < trace.intervals[*x].end_tick
|
|
||||||
// || trace.intervals[*x].start_tick > (lb as u64) && trace.intervals[*x].start_tick < (ub as u64))
|
|
||||||
// ).collect();
|
|
||||||
// let not_yet_hit : Vec<_> = alternatives.iter().filter(
|
|
||||||
// |x| feedbackstate.graph.edges_directed(*node_indices[**x].unwrap(), petgraph::Direction::Outgoing).any(|y| y.weight().event != CaptureEvent::ISRStart)).collect();
|
|
||||||
// if not_yet_hit.len() > 0 {
|
|
||||||
// let replacement = &trace.intervals[*myrand.choose(not_yet_hit).unwrap()];
|
|
||||||
// interrupt_offsets[i] = (myrand.between(replacement.start_tick as usize,
|
|
||||||
// replacement.end_tick as usize)).try_into().expect("ticks > u32");
|
|
||||||
// // println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
|
||||||
// do_rerun = true;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
else { // old version of the alternative search
|
|
||||||
let tmp = current_case.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 = FIRST_INT;
|
|
||||||
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], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
|
||||||
}
|
|
||||||
if i < num_interrupts-1 {
|
|
||||||
ub = u32::saturating_sub(interrupt_offsets[i+1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
|
||||||
}
|
|
||||||
// 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 > (lb as u64) && x.0.start_tick < (ub as u64))
|
|
||||||
).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();
|
).collect();
|
||||||
if untouched.len() > 0 {
|
// in cases there are no alternatives
|
||||||
let tmp = interrupt_offsets[i];
|
if alternatives.len() == 0 {
|
||||||
let choice = myrand.choose(untouched).unwrap();
|
if old_hit.is_none() {
|
||||||
interrupt_offsets[i] = myrand.between(choice.0.start_tick as usize, choice.0.end_tick as usize)
|
// choose something random
|
||||||
.try_into().expect("tick > u32");
|
let untouched : Vec<_> = marks.iter().filter(
|
||||||
|
|x| x.2 == 0
|
||||||
|
).collect();
|
||||||
|
if untouched.len() > 0 {
|
||||||
|
let tmp = old_interrupt_times[i];
|
||||||
|
let choice = myrand.choose(untouched).unwrap();
|
||||||
|
new_interrupt_times[i] = myrand.between(choice.0.start_tick as usize, choice.0.end_tick as usize)
|
||||||
|
.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).unwrap();
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
let extra = if (old_hit.map_or(false, |x| x.1 < replacement.1)) {
|
||||||
|
// move futher back, respect old_handler
|
||||||
|
old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick)
|
||||||
|
} else { 0 };
|
||||||
|
// let tmp = new_interrupt_times[i];
|
||||||
|
new_interrupt_times[i] = (myrand.between(replacement.0.start_tick as usize,
|
||||||
|
replacement.0.end_tick as usize) + extra as usize).try_into().expect("ticks > u32");
|
||||||
|
// println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
||||||
do_rerun = true;
|
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;
|
|
||||||
}
|
}
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
|
new_interrupt_part.extend(&interrupt_times_to_input_bytes(&new_interrupt_times));
|
||||||
}
|
}
|
||||||
let replacement = myrand.choose(alternatives).unwrap();
|
|
||||||
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;
|
|
||||||
} else {
|
|
||||||
let extra = if (old_hit.map_or(false, |x| x.1 < replacement.1)) {
|
|
||||||
// move futher back, respect old_handler
|
|
||||||
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 as usize,
|
|
||||||
replacement.0.end_tick as usize) + extra as usize).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"))]
|
{
|
||||||
{
|
if myrand.between(1,100) <= 25 { // we have no hint if interrupt times will change anything
|
||||||
if myrand.between(1,100) <= 25 { // we have no hint if interrupt times will change anything
|
do_rerun = true;
|
||||||
do_rerun = true;
|
let metadata = state.metadata_map();
|
||||||
let metadata = state.metadata_map();
|
let maxtick = {metadata.get::<IcHist>().unwrap().1.0};
|
||||||
let hist = metadata.get::<IcHist>().unwrap();
|
new_interrupt_times = Vec::with_capacity(MAX_NUM_INTERRUPT);
|
||||||
let maxtick : u64 = hist.1.0;
|
for i in 0..myrand.between(0,min(MAX_NUM_INTERRUPT, (maxtick as usize * 3) / (interrup_config.1 as usize * QEMU_ISNS_PER_USEC as usize * 2))) {
|
||||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
new_interrupt_times.push(myrand.between(0, min(maxtick, u32::MAX as u64) as usize).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 as usize, u32::MAX as usize)).try_into().expect("ticks > u32")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
new_interrupt_part.extend(&interrupt_times_to_input_bytes(&new_interrupt_times));
|
||||||
}
|
}
|
||||||
let _t= new_interrupt_times.drain(..).collect::<Vec<_>>();
|
drop(curr_case);
|
||||||
drop(_t);
|
if do_rerun {
|
||||||
new_interrupt_times.extend(&prefix.concat());
|
rerun_count+=1;
|
||||||
}
|
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, new_input)?;
|
||||||
drop(current_case);
|
if corpus_idx.is_none() && loopbound<=0 { break;}
|
||||||
// InterruptShifterMutator::mutate(&mut mymut, state, &mut input, 0)?;
|
} else {if loopbound<=0 {break;}}
|
||||||
if do_rerun {
|
|
||||||
loopcount+=1;
|
|
||||||
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, new_input)?;
|
|
||||||
if corpus_idx.is_none() && loopbound<=0 { break;}
|
|
||||||
} else {if loopbound<=0 {break;}}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user