Observers refactor (#84)
* new observer structure with HasExecHooks * adapt libafl_frida to new observers * docstrings
This commit is contained in:
parent
116a51270c
commit
9e9d95f93d
@ -77,7 +77,6 @@ pub fn main() {
|
|||||||
|
|
||||||
// Create the executor for an in-process function with just one observer
|
// Create the executor for an in-process function with just one observer
|
||||||
let mut executor = InProcessExecutor::new(
|
let mut executor = InProcessExecutor::new(
|
||||||
"in-process(signals)",
|
|
||||||
&mut harness,
|
&mut harness,
|
||||||
tuple_list!(observer),
|
tuple_list!(observer),
|
||||||
&mut state,
|
&mut state,
|
||||||
|
@ -2,14 +2,15 @@
|
|||||||
//! The example harness is built for libpng.
|
//! The example harness is built for libpng.
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::tuples::{tuple_list, Named},
|
bolts::tuples::tuple_list,
|
||||||
corpus::{
|
corpus::{
|
||||||
ondisk::OnDiskMetadataFormat, Corpus, InMemoryCorpus,
|
ondisk::OnDiskMetadataFormat, Corpus, InMemoryCorpus,
|
||||||
IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler,
|
IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler,
|
||||||
},
|
},
|
||||||
events::{setup_restarting_mgr_std, EventManager},
|
events::setup_restarting_mgr_std,
|
||||||
executors::{
|
executors::{
|
||||||
inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, HasObservers,
|
inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, HasExecHooks,
|
||||||
|
HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
},
|
},
|
||||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
@ -37,14 +38,14 @@ use libafl_frida::{
|
|||||||
FridaOptions,
|
FridaOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT>
|
struct FridaInProcessExecutor<'a, 'b, 'c, EM, FH, H, I, OT, S>
|
||||||
where
|
where
|
||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
base: TimeoutExecutor<InProcessExecutor<'a, H, I, OT>, I, OT>,
|
base: TimeoutExecutor<InProcessExecutor<'a, EM, H, I, OT, S>, I>,
|
||||||
/// Frida's dynamic rewriting engine
|
/// Frida's dynamic rewriting engine
|
||||||
stalker: Stalker<'a>,
|
stalker: Stalker<'a>,
|
||||||
/// User provided callback for instrumentation
|
/// User provided callback for instrumentation
|
||||||
@ -53,19 +54,17 @@ where
|
|||||||
_phantom: PhantomData<&'b u8>,
|
_phantom: PhantomData<&'b u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'c, FH, H, I, OT> Executor<I> for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT>
|
impl<'a, 'b, 'c, EM, FH, H, I, OT, S> Executor<I>
|
||||||
|
for FridaInProcessExecutor<'a, 'b, 'c, EM, FH, H, I, OT, S>
|
||||||
where
|
where
|
||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
/// Called right before exexution starts
|
/// Instruct the target about the input and run
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec<EM, S>(&mut self, state: &mut S, event_mgr: &mut EM, input: &I) -> Result<(), Error>
|
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error> {
|
||||||
where
|
|
||||||
EM: EventManager<I, S>,
|
|
||||||
{
|
|
||||||
if self.helper.stalker_enabled() {
|
if self.helper.stalker_enabled() {
|
||||||
if !self.followed {
|
if !self.followed {
|
||||||
self.followed = true;
|
self.followed = true;
|
||||||
@ -77,15 +76,6 @@ where
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.helper.pre_exec(input);
|
|
||||||
|
|
||||||
self.base.pre_exec(state, event_mgr, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Instruct the target about the input and run
|
|
||||||
#[inline]
|
|
||||||
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error> {
|
|
||||||
let res = self.base.run_target(input);
|
let res = self.base.run_target(input);
|
||||||
if unsafe { ASAN_ERRORS.is_some() && !ASAN_ERRORS.as_ref().unwrap().is_empty() } {
|
if unsafe { ASAN_ERRORS.is_some() && !ASAN_ERRORS.as_ref().unwrap().is_empty() } {
|
||||||
println!("Crashing target as it had ASAN errors");
|
println!("Crashing target as it had ASAN errors");
|
||||||
@ -93,29 +83,38 @@ where
|
|||||||
libc::raise(libc::SIGABRT);
|
libc::raise(libc::SIGABRT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.helper.stalker_enabled() {
|
||||||
|
self.stalker.deactivate();
|
||||||
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'c, EM, FH, H, I, OT, S> HasExecHooks<EM, I, S>
|
||||||
|
for FridaInProcessExecutor<'a, 'b, 'c, EM, FH, H, I, OT, S>
|
||||||
|
where
|
||||||
|
FH: FridaHelper<'b>,
|
||||||
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
|
I: Input + HasTargetBytes,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
/// Called right before exexution starts
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec(&mut self, state: &mut S, event_mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
|
self.helper.pre_exec(input);
|
||||||
|
self.base.pre_exec(state, event_mgr, input)
|
||||||
|
}
|
||||||
|
|
||||||
/// Called right after execution finished.
|
/// Called right after execution finished.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn post_exec<EM, S>(
|
fn post_exec(&mut self, state: &mut S, event_mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
state: &mut S,
|
|
||||||
event_mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
EM: EventManager<I, S>,
|
|
||||||
{
|
|
||||||
if self.helper.stalker_enabled() {
|
|
||||||
self.stalker.deactivate();
|
|
||||||
}
|
|
||||||
self.helper.post_exec(input);
|
self.helper.post_exec(input);
|
||||||
self.base.post_exec(state, event_mgr, input)
|
self.base.post_exec(state, event_mgr, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'c, FH, H, I, OT> HasObservers<OT> for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT>
|
impl<'a, 'b, 'c, EM, FH, H, I, OT, S> HasObservers<OT>
|
||||||
|
for FridaInProcessExecutor<'a, 'b, 'c, EM, FH, H, I, OT, S>
|
||||||
where
|
where
|
||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
@ -133,19 +132,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'c, FH, H, I, OT> Named for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT>
|
impl<'a, 'b, 'c, EM, FH, H, I, OT, S> HasObserversHooks<EM, I, OT, S>
|
||||||
|
for FridaInProcessExecutor<'a, 'b, 'c, EM, FH, H, I, OT, S>
|
||||||
where
|
where
|
||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
{
|
{
|
||||||
fn name(&self) -> &str {
|
|
||||||
self.base.name()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'c, FH, H, I, OT> FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT>
|
impl<'a, 'b, 'c, EM, FH, H, I, OT, S> FridaInProcessExecutor<'a, 'b, 'c, EM, FH, H, I, OT, S>
|
||||||
where
|
where
|
||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
@ -154,7 +151,7 @@ where
|
|||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
gum: &'a Gum,
|
gum: &'a Gum,
|
||||||
base: InProcessExecutor<'a, H, I, OT>,
|
base: InProcessExecutor<'a, EM, H, I, OT, S>,
|
||||||
helper: &'c mut FH,
|
helper: &'c mut FH,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -324,7 +321,6 @@ unsafe fn fuzz(
|
|||||||
let mut executor = FridaInProcessExecutor::new(
|
let mut executor = FridaInProcessExecutor::new(
|
||||||
&gum,
|
&gum,
|
||||||
InProcessExecutor::new(
|
InProcessExecutor::new(
|
||||||
"in-process(edges)",
|
|
||||||
&mut frida_harness,
|
&mut frida_harness,
|
||||||
tuple_list!(edges_observer, AsanErrorsObserver::new(&ASAN_ERRORS)),
|
tuple_list!(edges_observer, AsanErrorsObserver::new(&ASAN_ERRORS)),
|
||||||
&mut state,
|
&mut state,
|
||||||
|
@ -113,7 +113,6 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
|
|
||||||
// Create the executor for an in-process function with observers for edge coverage, value-profile and allocations sizes
|
// Create the executor for an in-process function with observers for edge coverage, value-profile and allocations sizes
|
||||||
let mut executor = InProcessExecutor::new(
|
let mut executor = InProcessExecutor::new(
|
||||||
"in-process(edges,cmp,alloc)",
|
|
||||||
&mut harness,
|
&mut harness,
|
||||||
tuple_list!(edges_observer, cmps_observer, allocs_observer),
|
tuple_list!(edges_observer, cmps_observer, allocs_observer),
|
||||||
&mut state,
|
&mut state,
|
||||||
|
@ -120,7 +120,6 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
|
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
|
||||||
let mut executor = TimeoutExecutor::new(
|
let mut executor = TimeoutExecutor::new(
|
||||||
InProcessExecutor::new(
|
InProcessExecutor::new(
|
||||||
"in-process(edges,time)",
|
|
||||||
&mut harness,
|
&mut harness,
|
||||||
tuple_list!(edges_observer, TimeObserver::new("time")),
|
tuple_list!(edges_observer, TimeObserver::new("time")),
|
||||||
&mut state,
|
&mut state,
|
||||||
|
@ -116,7 +116,6 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
|
|
||||||
// Create the executor for an in-process function with just one observer for edge coverage
|
// Create the executor for an in-process function with just one observer for edge coverage
|
||||||
let mut executor = InProcessExecutor::new(
|
let mut executor = InProcessExecutor::new(
|
||||||
"in-process(edges,time)",
|
|
||||||
&mut harness,
|
&mut harness,
|
||||||
tuple_list!(edges_observer, TimeObserver::new("time")),
|
tuple_list!(edges_observer, TimeObserver::new("time")),
|
||||||
&mut state,
|
&mut state,
|
||||||
|
@ -14,10 +14,11 @@ use crate::bolts::os::unix_signals::setup_signal_handler;
|
|||||||
use crate::bolts::os::windows_exceptions::setup_exception_handler;
|
use crate::bolts::os::windows_exceptions::setup_exception_handler;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::Named,
|
|
||||||
corpus::Corpus,
|
corpus::Corpus,
|
||||||
events::EventManager,
|
events::EventManager,
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{
|
||||||
|
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
|
},
|
||||||
feedbacks::FeedbacksTuple,
|
feedbacks::FeedbacksTuple,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
@ -26,34 +27,41 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// The inmem executor simply calls a target function, then returns afterwards.
|
/// The inmem executor simply calls a target function, then returns afterwards.
|
||||||
pub struct InProcessExecutor<'a, H, I, OT>
|
pub struct InProcessExecutor<'a, EM, H, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
/// The name of this executor instance, to address it from other components
|
|
||||||
name: &'static str,
|
|
||||||
/// The harness function, being executed for each fuzzing loop execution
|
/// The harness function, being executed for each fuzzing loop execution
|
||||||
harness_fn: &'a mut H,
|
harness_fn: &'a mut H,
|
||||||
/// The observers, observing each run
|
/// The observers, observing each run
|
||||||
observers: OT,
|
observers: OT,
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<(EM, I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H, I, OT> Executor<I> for InProcessExecutor<'a, H, I, OT>
|
impl<'a, EM, H, I, OT, S> Executor<I> for InProcessExecutor<'a, EM, H, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec<EM, S>(
|
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error> {
|
||||||
&mut self,
|
let bytes = input.target_bytes();
|
||||||
_state: &mut S,
|
let ret = (self.harness_fn)(bytes.as_slice());
|
||||||
_event_mgr: &mut EM,
|
Ok(ret)
|
||||||
_input: &I,
|
}
|
||||||
) -> Result<(), Error> {
|
}
|
||||||
|
|
||||||
|
impl<'a, EM, H, I, OT, S> HasExecHooks<EM, I, S> for InProcessExecutor<'a, EM, H, I, OT, S>
|
||||||
|
where
|
||||||
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
|
I: Input + HasTargetBytes,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _event_mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = &mut unix_signal_handler::GLOBAL_STATE;
|
let data = &mut unix_signal_handler::GLOBAL_STATE;
|
||||||
@ -92,19 +100,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error> {
|
fn post_exec(&mut self, _state: &mut S, _event_mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
let bytes = input.target_bytes();
|
|
||||||
let ret = (self.harness_fn)(bytes.as_slice());
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn post_exec<EM, S>(
|
|
||||||
&mut self,
|
|
||||||
_state: &mut S,
|
|
||||||
_event_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
unsafe {
|
unsafe {
|
||||||
write_volatile(
|
write_volatile(
|
||||||
@ -125,18 +121,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H, I, OT> Named for InProcessExecutor<'a, H, I, OT>
|
impl<'a, EM, H, I, OT, S> HasObservers<OT> for InProcessExecutor<'a, EM, H, I, OT, S>
|
||||||
where
|
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
|
||||||
I: Input + HasTargetBytes,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
self.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, H, I, OT> HasObservers<OT> for InProcessExecutor<'a, H, I, OT>
|
|
||||||
where
|
where
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
@ -153,7 +138,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H, I, OT> InProcessExecutor<'a, H, I, OT>
|
impl<'a, EM, H, I, OT, S> HasObserversHooks<EM, I, OT, S> for InProcessExecutor<'a, EM, H, I, OT, S>
|
||||||
|
where
|
||||||
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
|
I: Input + HasTargetBytes,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, EM, H, I, OT, S> InProcessExecutor<'a, EM, H, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&[u8]) -> ExitKind,
|
H: FnMut(&[u8]) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
@ -162,12 +155,10 @@ where
|
|||||||
/// Create a new in mem executor.
|
/// Create a new in mem executor.
|
||||||
/// Caution: crash and restart in one of them will lead to odd behavior if multiple are used,
|
/// Caution: crash and restart in one of them will lead to odd behavior if multiple are used,
|
||||||
/// depending on different corpus or state.
|
/// depending on different corpus or state.
|
||||||
/// * `name` - the name of this executor (to address it along the way)
|
|
||||||
/// * `harness_fn` - the harness, executiong the function
|
/// * `harness_fn` - the harness, executiong the function
|
||||||
/// * `observers` - the observers observing the target during execution
|
/// * `observers` - the observers observing the target during execution
|
||||||
/// This may return an error on unix, if signal handler setup fails
|
/// This may return an error on unix, if signal handler setup fails
|
||||||
pub fn new<EM, OC, OFT, S>(
|
pub fn new<OC, OFT>(
|
||||||
name: &'static str,
|
|
||||||
harness_fn: &'a mut H,
|
harness_fn: &'a mut H,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
@ -213,7 +204,6 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
harness_fn,
|
harness_fn,
|
||||||
observers,
|
observers,
|
||||||
name,
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -696,10 +686,9 @@ mod tests {
|
|||||||
fn test_inmem_exec() {
|
fn test_inmem_exec() {
|
||||||
let mut harness = |_buf: &[u8]| ExitKind::Ok;
|
let mut harness = |_buf: &[u8]| ExitKind::Ok;
|
||||||
|
|
||||||
let mut in_process_executor = InProcessExecutor::<_, NopInput, ()> {
|
let mut in_process_executor = InProcessExecutor::<(), _, NopInput, (), ()> {
|
||||||
harness_fn: &mut harness,
|
harness_fn: &mut harness,
|
||||||
observers: tuple_list!(),
|
observers: tuple_list!(),
|
||||||
name: "main",
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
};
|
};
|
||||||
let mut input = NopInput {};
|
let mut input = NopInput {};
|
||||||
|
@ -8,8 +8,7 @@ pub use timeout::TimeoutExecutor;
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::{serdeany::SerdeAny, tuples::Named},
|
bolts::serdeany::SerdeAny,
|
||||||
events::EventManager,
|
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
Error,
|
Error,
|
||||||
@ -29,6 +28,57 @@ pub enum ExitKind {
|
|||||||
Custom(Box<dyn CustomExitKind>),
|
Custom(Box<dyn CustomExitKind>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pre and post exec hooks
|
||||||
|
pub trait HasExecHooks<EM, I, S> {
|
||||||
|
/// Called right before exexution starts
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Called right after execution finished.
|
||||||
|
#[inline]
|
||||||
|
fn post_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A haskell-style tuple of objects that have pre and post exec hooks
|
||||||
|
pub trait HasExecHooksTuple<EM, I, S> {
|
||||||
|
/// This is called right before the next execution.
|
||||||
|
fn pre_exec_all(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// This is called right after the last execution
|
||||||
|
fn post_exec_all(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<EM, I, S> HasExecHooksTuple<EM, I, S> for () {
|
||||||
|
fn pre_exec_all(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_exec_all(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<EM, I, S, Head, Tail> HasExecHooksTuple<EM, I, S> for (Head, Tail)
|
||||||
|
where
|
||||||
|
Head: HasExecHooks<EM, I, S>,
|
||||||
|
Tail: HasExecHooksTuple<EM, I, S>,
|
||||||
|
{
|
||||||
|
fn pre_exec_all(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
|
self.0.pre_exec(state, mgr, input)?;
|
||||||
|
self.1.pre_exec_all(state, mgr, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_exec_all(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
|
self.0.post_exec(state, mgr, input)?;
|
||||||
|
self.1.post_exec_all(state, mgr, input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Holds a tuple of Observers
|
||||||
pub trait HasObservers<OT>
|
pub trait HasObservers<OT>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
@ -38,27 +88,41 @@ where
|
|||||||
|
|
||||||
/// Get the linked observers
|
/// Get the linked observers
|
||||||
fn observers_mut(&mut self) -> &mut OT;
|
fn observers_mut(&mut self) -> &mut OT;
|
||||||
|
}
|
||||||
|
|
||||||
/// Reset the state of all the observes linked to this executor
|
/// Execute the exec hooks of the observers if they all implement HasExecHooks
|
||||||
|
pub trait HasObserversHooks<EM, I, OT, S>: HasObservers<OT>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec_observers(&mut self) -> Result<(), Error> {
|
fn pre_exec_observers(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
self.observers_mut().pre_exec_all()
|
self.observers_mut().pre_exec_all(state, mgr, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the post exec hook for all the observes linked to this executor
|
/// Run the post exec hook for all the observes linked to this executor
|
||||||
#[inline]
|
#[inline]
|
||||||
fn post_exec_observers(&mut self) -> Result<(), Error> {
|
fn post_exec_observers(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
self.observers_mut().post_exec_all()
|
self.observers_mut().post_exec_all(state, mgr, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An executor takes the given inputs, and runs the harness/target.
|
||||||
|
pub trait Executor<I>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
/// Instruct the target about the input and run
|
||||||
|
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
/// A simple executor that does nothing.
|
/// A simple executor that does nothing.
|
||||||
/// If intput len is 0, `run_target` will return Err
|
/// If intput len is 0, `run_target` will return Err
|
||||||
struct NopExecutor<I> {
|
struct NopExecutor<EM, I, S> {
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<(EM, I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> Executor<I> for NopExecutor<I>
|
impl<EM, I, S> Executor<I> for NopExecutor<EM, I, S>
|
||||||
where
|
where
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
{
|
{
|
||||||
@ -71,48 +135,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> Named for NopExecutor<I> {
|
impl<EM, I, S> HasExecHooks<EM, I, S> for NopExecutor<EM, I, S> where I: Input + HasTargetBytes {}
|
||||||
fn name(&self) -> &str {
|
|
||||||
&"NopExecutor"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An executor takes the given inputs, and runs the harness/target.
|
|
||||||
pub trait Executor<I>: Named
|
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
{
|
|
||||||
/// Called right before exexution starts
|
|
||||||
#[inline]
|
|
||||||
fn pre_exec<EM, S>(
|
|
||||||
&mut self,
|
|
||||||
_state: &mut S,
|
|
||||||
_event_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
EM: EventManager<I, S>,
|
|
||||||
{
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called right after execution finished.
|
|
||||||
#[inline]
|
|
||||||
fn post_exec<EM, S>(
|
|
||||||
&mut self,
|
|
||||||
_state: &mut S,
|
|
||||||
_event_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
EM: EventManager<I, S>,
|
|
||||||
{
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Instruct the target about the input and run
|
|
||||||
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
@ -125,7 +148,7 @@ mod test {
|
|||||||
fn nop_executor() {
|
fn nop_executor() {
|
||||||
let empty_input = BytesInput::new(vec![]);
|
let empty_input = BytesInput::new(vec![]);
|
||||||
let nonempty_input = BytesInput::new(vec![1u8]);
|
let nonempty_input = BytesInput::new(vec![1u8]);
|
||||||
let mut executor = NopExecutor {
|
let mut executor = NopExecutor::<(), _, ()> {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
};
|
};
|
||||||
assert!(executor.run_target(&empty_input).is_err());
|
assert!(executor.run_target(&empty_input).is_err());
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
use core::{marker::PhantomData, time::Duration};
|
use core::{marker::PhantomData, time::Duration};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::Named,
|
executors::{
|
||||||
events::EventManager,
|
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
},
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
@ -39,50 +39,20 @@ extern "C" {
|
|||||||
const ITIMER_REAL: c_int = 0;
|
const ITIMER_REAL: c_int = 0;
|
||||||
|
|
||||||
/// The timeout excutor is a wrapper that set a timeout before each run
|
/// The timeout excutor is a wrapper that set a timeout before each run
|
||||||
pub struct TimeoutExecutor<E, I, OT>
|
pub struct TimeoutExecutor<E, I>
|
||||||
where
|
where
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I>,
|
||||||
I: Input + HasTargetBytes,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
{
|
||||||
executor: E,
|
executor: E,
|
||||||
exec_tmout: Duration,
|
exec_tmout: Duration,
|
||||||
phantom: PhantomData<(I, OT)>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, I, OT> Named for TimeoutExecutor<E, I, OT>
|
impl<E, I> TimeoutExecutor<E, I>
|
||||||
where
|
where
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I>,
|
||||||
I: Input + HasTargetBytes,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
self.executor.name()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E, I, OT> HasObservers<OT> for TimeoutExecutor<E, I, OT>
|
|
||||||
where
|
|
||||||
E: Executor<I> + HasObservers<OT>,
|
|
||||||
I: Input + HasTargetBytes,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn observers(&self) -> &OT {
|
|
||||||
self.executor.observers()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
|
||||||
self.executor.observers_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E, I, OT> TimeoutExecutor<E, I, OT>
|
|
||||||
where
|
|
||||||
E: Executor<I> + HasObservers<OT>,
|
|
||||||
I: Input + HasTargetBytes,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
{
|
||||||
pub fn new(executor: E, exec_tmout: Duration) -> Self {
|
pub fn new(executor: E, exec_tmout: Duration) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -97,19 +67,48 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, I, OT> Executor<I> for TimeoutExecutor<E, I, OT>
|
impl<E, I> Executor<I> for TimeoutExecutor<E, I>
|
||||||
|
where
|
||||||
|
E: Executor<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error> {
|
||||||
|
self.executor.run_target(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, I, OT> HasObservers<OT> for TimeoutExecutor<E, I>
|
||||||
where
|
where
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT>,
|
||||||
I: Input + HasTargetBytes,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec<EM: EventManager<I, S>, S>(
|
fn observers(&self) -> &OT {
|
||||||
&mut self,
|
self.executor.observers()
|
||||||
_state: &mut S,
|
}
|
||||||
_event_mgr: &mut EM,
|
|
||||||
_input: &I,
|
#[inline]
|
||||||
) -> Result<(), Error> {
|
fn observers_mut(&mut self) -> &mut OT {
|
||||||
|
self.executor.observers_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, EM, I, OT, S> HasObserversHooks<EM, I, OT, S> for TimeoutExecutor<E, I>
|
||||||
|
where
|
||||||
|
E: Executor<I> + HasObservers<OT>,
|
||||||
|
I: Input,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, EM, I, S> HasExecHooks<EM, I, S> for TimeoutExecutor<E, I>
|
||||||
|
where
|
||||||
|
E: Executor<I> + HasExecHooks<EM, I, S>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
unsafe {
|
unsafe {
|
||||||
let milli_sec = self.exec_tmout.as_millis();
|
let milli_sec = self.exec_tmout.as_millis();
|
||||||
@ -135,16 +134,11 @@ where
|
|||||||
// TODO
|
// TODO
|
||||||
let _ = self.exec_tmout.as_millis();
|
let _ = self.exec_tmout.as_millis();
|
||||||
}
|
}
|
||||||
self.executor.pre_exec(_state, _event_mgr, _input)
|
self.executor.pre_exec(state, mgr, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn post_exec<EM: EventManager<I, S>, S>(
|
fn post_exec(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_state: &mut S,
|
|
||||||
_event_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
unsafe {
|
unsafe {
|
||||||
let it_value = Timeval {
|
let it_value = Timeval {
|
||||||
@ -168,10 +162,6 @@ where
|
|||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
self.executor.post_exec(_state, _event_mgr, _input)
|
self.executor.post_exec(state, mgr, input)
|
||||||
}
|
|
||||||
|
|
||||||
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error> {
|
|
||||||
self.executor.run_target(input)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,14 @@ use crate::{
|
|||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::Feedback,
|
feedbacks::Feedback,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::{MapObserver, Observer, ObserversTuple},
|
observers::{MapObserver, ObserversTuple},
|
||||||
state::HasMetadata,
|
state::HasMetadata,
|
||||||
utils::AsSlice,
|
utils::AsSlice,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type MaxMapFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
|
pub type MaxMapFeedback<O, T> = MapFeedback<O, MaxReducer, T>;
|
||||||
pub type MinMapFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
|
pub type MinMapFeedback<O, T> = MapFeedback<O, MinReducer, T>;
|
||||||
|
|
||||||
/// A Reducer function is used to aggregate values for the novelty search
|
/// A Reducer function is used to aggregate values for the novelty search
|
||||||
pub trait Reducer<T>: Serialize + serde::de::DeserializeOwned + 'static
|
pub trait Reducer<T>: Serialize + serde::de::DeserializeOwned + 'static
|
||||||
@ -32,14 +32,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct MaxReducer<T>
|
pub struct MaxReducer {}
|
||||||
where
|
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
|
||||||
{
|
|
||||||
phantom: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Reducer<T> for MaxReducer<T>
|
impl<T> Reducer<T> for MaxReducer
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
@ -54,14 +49,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct MinReducer<T>
|
pub struct MinReducer {}
|
||||||
where
|
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
|
||||||
{
|
|
||||||
phantom: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Reducer<T> for MinReducer<T>
|
impl<T> Reducer<T> for MinReducer
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
@ -119,7 +109,7 @@ impl MapNoveltiesMetadata {
|
|||||||
/// The most common AFL-like feedback type
|
/// The most common AFL-like feedback type
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||||
pub struct MapFeedback<T, R, O>
|
pub struct MapFeedback<O, R, T>
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
@ -137,25 +127,22 @@ where
|
|||||||
phantom: PhantomData<(R, O)>,
|
phantom: PhantomData<(R, O)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, R, O, I> Feedback<I> for MapFeedback<T, R, O>
|
impl<O, R, T, I> Feedback<I> for MapFeedback<O, R, T>
|
||||||
where
|
where
|
||||||
T: Integer
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
+ Default
|
|
||||||
+ Copy
|
|
||||||
+ 'static
|
|
||||||
+ serde::Serialize
|
|
||||||
+ serde::de::DeserializeOwned
|
|
||||||
+ core::fmt::Debug,
|
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
O: MapObserver<T>,
|
O: MapObserver<T>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT: ObserversTuple>(
|
fn is_interesting<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error> {
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
let mut interesting = 0;
|
let mut interesting = 0;
|
||||||
// TODO optimize
|
// TODO optimize
|
||||||
let observer = observers.match_name_type::<O>(&self.name).unwrap();
|
let observer = observers.match_name_type::<O>(&self.name).unwrap();
|
||||||
@ -243,7 +230,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, R, O> Named for MapFeedback<T, R, O>
|
impl<O, R, T> Named for MapFeedback<O, R, T>
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
@ -255,11 +242,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, R, O> MapFeedback<T, R, O>
|
impl<O, R, T> MapFeedback<O, R, T>
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
O: MapObserver<T> + Observer,
|
O: MapObserver<T>,
|
||||||
{
|
{
|
||||||
/// Create new `MapFeedback`
|
/// Create new `MapFeedback`
|
||||||
pub fn new(name: &'static str, map_size: usize) -> Self {
|
pub fn new(name: &'static str, map_size: usize) -> Self {
|
||||||
@ -315,7 +302,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, R, O> MapFeedback<T, R, O>
|
impl<O, R, T> MapFeedback<O, R, T>
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
|
@ -25,12 +25,14 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// `is_interesting ` should return the "Interestingness" from 0 to 255 (percent times 2.55)
|
/// `is_interesting ` should return the "Interestingness" from 0 to 255 (percent times 2.55)
|
||||||
fn is_interesting<OT: ObserversTuple>(
|
fn is_interesting<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>;
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple;
|
||||||
|
|
||||||
/// 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]
|
||||||
@ -50,12 +52,14 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// Get the total interestingness value from all feedbacks
|
/// Get the total interestingness value from all feedbacks
|
||||||
fn is_interesting_all<OT: ObserversTuple>(
|
fn is_interesting_all<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>;
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple;
|
||||||
|
|
||||||
/// Write metadata for this testcase
|
/// Write metadata for this testcase
|
||||||
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), Error>;
|
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), Error>;
|
||||||
@ -69,12 +73,10 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_interesting_all<OT: ObserversTuple>(
|
fn is_interesting_all<OT>(&mut self, _: &I, _: &OT, _: &ExitKind) -> Result<u32, Error>
|
||||||
&mut self,
|
where
|
||||||
_: &I,
|
OT: ObserversTuple,
|
||||||
_: &OT,
|
{
|
||||||
_: &ExitKind,
|
|
||||||
) -> Result<u32, Error> {
|
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,12 +97,15 @@ where
|
|||||||
Tail: FeedbacksTuple<I>,
|
Tail: FeedbacksTuple<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting_all<OT: ObserversTuple>(
|
fn is_interesting_all<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error> {
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
Ok(self.0.is_interesting(input, observers, exit_kind)?
|
Ok(self.0.is_interesting(input, observers, exit_kind)?
|
||||||
+ self.1.is_interesting_all(input, observers, exit_kind)?)
|
+ self.1.is_interesting_all(input, observers, exit_kind)?)
|
||||||
}
|
}
|
||||||
@ -124,12 +129,15 @@ impl<I> Feedback<I> for CrashFeedback
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT: ObserversTuple>(
|
fn is_interesting<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
_observers: &OT,
|
_observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error> {
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
if let ExitKind::Crash = exit_kind {
|
if let ExitKind::Crash = exit_kind {
|
||||||
Ok(1)
|
Ok(1)
|
||||||
} else {
|
} else {
|
||||||
@ -164,12 +172,15 @@ impl<I> Feedback<I> for TimeoutFeedback
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT: ObserversTuple>(
|
fn is_interesting<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
_observers: &OT,
|
_observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error> {
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
if let ExitKind::Timeout = exit_kind {
|
if let ExitKind::Timeout = exit_kind {
|
||||||
Ok(1)
|
Ok(1)
|
||||||
} else {
|
} else {
|
||||||
@ -207,12 +218,15 @@ impl<I> Feedback<I> for TimeFeedback
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT: ObserversTuple>(
|
fn is_interesting<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error> {
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
let observer = observers.match_first_type::<TimeObserver>().unwrap();
|
let observer = observers.match_first_type::<TimeObserver>().unwrap();
|
||||||
self.exec_time = *observer.last_runtime();
|
self.exec_time = *observer.last_runtime();
|
||||||
Ok(0)
|
Ok(0)
|
||||||
|
@ -194,7 +194,6 @@ mod tests {
|
|||||||
|
|
||||||
let mut harness = |_buf: &[u8]| ExitKind::Ok;
|
let mut harness = |_buf: &[u8]| ExitKind::Ok;
|
||||||
let mut executor = InProcessExecutor::new(
|
let mut executor = InProcessExecutor::new(
|
||||||
"main",
|
|
||||||
&mut harness,
|
&mut harness,
|
||||||
tuple_list!(),
|
tuple_list!(),
|
||||||
//Box::new(|_, _, _, _, _| ()),
|
//Box::new(|_, _, _, _, _| ()),
|
||||||
|
@ -11,6 +11,7 @@ use crate::{
|
|||||||
ownedref::{OwnedArrayPtrMut, OwnedPtr},
|
ownedref::{OwnedArrayPtrMut, OwnedPtr},
|
||||||
tuples::Named,
|
tuples::Named,
|
||||||
},
|
},
|
||||||
|
executors::HasExecHooks,
|
||||||
observers::Observer,
|
observers::Observer,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
@ -68,12 +69,18 @@ where
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Observer for StdMapObserver<T>
|
impl<T> Observer for StdMapObserver<T> where
|
||||||
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<EM, I, S, T> HasExecHooks<EM, I, S> for StdMapObserver<T>
|
||||||
where
|
where
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
|
Self: MapObserver<T>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(&mut self) -> Result<(), Error> {
|
fn pre_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
self.reset_map()
|
self.reset_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,12 +177,17 @@ where
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Observer for VariableMapObserver<T>
|
impl<T> Observer for VariableMapObserver<T> where
|
||||||
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<EM, I, S, T> HasExecHooks<EM, I, S> for VariableMapObserver<T>
|
||||||
where
|
where
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(&mut self) -> Result<(), Error> {
|
fn pre_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
self.reset_map()
|
self.reset_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,7 +276,7 @@ where
|
|||||||
#[serde(bound = "M: serde::de::DeserializeOwned")]
|
#[serde(bound = "M: serde::de::DeserializeOwned")]
|
||||||
pub struct HitcountsMapObserver<M>
|
pub struct HitcountsMapObserver<M>
|
||||||
where
|
where
|
||||||
M: MapObserver<u8>,
|
M: serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
base: M,
|
base: M,
|
||||||
}
|
}
|
||||||
@ -284,27 +296,29 @@ static COUNT_CLASS_LOOKUP: [u8; 256] = [
|
|||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl<M> Observer for HitcountsMapObserver<M>
|
impl<M> Observer for HitcountsMapObserver<M> where M: MapObserver<u8> {}
|
||||||
|
|
||||||
|
impl<EM, I, S, M> HasExecHooks<EM, I, S> for HitcountsMapObserver<M>
|
||||||
where
|
where
|
||||||
M: MapObserver<u8>,
|
M: MapObserver<u8> + HasExecHooks<EM, I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(&mut self) -> Result<(), Error> {
|
fn pre_exec(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
self.reset_map()
|
self.base.pre_exec(state, mgr, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn post_exec(&mut self) -> Result<(), Error> {
|
fn post_exec(&mut self, state: &mut S, mgr: &mut EM, input: &I) -> Result<(), Error> {
|
||||||
for x in self.map_mut().iter_mut() {
|
for x in self.map_mut().iter_mut() {
|
||||||
*x = COUNT_CLASS_LOOKUP[*x as usize];
|
*x = COUNT_CLASS_LOOKUP[*x as usize];
|
||||||
}
|
}
|
||||||
Ok(())
|
self.base.post_exec(state, mgr, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M> Named for HitcountsMapObserver<M>
|
impl<M> Named for HitcountsMapObserver<M>
|
||||||
where
|
where
|
||||||
M: MapObserver<u8>,
|
M: Named + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
@ -349,7 +363,7 @@ where
|
|||||||
|
|
||||||
impl<M> HitcountsMapObserver<M>
|
impl<M> HitcountsMapObserver<M>
|
||||||
where
|
where
|
||||||
M: MapObserver<u8>,
|
M: serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
/// Creates a new MapObserver
|
/// Creates a new MapObserver
|
||||||
pub fn new(base: M) -> Self {
|
pub fn new(base: M) -> Self {
|
||||||
|
@ -3,15 +3,13 @@
|
|||||||
pub mod map;
|
pub mod map;
|
||||||
pub use map::*;
|
pub use map::*;
|
||||||
|
|
||||||
use alloc::{
|
use alloc::string::{String, ToString};
|
||||||
string::{String, ToString},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::{MatchFirstType, MatchNameAndType, MatchType, Named},
|
bolts::tuples::{MatchFirstType, MatchNameAndType, MatchType, Named},
|
||||||
|
executors::HasExecHooks,
|
||||||
utils::current_time,
|
utils::current_time,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
@ -20,74 +18,26 @@ use crate::{
|
|||||||
/// They can then be used by various sorts of feedback.
|
/// They can then be used by various sorts of feedback.
|
||||||
pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned + 'static {
|
pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned + 'static {
|
||||||
/// The testcase finished execution, calculate any changes.
|
/// The testcase finished execution, calculate any changes.
|
||||||
|
/// Reserved for future use.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn flush(&mut self) -> Result<(), Error> {
|
fn flush(&mut self) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets the observer
|
|
||||||
fn pre_exec(&mut self) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// This function is executed after each fuzz run
|
|
||||||
#[inline]
|
|
||||||
fn post_exec(&mut self) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize this observer's state only, to be restored later using deserialize_state
|
|
||||||
/// As opposed to completely serializing the observer, this is only needed when the fuzzer is to be restarted
|
|
||||||
/// If no state is needed to be kept, just return an empty vec.
|
|
||||||
/// Example:
|
|
||||||
/// >> The virgin_bits map in AFL needs to be in sync with the corpus
|
|
||||||
#[inline]
|
|
||||||
fn serialize_state(&mut self) -> Result<Vec<u8>, Error> {
|
|
||||||
Ok(vec![])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Restore the state from a given vec, priviously stored using `serialize_state`
|
|
||||||
#[inline]
|
|
||||||
fn deserialize_state(&mut self, serialized_state: &[u8]) -> Result<(), Error> {
|
|
||||||
let _ = serialized_state;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A hastkel-style tuple of observers
|
/// A haskell-style tuple of observers
|
||||||
pub trait ObserversTuple:
|
pub trait ObserversTuple:
|
||||||
MatchNameAndType + MatchType + MatchFirstType + serde::Serialize + serde::de::DeserializeOwned
|
MatchNameAndType + MatchType + MatchFirstType + serde::Serialize + serde::de::DeserializeOwned
|
||||||
{
|
{
|
||||||
/// Reset all executors in the tuple
|
|
||||||
/// This is called right before the next execution.
|
|
||||||
fn pre_exec_all(&mut self) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Do whatever you need to do after a run.
|
|
||||||
/// This is called right after the last execution
|
|
||||||
fn post_exec_all(&mut self) -> Result<(), Error>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObserversTuple for () {
|
impl ObserversTuple for () {}
|
||||||
fn pre_exec_all(&mut self) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn post_exec_all(&mut self) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Head, Tail> ObserversTuple for (Head, Tail)
|
impl<Head, Tail> ObserversTuple for (Head, Tail)
|
||||||
where
|
where
|
||||||
Head: Observer,
|
Head: Observer,
|
||||||
Tail: ObserversTuple,
|
Tail: ObserversTuple,
|
||||||
{
|
{
|
||||||
fn pre_exec_all(&mut self) -> Result<(), Error> {
|
|
||||||
self.0.pre_exec()?;
|
|
||||||
self.1.pre_exec_all()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn post_exec_all(&mut self) -> Result<(), Error> {
|
|
||||||
self.0.post_exec()?;
|
|
||||||
self.1.post_exec_all()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple observer, just overlooking the runtime of the target.
|
/// A simple observer, just overlooking the runtime of the target.
|
||||||
@ -113,14 +63,16 @@ impl TimeObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Observer for TimeObserver {
|
impl Observer for TimeObserver {}
|
||||||
fn pre_exec(&mut self) -> Result<(), Error> {
|
|
||||||
|
impl<EM, I, S> HasExecHooks<EM, I, S> for TimeObserver {
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
self.last_runtime = None;
|
self.last_runtime = None;
|
||||||
self.start_time = current_time();
|
self.start_time = current_time();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_exec(&mut self) -> Result<(), Error> {
|
fn post_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
self.last_runtime = Some(current_time() - self.start_time);
|
self.last_runtime = Some(current_time() - self.start_time);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use core::marker::PhantomData;
|
|||||||
use crate::{
|
use crate::{
|
||||||
corpus::{Corpus, CorpusScheduler},
|
corpus::{Corpus, CorpusScheduler},
|
||||||
events::EventManager,
|
events::EventManager,
|
||||||
executors::{Executor, HasObservers},
|
executors::{Executor, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
mutators::Mutator,
|
mutators::Mutator,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
@ -25,8 +25,8 @@ where
|
|||||||
S: HasCorpus<C, I> + Evaluator<I>,
|
S: HasCorpus<C, I> + Evaluator<I>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT> + HasExecHooks<EM, I, S> + HasObserversHooks<EM, I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
{
|
{
|
||||||
/// The mutator registered for this stage
|
/// The mutator registered for this stage
|
||||||
@ -76,8 +76,8 @@ where
|
|||||||
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT> + HasExecHooks<EM, I, S> + HasObserversHooks<EM, I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
@ -94,8 +94,8 @@ where
|
|||||||
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT> + HasExecHooks<EM, I, S> + HasObserversHooks<EM, I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
@ -125,8 +125,8 @@ where
|
|||||||
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT> + HasExecHooks<EM, I, S> + HasObserversHooks<EM, I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
@ -150,8 +150,8 @@ where
|
|||||||
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
S: HasCorpus<C, I> + Evaluator<I> + HasRand<R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT> + HasExecHooks<EM, I, S> + HasObserversHooks<EM, I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S>,
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,9 @@ use crate::{
|
|||||||
bolts::serdeany::{SerdeAny, SerdeAnyMap},
|
bolts::serdeany::{SerdeAny, SerdeAnyMap},
|
||||||
corpus::{Corpus, CorpusScheduler, Testcase},
|
corpus::{Corpus, CorpusScheduler, Testcase},
|
||||||
events::{Event, EventManager, LogSeverity},
|
events::{Event, EventManager, LogSeverity},
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{
|
||||||
|
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
|
},
|
||||||
feedbacks::FeedbacksTuple,
|
feedbacks::FeedbacksTuple,
|
||||||
generators::Generator,
|
generators::Generator,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
@ -97,7 +99,7 @@ pub trait HasMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for elements offering a feedbacks tuple
|
/// Trait for elements offering a feedbacks tuple
|
||||||
pub trait HasFeedbacks<FT, I>
|
pub trait HasFeedbacks<FT, I>: Sized
|
||||||
where
|
where
|
||||||
FT: FeedbacksTuple<I>,
|
FT: FeedbacksTuple<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
@ -107,29 +109,10 @@ where
|
|||||||
|
|
||||||
/// The feedbacks tuple (mut)
|
/// The feedbacks tuple (mut)
|
||||||
fn feedbacks_mut(&mut self) -> &mut FT;
|
fn feedbacks_mut(&mut self) -> &mut FT;
|
||||||
|
|
||||||
/// Resets all metadata holds by feedbacks
|
|
||||||
#[inline]
|
|
||||||
fn discard_feedbacks_metadata(&mut self, input: &I) -> Result<(), Error> {
|
|
||||||
// TODO: This could probably be automatic in the feedback somehow?
|
|
||||||
self.feedbacks_mut().discard_metadata_all(&input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new testcase, appending the metadata from each feedback
|
|
||||||
#[inline]
|
|
||||||
fn testcase_with_feedbacks_metadata(
|
|
||||||
&mut self,
|
|
||||||
input: I,
|
|
||||||
fitness: u32,
|
|
||||||
) -> Result<Testcase<I>, Error> {
|
|
||||||
let mut testcase = Testcase::with_fitness(input, fitness);
|
|
||||||
self.feedbacks_mut().append_metadata_all(&mut testcase)?;
|
|
||||||
Ok(testcase)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for elements offering an objective feedbacks tuple
|
/// Trait for elements offering an objective feedbacks tuple
|
||||||
pub trait HasObjectives<FT, I>
|
pub trait HasObjectives<FT, I>: Sized
|
||||||
where
|
where
|
||||||
FT: FeedbacksTuple<I>,
|
FT: FeedbacksTuple<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
@ -160,7 +143,7 @@ pub trait HasStartTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add to the state if interesting
|
/// Add to the state if interesting
|
||||||
pub trait IfInteresting<I>
|
pub trait IfInteresting<I>: Sized
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
@ -200,8 +183,11 @@ where
|
|||||||
scheduler: &CS,
|
scheduler: &CS,
|
||||||
) -> Result<(u32, Option<usize>), Error>
|
) -> Result<(u32, Option<usize>), Error>
|
||||||
where
|
where
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I>
|
||||||
OT: ObserversTuple,
|
+ HasObservers<OT>
|
||||||
|
+ HasExecHooks<EM, I, Self>
|
||||||
|
+ HasObserversHooks<EM, I, OT, Self>,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, Self>,
|
||||||
EM: EventManager<I, Self>,
|
EM: EventManager<I, Self>,
|
||||||
CS: CorpusScheduler<I, Self>;
|
CS: CorpusScheduler<I, Self>;
|
||||||
}
|
}
|
||||||
@ -469,12 +455,13 @@ where
|
|||||||
CS: CorpusScheduler<I, Self>,
|
CS: CorpusScheduler<I, Self>,
|
||||||
{
|
{
|
||||||
if fitness > 0 {
|
if fitness > 0 {
|
||||||
let testcase = self.testcase_with_feedbacks_metadata(input.clone(), fitness)?;
|
let mut testcase = Testcase::with_fitness(input.clone(), fitness);
|
||||||
|
self.feedbacks_mut().append_metadata_all(&mut testcase)?;
|
||||||
let idx = self.corpus.add(testcase)?;
|
let idx = self.corpus.add(testcase)?;
|
||||||
scheduler.on_add(self, idx)?;
|
scheduler.on_add(self, idx)?;
|
||||||
Ok(Some(idx))
|
Ok(Some(idx))
|
||||||
} else {
|
} else {
|
||||||
self.discard_feedbacks_metadata(input)?;
|
self.feedbacks_mut().discard_metadata_all(&input)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -500,8 +487,11 @@ where
|
|||||||
scheduler: &CS,
|
scheduler: &CS,
|
||||||
) -> Result<(u32, Option<usize>), Error>
|
) -> Result<(u32, Option<usize>), Error>
|
||||||
where
|
where
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I>
|
||||||
OT: ObserversTuple,
|
+ HasObservers<OT>
|
||||||
|
+ HasExecHooks<EM, I, Self>
|
||||||
|
+ HasObserversHooks<EM, I, OT, Self>,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, Self>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
EM: EventManager<I, Self>,
|
EM: EventManager<I, Self>,
|
||||||
CS: CorpusScheduler<I, Self>,
|
CS: CorpusScheduler<I, Self>,
|
||||||
@ -555,8 +545,11 @@ where
|
|||||||
in_dir: &Path,
|
in_dir: &Path,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
E: Executor<BytesInput> + HasObservers<OT>,
|
E: Executor<BytesInput>
|
||||||
OT: ObserversTuple,
|
+ HasObservers<OT>
|
||||||
|
+ HasExecHooks<EM, BytesInput, Self>
|
||||||
|
+ HasObserversHooks<EM, BytesInput, OT, Self>,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, BytesInput, Self>,
|
||||||
EM: EventManager<BytesInput, Self>,
|
EM: EventManager<BytesInput, Self>,
|
||||||
CS: CorpusScheduler<BytesInput, Self>,
|
CS: CorpusScheduler<BytesInput, Self>,
|
||||||
{
|
{
|
||||||
@ -601,8 +594,11 @@ where
|
|||||||
in_dirs: &[PathBuf],
|
in_dirs: &[PathBuf],
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
E: Executor<BytesInput> + HasObservers<OT>,
|
E: Executor<BytesInput>
|
||||||
OT: ObserversTuple,
|
+ HasObservers<OT>
|
||||||
|
+ HasExecHooks<EM, BytesInput, Self>
|
||||||
|
+ HasObserversHooks<EM, BytesInput, OT, Self>,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, BytesInput, Self>,
|
||||||
EM: EventManager<BytesInput, Self>,
|
EM: EventManager<BytesInput, Self>,
|
||||||
CS: CorpusScheduler<BytesInput, Self>,
|
CS: CorpusScheduler<BytesInput, Self>,
|
||||||
{
|
{
|
||||||
@ -639,19 +635,22 @@ where
|
|||||||
event_mgr: &mut EM,
|
event_mgr: &mut EM,
|
||||||
) -> Result<(u32, bool), Error>
|
) -> Result<(u32, bool), Error>
|
||||||
where
|
where
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I>
|
||||||
OT: ObserversTuple,
|
+ HasObservers<OT>
|
||||||
|
+ HasExecHooks<EM, I, Self>
|
||||||
|
+ HasObserversHooks<EM, I, OT, Self>,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, Self>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
EM: EventManager<I, Self>,
|
EM: EventManager<I, Self>,
|
||||||
{
|
{
|
||||||
executor.pre_exec_observers()?;
|
executor.pre_exec_observers(self, event_mgr, input)?;
|
||||||
|
|
||||||
executor.pre_exec(self, event_mgr, input)?;
|
executor.pre_exec(self, event_mgr, input)?;
|
||||||
let exit_kind = executor.run_target(input)?;
|
let exit_kind = executor.run_target(input)?;
|
||||||
executor.post_exec(self, event_mgr, input)?;
|
executor.post_exec(self, event_mgr, input)?;
|
||||||
|
|
||||||
*self.executions_mut() += 1;
|
*self.executions_mut() += 1;
|
||||||
executor.post_exec_observers()?;
|
executor.post_exec_observers(self, event_mgr, input)?;
|
||||||
|
|
||||||
let observers = executor.observers();
|
let observers = executor.observers();
|
||||||
let fitness = self
|
let fitness = self
|
||||||
@ -676,8 +675,11 @@ where
|
|||||||
where
|
where
|
||||||
G: Generator<I, R>,
|
G: Generator<I, R>,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I>
|
||||||
OT: ObserversTuple,
|
+ HasObservers<OT>
|
||||||
|
+ HasExecHooks<EM, I, Self>
|
||||||
|
+ HasObserversHooks<EM, I, OT, Self>,
|
||||||
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, Self>,
|
||||||
EM: EventManager<I, Self>,
|
EM: EventManager<I, Self>,
|
||||||
CS: CorpusScheduler<I, Self>,
|
CS: CorpusScheduler<I, Self>,
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@ use hashbrown::HashMap;
|
|||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{ownedref::OwnedPtr, tuples::Named},
|
bolts::{ownedref::OwnedPtr, tuples::Named},
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
executors::{CustomExitKind, ExitKind},
|
executors::{CustomExitKind, ExitKind, HasExecHooks},
|
||||||
feedbacks::Feedback,
|
feedbacks::Feedback,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::{Observer, ObserversTuple},
|
observers::{Observer, ObserversTuple},
|
||||||
@ -1625,8 +1625,10 @@ pub struct AsanErrorsObserver {
|
|||||||
errors: OwnedPtr<Option<AsanErrors>>,
|
errors: OwnedPtr<Option<AsanErrors>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Observer for AsanErrorsObserver {
|
impl Observer for AsanErrorsObserver {}
|
||||||
fn pre_exec(&mut self) -> Result<(), Error> {
|
|
||||||
|
impl<EM, I, S> HasExecHooks<EM, I, S> for AsanErrorsObserver {
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ASAN_ERRORS.is_some() {
|
if ASAN_ERRORS.is_some() {
|
||||||
ASAN_ERRORS.as_mut().unwrap().clear();
|
ASAN_ERRORS.as_mut().unwrap().clear();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user