add sysstate feedback
This commit is contained in:
parent
b85e0a6d5b
commit
b73a971c51
@ -1,5 +1,11 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
|
use libafl_qemu::QemuInstrumentationFilter;
|
||||||
|
use wcet_qemu_sys::system_trace::QemuSystemStateHelper;
|
||||||
|
use wcet_qemu_sys::system_trace::QemuSysStateObserver;
|
||||||
|
use wcet_qemu_sys::system_trace::FreeRTOSSystemStateMetadata;
|
||||||
|
use wcet_qemu_sys::system_trace::SysStateFeedbackState;
|
||||||
|
use wcet_qemu_sys::system_trace::NovelSysStateFeedback;
|
||||||
use wcet_qemu_sys::worst::QemuHashMapObserver;
|
use wcet_qemu_sys::worst::QemuHashMapObserver;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
@ -238,6 +244,21 @@ fn fuzz(
|
|||||||
let check_breakpoint = virt2phys(check_breakpoint,&elf.goblin());
|
let check_breakpoint = virt2phys(check_breakpoint,&elf.goblin());
|
||||||
println!("Breakpoint at {:#x}", check_breakpoint);
|
println!("Breakpoint at {:#x}", check_breakpoint);
|
||||||
|
|
||||||
|
let curr_tcb_pointer = elf // loads to the address specified in elf, without respecting program headers
|
||||||
|
.resolve_symbol("pxCurrentTCB", 0)
|
||||||
|
.expect("Symbol pxCurrentTCBC not found");
|
||||||
|
// let curr_tcb_pointer = virt2phys(curr_tcb_pointer,&elf.goblin());
|
||||||
|
println!("TCB pointer at {:#x}", curr_tcb_pointer);
|
||||||
|
let task_queue_addr = elf
|
||||||
|
.resolve_symbol("pxReadyTasksLists", 0)
|
||||||
|
.expect("Symbol pxReadyTasksLists not found");
|
||||||
|
// let task_queue_addr = virt2phys(task_queue_addr,&elf.goblin());
|
||||||
|
println!("Task Queue at {:#x}", task_queue_addr);
|
||||||
|
let svh = elf
|
||||||
|
.resolve_symbol("xPortPendSVHandler", 0)
|
||||||
|
.expect("Symbol xPortPendSVHandler not found");
|
||||||
|
let svh = virt2phys(svh,&elf.goblin());
|
||||||
|
|
||||||
//=========== Prepare Emulator Args
|
//=========== Prepare Emulator Args
|
||||||
let args: Vec<String> = vec![
|
let args: Vec<String> = vec![
|
||||||
"qemu-system-arm",
|
"qemu-system-arm",
|
||||||
@ -289,6 +310,9 @@ fn fuzz(
|
|||||||
// The state of the edges feedback.
|
// The state of the edges feedback.
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||||
|
|
||||||
|
let sysstate_observer = QemuSysStateObserver::new();
|
||||||
|
let sysstate_feedback_state = SysStateFeedbackState::default();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
let target_map : HashMap<(u64,u64),u8> = match dump_edges {
|
let target_map : HashMap<(u64,u64),u8> = match dump_edges {
|
||||||
@ -304,7 +328,8 @@ fn fuzz(
|
|||||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||||
HitImprovingFeedback::new(target_map.clone(), &edges_observer),
|
HitImprovingFeedback::new(target_map.clone(), &edges_observer),
|
||||||
QemuClockIncreaseFeedback::default(),
|
QemuClockIncreaseFeedback::default(),
|
||||||
ClockFeedback::new_with_observer(&clock_observer)
|
ClockFeedback::new_with_observer(&clock_observer),
|
||||||
|
NovelSysStateFeedback::default()
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
@ -323,7 +348,7 @@ fn fuzz(
|
|||||||
OnDiskCorpus::new(&objective_dir).unwrap(),
|
OnDiskCorpus::new(&objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// They are the data related to the feedbacks that you want to persist in the State.
|
||||||
tuple_list!(feedback_state,clock::MaxIcountMetadata::default()),
|
tuple_list!(feedback_state,clock::MaxIcountMetadata::default(),sysstate_feedback_state),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -365,6 +390,7 @@ fn fuzz(
|
|||||||
ExitKind::Ok
|
ExitKind::Ok
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let system_state_filter = QemuInstrumentationFilter::AllowList(vec![svh..svh+1]);
|
||||||
let executor = QemuExecutor::new(
|
let executor = QemuExecutor::new(
|
||||||
&mut harness,
|
&mut harness,
|
||||||
&emu,
|
&emu,
|
||||||
@ -372,9 +398,10 @@ fn fuzz(
|
|||||||
QemuEdgeCoverageHelper::new(),
|
QemuEdgeCoverageHelper::new(),
|
||||||
QemuCmpLogHelper::new(),
|
QemuCmpLogHelper::new(),
|
||||||
//QemuAsanHelper::new(),
|
//QemuAsanHelper::new(),
|
||||||
QemuSysSnapshotHelper::new()
|
QemuSysSnapshotHelper::new(),
|
||||||
|
QemuSystemStateHelper::with_instrumentation_filter(system_state_filter,curr_tcb_pointer.try_into().unwrap(),task_queue_addr.try_into().unwrap())
|
||||||
),
|
),
|
||||||
tuple_list!(edges_observer, clock_observer),
|
tuple_list!(edges_observer, clock_observer,sysstate_observer),
|
||||||
&mut fuzzer,
|
&mut fuzzer,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut mgr,
|
&mut mgr,
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
use libafl::feedbacks::FeedbackState;
|
||||||
|
use libafl::corpus::Testcase;
|
||||||
|
use libafl::state::HasFeedbackStates;
|
||||||
|
use libafl::bolts::tuples::MatchName;
|
||||||
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
use std::hash::Hasher;
|
||||||
|
use std::hash::Hash;
|
||||||
use crate::freertos::emu_lookup;
|
use crate::freertos::emu_lookup;
|
||||||
use crate::freertos::rtos_struct;
|
use crate::freertos::rtos_struct;
|
||||||
use crate::freertos::List_t;
|
use crate::freertos::List_t;
|
||||||
@ -37,7 +44,7 @@ pub struct FreeRTOSSystemStateRaw {
|
|||||||
dumping_ground: HashMap<u32,freertos::rtos_struct>,
|
dumping_ground: HashMap<u32,freertos::rtos_struct>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
pub struct MiniTCB {
|
pub struct MiniTCB {
|
||||||
task_name: String,
|
task_name: String,
|
||||||
priority: u32,
|
priority: u32,
|
||||||
@ -47,6 +54,16 @@ pub struct MiniTCB {
|
|||||||
notify_state: u8,
|
notify_state: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for MiniTCB {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.task_name.hash(state);
|
||||||
|
// self.priority.hash(state);
|
||||||
|
// self.mutexes_held.hash(state);
|
||||||
|
// self.notify_state.hash(state);
|
||||||
|
// self.notify_value.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MiniTCB {
|
impl MiniTCB {
|
||||||
pub fn from_tcb(input: &TCB_t) -> Self {
|
pub fn from_tcb(input: &TCB_t) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -62,18 +79,49 @@ impl MiniTCB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn from_tcb_owned(input: TCB_t) -> Self {
|
||||||
|
unsafe {
|
||||||
|
let tmp = std::mem::transmute::<[i8; 10],[u8; 10]>(input.pcTaskName);
|
||||||
|
let name : String = std::str::from_utf8(&tmp).expect("TCB name was not utf8").chars().filter(|x| *x != '\0').collect::<String>();
|
||||||
|
Self {
|
||||||
|
task_name: name,
|
||||||
|
priority: input.uxPriority,
|
||||||
|
base_priority: input.uxBasePriority,
|
||||||
|
mutexes_held: input.uxMutexesHeld,
|
||||||
|
notify_value: input.ulNotifiedValue[0],
|
||||||
|
notify_state: input.ucNotifyState[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Refined information about the states an execution transitioned between
|
/// Refined information about the states an execution transitioned between
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
pub struct QemuSystemStateMetadata {
|
pub struct MiniFreeRTOSSystemState {
|
||||||
start_tick: u64,
|
start_tick: u64,
|
||||||
end_tick: u64,
|
end_tick: u64,
|
||||||
current_task: MiniTCB,
|
current_task: MiniTCB,
|
||||||
ready_list_after: Vec<MiniTCB>,
|
ready_list_after: Vec<MiniTCB>,
|
||||||
}
|
}
|
||||||
|
|
||||||
libafl::impl_serdeany!(QemuSystemStateMetadata);
|
impl Hash for MiniFreeRTOSSystemState {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.current_task.hash(state);
|
||||||
|
// self.ready_list_after.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct FreeRTOSSystemStateMetadata {
|
||||||
|
inner: Vec<MiniFreeRTOSSystemState>,
|
||||||
|
}
|
||||||
|
impl FreeRTOSSystemStateMetadata {
|
||||||
|
pub fn new(inner: Vec<MiniFreeRTOSSystemState>) -> Self{
|
||||||
|
Self {inner: inner}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
libafl::impl_serdeany!(FreeRTOSSystemStateMetadata);
|
||||||
|
|
||||||
|
|
||||||
//============================= Qemu Helper
|
//============================= Qemu Helper
|
||||||
@ -206,7 +254,7 @@ pub fn gen_not_exec_block_hook<I, QT, S>(
|
|||||||
#[allow(clippy::unsafe_derive_deserialize)]
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
pub struct QemuSysStateObserver
|
pub struct QemuSysStateObserver
|
||||||
{
|
{
|
||||||
last_run: Vec<FreeRTOSSystemStateRaw>,
|
last_run: Vec<MiniFreeRTOSSystemState>,
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,8 +268,15 @@ impl<I, S> Observer<I, S> for QemuSysStateObserver
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
unsafe {self.last_run.append(&mut CURRENT_SYSSTATE_VEC);}
|
unsafe {self.last_run = parse_last(&mut CURRENT_SYSSTATE_VEC);}
|
||||||
println!("{:#?}",self.parse_last());
|
// let mut hasher = DefaultHasher::new();
|
||||||
|
// let mut a = self.parse_last();
|
||||||
|
// a[0].start_tick=21355;
|
||||||
|
// a[0].end_tick=2131;
|
||||||
|
// a.hash(&mut hasher);
|
||||||
|
// let somehash = hasher.finish();
|
||||||
|
// println!("HashValue: {}",somehash);
|
||||||
|
// println!("{:#?}",self.parse_last());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,31 +296,31 @@ impl HasLen for QemuSysStateObserver
|
|||||||
self.last_run.len()
|
self.last_run.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn parse_last(input: &mut Vec<FreeRTOSSystemStateRaw>) -> Vec<MiniFreeRTOSSystemState> {
|
||||||
|
let mut ret = Vec::<MiniFreeRTOSSystemState>::new();
|
||||||
|
let mut start_tick : u64 = 0;
|
||||||
|
for i in input.into_iter() {
|
||||||
|
let mut collector = Vec::<MiniTCB>::new();
|
||||||
|
for j in i.prio_ready_lists.into_iter().rev() {
|
||||||
|
let mut tmp = list_to_tcb_vec_owned(j,&mut i.dumping_ground).iter().map(|x| MiniTCB::from_tcb(x)).collect();
|
||||||
|
collector.append(&mut tmp);
|
||||||
|
}
|
||||||
|
ret.push(MiniFreeRTOSSystemState {
|
||||||
|
current_task: MiniTCB::from_tcb_owned(i.current_tcb),
|
||||||
|
start_tick: start_tick,
|
||||||
|
end_tick: i.qemu_tick,
|
||||||
|
ready_list_after: collector,
|
||||||
|
});
|
||||||
|
start_tick=i.qemu_tick;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
impl QemuSysStateObserver {
|
impl QemuSysStateObserver {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self{last_run: vec![], name: "sysstate".to_string()}
|
Self{last_run: vec![], name: "sysstate".to_string()}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_last(&self) -> Vec<QemuSystemStateMetadata> {
|
|
||||||
let mut ret = Vec::<QemuSystemStateMetadata>::new();
|
|
||||||
let mut start_tick : u64 = 0;
|
|
||||||
for i in 0..self.last_run.len() {
|
|
||||||
let mut collector = Vec::<MiniTCB>::new();
|
|
||||||
for j in self.last_run[i].prio_ready_lists.iter().rev() {
|
|
||||||
let mut tmp = list_to_tcb_vec(j,&self.last_run[i].dumping_ground).iter().map(|x| MiniTCB::from_tcb(x)).collect();
|
|
||||||
collector.append(&mut tmp);
|
|
||||||
}
|
|
||||||
ret.push(QemuSystemStateMetadata {
|
|
||||||
current_task: MiniTCB::from_tcb(&self.last_run[i].current_tcb),
|
|
||||||
start_tick: start_tick,
|
|
||||||
end_tick: self.last_run[i].qemu_tick,
|
|
||||||
ready_list_after: collector,
|
|
||||||
});
|
|
||||||
start_tick=self.last_run[i].qemu_tick;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_to_tcb_vec(list: &List_t, dump: &HashMap<u32,rtos_struct>) -> Vec<TCB_t>
|
pub fn list_to_tcb_vec(list: &List_t, dump: &HashMap<u32,rtos_struct>) -> Vec<TCB_t>
|
||||||
@ -298,51 +353,140 @@ pub fn list_to_tcb_vec(list: &List_t, dump: &HashMap<u32,rtos_struct>) -> Vec<TC
|
|||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
pub fn list_to_tcb_vec_owned(list: List_t, dump: &mut HashMap<u32,rtos_struct>) -> Vec<TCB_t>
|
||||||
|
{
|
||||||
|
let mut ret : Vec<TCB_t> = Vec::new();
|
||||||
|
if list.uxNumberOfItems == 0 {return ret;}
|
||||||
|
let last_list_item = match dump.remove(&list.pxIndex).expect("List_t entry was not in Hashmap") {
|
||||||
|
List_Item_struct(li) => li,
|
||||||
|
List_MiniItem_struct(mli) => match dump.remove(&mli.pxNext).expect("MiniListItem pointer invaild") {
|
||||||
|
List_Item_struct(li) => li,
|
||||||
|
_ => panic!("MiniListItem of a non empty List does not point to ListItem"),
|
||||||
|
},
|
||||||
|
_ => panic!("List_t entry was not a ListItem"),
|
||||||
|
};
|
||||||
|
let mut next_index = last_list_item.pxNext;
|
||||||
|
let last_tcb = match dump.remove(&last_list_item.pvOwner).expect("ListItem Owner not in Hashmap") {
|
||||||
|
TCB_struct(t) => t,
|
||||||
|
_ => panic!("List content does not equal type"),
|
||||||
|
};
|
||||||
|
for _ in 0..list.uxNumberOfItems-1 {
|
||||||
|
let next_list_item = match dump.remove(&next_index).expect("List_t entry was not in Hashmap") {
|
||||||
|
List_Item_struct(li) => li,
|
||||||
|
List_MiniItem_struct(mli) => match dump.remove(&mli.pxNext).expect("MiniListItem pointer invaild") {
|
||||||
|
List_Item_struct(li) => li,
|
||||||
|
_ => panic!("MiniListItem of a non empty List does not point to ListItem"),
|
||||||
|
},
|
||||||
|
_ => panic!("List_t entry was not a ListItem"),
|
||||||
|
};
|
||||||
|
match dump.remove(&next_list_item.pvOwner).expect("ListItem Owner not in Hashmap") {
|
||||||
|
TCB_struct(t) => {ret.push(t)},
|
||||||
|
_ => panic!("List content does not equal type"),
|
||||||
|
}
|
||||||
|
next_index=next_list_item.pxNext;
|
||||||
|
}
|
||||||
|
ret.push(last_tcb);
|
||||||
|
ret
|
||||||
|
}
|
||||||
//============================= Feedback
|
//============================= Feedback
|
||||||
|
|
||||||
/// A Feedback reporting interesting System-State Transitions
|
/// Shared Metadata for a SysStateFeedback
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||||
pub struct SysStateFeedback
|
pub struct SysStateFeedbackState
|
||||||
{
|
{
|
||||||
|
known_traces: HashMap<u64,(u64,usize)>,
|
||||||
|
longest: Vec<MiniFreeRTOSSystemState>,
|
||||||
}
|
}
|
||||||
|
impl Named for SysStateFeedbackState
|
||||||
impl<I, S> Feedback<I, S> for SysStateFeedback
|
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
S: HasClientPerfMonitor,
|
|
||||||
{
|
|
||||||
fn is_interesting<EM, OT>(
|
|
||||||
&mut self,
|
|
||||||
_state: &mut S,
|
|
||||||
_manager: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
_observers: &OT,
|
|
||||||
_exit_kind: &ExitKind,
|
|
||||||
) -> Result<bool, Error>
|
|
||||||
where
|
|
||||||
EM: EventFirer<I>,
|
|
||||||
OT: ObserversTuple<I, S>,
|
|
||||||
{
|
|
||||||
let observer = _observers.match_name::<QemuSysStateObserver>("sysstate")
|
|
||||||
.expect("QemuSysStateObserver not found");
|
|
||||||
// Do Stuff
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Named for SysStateFeedback
|
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"sysstate"
|
"sysstate"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl FeedbackState for SysStateFeedbackState
|
||||||
impl SysStateFeedback
|
|
||||||
{
|
{
|
||||||
/// Creates a new [`SysStateFeedback`]
|
fn reset(&mut self) -> Result<(), Error> {
|
||||||
#[must_use]
|
self.longest.clear();
|
||||||
pub fn new() -> Self {
|
self.known_traces.clear();
|
||||||
Self {}
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A Feedback reporting novel System-State Transitions
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||||
|
pub struct NovelSysStateFeedback
|
||||||
|
{
|
||||||
|
last_trace: Option<Vec<MiniFreeRTOSSystemState>>,
|
||||||
|
// known_traces: HashMap<u64,(u64,usize)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, S> Feedback<I, S> for NovelSysStateFeedback
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
S: HasClientPerfMonitor + HasFeedbackStates,
|
||||||
|
{
|
||||||
|
fn is_interesting<EM, OT>(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
|
_input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I>,
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
{
|
||||||
|
let observer = observers.match_name::<QemuSysStateObserver>("sysstate")
|
||||||
|
.expect("QemuSysStateObserver not found");
|
||||||
|
let feedbackstate = state
|
||||||
|
.feedback_states_mut()
|
||||||
|
.match_name_mut::<SysStateFeedbackState>("sysstate")
|
||||||
|
.unwrap();
|
||||||
|
// Do Stuff
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
observer.last_run.hash(&mut hasher);
|
||||||
|
let somehash = hasher.finish();
|
||||||
|
let mut is_novel = false;
|
||||||
|
match feedbackstate.known_traces.get_mut(&somehash) {
|
||||||
|
None => {
|
||||||
|
is_novel = true;
|
||||||
|
feedbackstate.known_traces.insert(somehash,(1,observer.last_run.len()));
|
||||||
|
}
|
||||||
|
Some(s) => s.0+=1,
|
||||||
|
}
|
||||||
|
if observer.last_run.len() > feedbackstate.longest.len() {
|
||||||
|
feedbackstate.longest=observer.last_run.clone();
|
||||||
|
}
|
||||||
|
self.last_trace = Some(observer.last_run.clone());
|
||||||
|
// if (!is_novel) { println!("not novel") };
|
||||||
|
Ok(is_novel)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||||
|
#[inline]
|
||||||
|
fn append_metadata(&mut self, _state: &mut S, testcase: &mut Testcase<I>) -> Result<(), Error> {
|
||||||
|
let a = self.last_trace.take();
|
||||||
|
match a {
|
||||||
|
Some(s) => testcase.metadata_mut().insert(FreeRTOSSystemStateMetadata::new(s)),
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
||||||
|
#[inline]
|
||||||
|
fn discard_metadata(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
self.last_trace = None;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for NovelSysStateFeedback
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"sysstate"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user