This commit is contained in:
Andrea Fioraldi 2020-12-11 17:08:50 +01:00
parent 60b0b16a60
commit 55c043ec73
6 changed files with 223 additions and 110 deletions

View File

@ -194,7 +194,7 @@ where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
{ {
let mut added = 0; let mut added = 0;
for _ in 0..num { for _ in 0..num {
@ -234,7 +234,7 @@ where
I: Input, I: Input,
{ {
executor: E, executor: E,
phantom: PhantomData<I>, phantom: PhantomData<(OT, I)>,
} }
impl<E, OT, I> Engine<E, OT, I> impl<E, OT, I> Engine<E, OT, I>
@ -263,24 +263,25 @@ where
} }
} }
pub trait Fuzzer<EM, E, OT, C, I, R> pub trait Fuzzer<EM, E, OT, FT, C, I, R>
where where
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
{ {
fn stages(&self) -> &[Box<dyn Stage<EM, E, OT, C, I, R>>]; fn stages(&self) -> &[Box<dyn Stage<EM, E, OT, FT, C, I, R>>];
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<EM, E, OT, C, I, R>>>; fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<EM, E, OT, FT, C, I, R>>>;
fn add_stage(&mut self, stage: Box<dyn Stage<EM, E, OT, C, I, R>>) { fn add_stage(&mut self, stage: Box<dyn Stage<EM, E, OT, FT, C, I, R>>) {
self.stages_mut().push(stage); self.stages_mut().push(stage);
} }
fn fuzz_one<FT>( fn fuzz_one(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT>, state: &mut State<I, R, FT>,
@ -288,8 +289,6 @@ where
engine: &mut Engine<E, OT, I>, engine: &mut Engine<E, OT, I>,
manager: &mut EM, manager: &mut EM,
) -> Result<usize, AflError> ) -> Result<usize, AflError>
where
FT: FeedbacksTuple<I>
{ {
let (_, idx) = corpus.next(rand)?; let (_, idx) = corpus.next(rand)?;
@ -301,15 +300,15 @@ where
Ok(idx) Ok(idx)
} }
fn fuzz_loop<FT>( fn fuzz_loop(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R, FT>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, OT, I>, engine: &mut Engine<E, OT, I>,
manager: &mut EM, manager: &mut EM,
) -> Result<(), AflError> where ) -> Result<(), AflError>
FT: FeedbacksTuple<I>{ {
let mut last = current_milliseconds(); let mut last = current_milliseconds();
loop { loop {
self.fuzz_one(rand, state, corpus, engine, manager)?; self.fuzz_one(rand, state, corpus, engine, manager)?;
@ -325,41 +324,44 @@ where
} }
} }
pub struct StdFuzzer<EM, E, OT, C, I, R> pub struct StdFuzzer<EM, E, OT, FT, C, I, R>
where where
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
{ {
stages: Vec<Box<dyn Stage<EM, E, OT, C, I, R>>>, stages: Vec<Box<dyn Stage<EM, E, OT, FT, C, I, R>>>,
} }
impl<EM, E, OT, C, I, R> Fuzzer<EM, E, OT, C, I, R> for StdFuzzer<EM, E, OT, C, I, R> impl<EM, E, OT, FT, C, I, R> Fuzzer<EM, E, OT, FT, C, I, R> for StdFuzzer<EM, E, OT, FT, C, I, R>
where where
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
{ {
fn stages(&self) -> &[Box<dyn Stage<EM, E, OT, C, I, R>>] { fn stages(&self) -> &[Box<dyn Stage<EM, E, OT, FT, C, I, R>>] {
&self.stages &self.stages
} }
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<EM, E, OT, C, I, R>>> { fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<EM, E, OT, FT, C, I, R>>> {
&mut self.stages &mut self.stages
} }
} }
impl<EM, E, OT, C, I, R> StdFuzzer<EM, E, OT, C, I, R> impl<EM, E, OT, FT, C, I, R> StdFuzzer<EM, E, OT, FT, C, I, R>
where where
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -403,8 +405,8 @@ mod tests {
let testcase = Testcase::new(vec![0; 4]).into(); let testcase = Testcase::new(vec![0; 4]).into();
corpus.add(testcase); corpus.add(testcase);
let executor = InMemoryExecutor::<BytesInput, _>::new(harness, tuple_list!()); let executor = InMemoryExecutor::new(harness, tuple_list!());
let mut state = State::new(); let mut state = State::<BytesInput, _, _>::new();
let mut events_manager = LoggerEventManager::new(stderr()); let mut events_manager = LoggerEventManager::new(stderr());
let mut engine = Engine::new(executor); let mut engine = Engine::new(executor);

View File

@ -16,11 +16,13 @@ use std::io::Write;
use crate::engines::State; use crate::engines::State;
use crate::executors::Executor; use crate::executors::Executor;
use crate::observers::ObserversTuple;
use crate::feedbacks::FeedbacksTuple;
use crate::inputs::Input; use crate::inputs::Input;
use crate::serde_anymap::{Ptr, PtrMut}; use crate::serde_anymap::{SerdeAny, Ptr, PtrMut};
use crate::utils::Rand; use crate::utils::Rand;
use crate::AflError; use crate::AflError;
use crate::{corpus::Corpus, serde_anymap::SerdeAny}; use crate::corpus::Corpus;
/// Indicate if an event worked or not /// Indicate if an event worked or not
pub enum BrokerEventResult { pub enum BrokerEventResult {
@ -33,7 +35,7 @@ pub enum BrokerEventResult {
pub trait ShowStats {} pub trait ShowStats {}
/// A custom event, for own messages, with own handler. /// A custom event, for own messages, with own handler.
pub trait CustomEvent<I>: SerdeAny + Serialize pub trait CustomEvent<I, OT>: SerdeAny + Serialize
where where
I: Input, I: Input,
{ {
@ -48,9 +50,10 @@ where
/// Events sent around in the library /// Events sent around in the library
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(bound = "I: serde::de::DeserializeOwned")] #[serde(bound = "I: serde::de::DeserializeOwned")]
pub enum Event<'a, I> pub enum Event<'a, I, OT>
where where
I: Input, I: Input,
OT: ObserversTuple
{ {
LoadInitial { LoadInitial {
sender_id: u64, sender_id: u64,
@ -59,7 +62,7 @@ where
NewTestcase { NewTestcase {
sender_id: u64, sender_id: u64,
input: Ptr<'a, I>, input: Ptr<'a, I>,
observers: PtrMut<'a, crate::observers::observer_serde::NamedSerdeAnyMap>, observers: PtrMut<'a, OT>,
corpus_count: usize, corpus_count: usize,
}, },
UpdateStats { UpdateStats {
@ -90,14 +93,15 @@ where
Custom { Custom {
sender_id: u64, sender_id: u64,
// TODO: Allow custom events // TODO: Allow custom events
// custom_event: Box<dyn CustomEvent<I>>, // custom_event: Box<dyn CustomEvent<I, OT>>,
}, },
} }
impl<'a, I> Event<'a, I> impl<'a, I, OT> Event<'a, I, OT>
where where
I: Input, I: Input,
//CE: CustomEvent<I>, OT: ObserversTuple
//CE: CustomEvent<I, OT>,
{ {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
match self { match self {
@ -159,29 +163,31 @@ where
} }
} }
pub trait EventManager<C, E, I, R> pub trait EventManager<C, E, OT, FT, I, R>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
{ {
/// Fire an Event /// Fire an Event
fn fire<'a>(&mut self, event: Event<'a, I>) -> Result<(), AflError>; fn fire<'a>(&mut self, event: Event<'a, I, OT>) -> Result<(), AflError>;
/// Lookup for incoming events and process them. /// Lookup for incoming events and process them.
/// Return the number of processes events or an error /// Return the number of processes events or an error
fn process(&mut self, state: &mut State<I, R>, corpus: &mut C) -> Result<usize, AflError>; fn process(&mut self, state: &mut State<I, R, FT>, corpus: &mut C) -> Result<usize, AflError>;
#[inline] #[inline]
fn on_recv(&self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<(), AflError> { fn on_recv(&self, _state: &mut State<I, R, FT>, _corpus: &mut C) -> Result<(), AflError> {
// TODO: Better way to move out of testcase, or get ref // TODO: Better way to move out of testcase, or get ref
//Ok(corpus.add(self.testcase.take().unwrap())) //Ok(corpus.add(self.testcase.take().unwrap()))
Ok(()) Ok(())
} }
// TODO the broker has a state? do we need to pass state and corpus? // TODO the broker has a state? do we need to pass state and corpus?
fn handle_in_broker(&mut self, event: &Event<I>) -> Result<BrokerEventResult, AflError> { fn handle_in_broker(&mut self, event: &Event<I, OT>) -> Result<BrokerEventResult, AflError> {
match event { match event {
Event::LoadInitial { Event::LoadInitial {
sender_id: _, sender_id: _,
@ -238,8 +244,8 @@ where
fn handle_in_client( fn handle_in_client(
&mut self, &mut self,
event: Event<I>, event: Event<I, OT>,
_state: &mut State<I, R>, _state: &mut State<I, R, FT>,
_corpus: &mut C, _corpus: &mut C,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
match event { match event {
@ -263,7 +269,7 @@ where
} }
/*TODO /*TODO
fn on_recv(&self, state: &mut State<I, R>, _corpus: &mut C) -> Result<(), AflError> { fn on_recv(&self, state: &mut State<I, R, FT>, _corpus: &mut C) -> Result<(), AflError> {
println!( println!(
"#{}\t exec/s: {}", "#{}\t exec/s: {}",
state.executions(), state.executions(),
@ -275,10 +281,16 @@ where
*/ */
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub struct LoggerEventManager<C, E, I, R, W> pub struct LoggerEventManager<C, E, OT, FT, I, R, W>
where where
C: Corpus<I, R>,
E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
I: Input,
R: Rand,
W: Write, W: Write,
//CE: CustomEvent<I>, //CE: CustomEvent<I, OT>,
{ {
writer: W, writer: W,
count: usize, count: usize,
@ -288,21 +300,23 @@ where
execs_over_sec: u64, execs_over_sec: u64,
corpus_count: usize, corpus_count: usize,
phantom: PhantomData<(C, E, I, R)>, phantom: PhantomData<(C, E, OT, FT, I, R)>,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<C, E, I, R, W> EventManager<C, E, I, R> for LoggerEventManager<C, E, I, R, W> impl<C, E, OT, FT, I, R, W> EventManager<C, E, OT, FT, I, R> for LoggerEventManager<C, E, OT, FT, I, R, W>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
W: Write, W: Write,
//CE: CustomEvent<I>, //CE: CustomEvent<I, OT>,
{ {
#[inline] #[inline]
fn fire<'a>(&mut self, event: Event<'a, I>) -> Result<(), AflError> { fn fire<'a>(&mut self, event: Event<'a, I, OT>) -> Result<(), AflError> {
match self.handle_in_broker(&event)? { match self.handle_in_broker(&event)? {
BrokerEventResult::Forward => (), //self.handle_in_client(event, state, corpus)?, BrokerEventResult::Forward => (), //self.handle_in_client(event, state, corpus)?,
// Ignore broker-only events // Ignore broker-only events
@ -311,13 +325,13 @@ where
Ok(()) Ok(())
} }
fn process(&mut self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<usize, AflError> { fn process(&mut self, _state: &mut State<I, R, FT>, _corpus: &mut C) -> Result<usize, AflError> {
let c = self.count; let c = self.count;
self.count = 0; self.count = 0;
Ok(c) Ok(c)
} }
fn handle_in_broker(&mut self, event: &Event<I>) -> Result<BrokerEventResult, AflError> { fn handle_in_broker(&mut self, event: &Event<I, OT>) -> Result<BrokerEventResult, AflError> {
match event { match event {
Event::NewTestcase { Event::NewTestcase {
sender_id: _, sender_id: _,
@ -377,11 +391,13 @@ where
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<C, E, I, R, W> LoggerEventManager<C, E, I, R, W> impl<C, E, OT, FT, I, R, W> LoggerEventManager<C, E, OT, FT, I, R, W>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
R: Rand, R: Rand,
W: Write, W: Write,
//TODO CE: CustomEvent, //TODO CE: CustomEvent,
@ -400,16 +416,18 @@ where
/// Eventmanager for multi-processed application /// Eventmanager for multi-processed application
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub struct LlmpBrokerEventManager<C, E, I, R> pub struct LlmpBrokerEventManager<C, E, OT, FT, I, R>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
R: Rand, R: Rand,
//CE: CustomEvent<I>, //CE: CustomEvent<I, OT>,
{ {
llmp_broker: llmp::LlmpBroker, llmp_broker: llmp::LlmpBroker,
phantom: PhantomData<(C, E, I, R)>, phantom: PhantomData<(C, E, OT, FT, I, R)>,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -424,35 +442,39 @@ const _LLMP_TAG_EVENT_TO_BOTH: llmp::Tag = 0x2B0741;
/// Eventmanager for multi-processed application /// Eventmanager for multi-processed application
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub struct LlmpClientEventManager<C, E, I, R> pub struct LlmpClientEventManager<C, E, OT, FT, I, R>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
R: Rand, R: Rand,
//CE: CustomEvent<I>, //CE: CustomEvent<I, OT>,
{ {
_llmp_client: llmp::LlmpClient, _llmp_client: llmp::LlmpClient,
phantom: PhantomData<(C, E, I, R)>, phantom: PhantomData<(C, E, OT, FT, I, R)>,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<C, E, I, R> EventManager<C, E, I, R> for LlmpBrokerEventManager<C, E, I, R> impl<C, E, OT, FT, I, R> EventManager<C, E, OT, FT, I, R> for LlmpBrokerEventManager<C, E, OT, FT, I, R>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
E: Executor<I>, E: Executor<I>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
I: Input, I: Input,
R: Rand, R: Rand,
{ {
/// Fire an Event /// Fire an Event
fn fire<'a>(&mut self, event: Event<'a, I>) -> Result<(), AflError> { fn fire<'a>(&mut self, event: Event<'a, I, OT>) -> Result<(), AflError> {
let serialized = postcard::to_allocvec(&event)?; let serialized = postcard::to_allocvec(&event)?;
self.llmp_broker self.llmp_broker
.send_buf(LLMP_TAG_EVENT_TO_CLIENT, &serialized)?; .send_buf(LLMP_TAG_EVENT_TO_CLIENT, &serialized)?;
Ok(()) Ok(())
} }
fn process(&mut self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<usize, AflError> { fn process(&mut self, _state: &mut State<I, R, FT>, _corpus: &mut C) -> Result<usize, AflError> {
// TODO: iterators // TODO: iterators
/* /*
let mut handled = vec![]; let mut handled = vec![];
@ -481,13 +503,13 @@ where
Ok(0) Ok(0)
} }
fn on_recv(&self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<(), AflError> { fn on_recv(&self, _state: &mut State<I, R, FT>, _corpus: &mut C) -> Result<(), AflError> {
// TODO: Better way to move out of testcase, or get ref // TODO: Better way to move out of testcase, or get ref
//Ok(corpus.add(self.testcase.take().unwrap())) //Ok(corpus.add(self.testcase.take().unwrap()))
Ok(()) Ok(())
} }
fn handle_in_broker(&mut self, event: &Event<I>) -> Result<BrokerEventResult, AflError> { fn handle_in_broker(&mut self, event: &Event<I, OT>) -> Result<BrokerEventResult, AflError> {
match event { match event {
Event::LoadInitial { Event::LoadInitial {
sender_id: _, sender_id: _,
@ -542,8 +564,8 @@ where
fn handle_in_client( fn handle_in_client(
&mut self, &mut self,
event: Event<I>, event: Event<I, OT>,
/*client: &dyn EventManager<C, E, I, R>,*/ _state: &mut State<I, R>, _state: &mut State<I, R, FT>,
_corpus: &mut C, _corpus: &mut C,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
match event { match event {
@ -572,17 +594,17 @@ mod tests {
use crate::events::Event; use crate::events::Event;
use crate::inputs::bytes::BytesInput; use crate::inputs::bytes::BytesInput;
use crate::observers::observer_serde::NamedSerdeAnyMap; use crate::observers::{Observer, StdMapObserver, ObserversTuple};
use crate::observers::{Observer, StdMapObserver}; use crate::tuples::{MatchNameAndType, Named, tuple_list, tuple_list_type};
use crate::serde_anymap::{Ptr, PtrMut}; use crate::serde_anymap::{Ptr, PtrMut};
static mut MAP: [u32; 4] = [0; 4]; static mut MAP: [u32; 4] = [0; 4];
#[test] #[test]
fn test_event_serde() { fn test_event_serde() {
let mut map = NamedSerdeAnyMap::new();
let obv = StdMapObserver::new("test", unsafe { &mut MAP }); let obv = StdMapObserver::new("test", unsafe { &mut MAP });
map.insert(Box::new(obv), &"key".to_string()); let mut map = tuple_list!(obv);
let i = BytesInput::new(vec![0]); let i = BytesInput::new(vec![0]);
let e = Event::NewTestcase { let e = Event::NewTestcase {
@ -594,19 +616,16 @@ mod tests {
let j = serde_json::to_string(&e).unwrap(); let j = serde_json::to_string(&e).unwrap();
let d: Event<BytesInput> = serde_json::from_str(&j).unwrap(); let d: Event<BytesInput, tuple_list_type!(StdMapObserver<u32>)> = serde_json::from_str(&j).unwrap();
match d { match d {
Event::NewTestcase { Event::NewTestcase {
sender_id: _, sender_id: _,
input: _, input: _,
observers: obs, observers,
corpus_count: _, corpus_count: _,
} => { } => {
let o = obs let o = observers.as_ref().match_name_type::<StdMapObserver<u32>>("test").unwrap();
.as_ref() assert_eq!("test", o.name());
.get::<StdMapObserver<u32>>(&"key".to_string())
.unwrap();
assert_eq!("test".to_string(), *o.name());
} }
_ => panic!("mistmatch".to_string()), _ => panic!("mistmatch".to_string()),
}; };

View File

@ -19,7 +19,7 @@ pub type MinMapFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
/// Feedbacks evaluate the observers. /// Feedbacks evaluate the observers.
/// Basically, they reduce the information provided by an observer to a value, /// Basically, they reduce the information provided by an observer to a value,
/// indicating the "interestingness" of the last run. /// indicating the "interestingness" of the last run.
pub trait Feedback<I>: Named pub trait Feedback<I>: Named + 'static
where where
I: Input, I: Input,
{ {
@ -39,7 +39,7 @@ where
} }
} }
pub trait FeedbacksTuple<I>: TupleList + MatchType + MatchNameAndType pub trait FeedbacksTuple<I>: MatchType + MatchNameAndType
where where
I: Input I: Input
{ {
@ -61,7 +61,7 @@ I: Input{
impl<Head, Tail, I> FeedbacksTuple<I> for (Head, Tail) where impl<Head, Tail, I> FeedbacksTuple<I> for (Head, Tail) where
Head: Feedback<I>, Head: Feedback<I>,
Tail: FeedbacksTuple<I>, Tail: FeedbacksTuple<I> + TupleList,
I: Input I: Input
{ {
fn is_interesting_all<OT: ObserversTuple>(&mut self, input: &I, observers: &OT) -> Result<u32, AflError> { fn is_interesting_all<OT: ObserversTuple>(&mut self, input: &I, observers: &OT) -> Result<u32, AflError> {
@ -90,7 +90,7 @@ impl<Head, Tail, I> FeedbacksTuple<I> for (Head, Tail) where
} }
/// 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> pub trait Reducer<T>: 'static
where where
T: Integer + Copy + 'static, T: Integer + Copy + 'static,
{ {

View File

@ -1,8 +1,5 @@
extern crate num; extern crate num;
use alloc::boxed::Box;
use alloc::string::String;
use core::any::Any;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::serde_anymap::ArrayMut; use crate::serde_anymap::ArrayMut;
@ -26,21 +23,23 @@ pub trait Observer: Named + 'static {
} }
} }
pub trait ObserversTuple: TupleList + MatchNameAndType + MatchType + serde::Serialize + serde::de::DeserializeOwned { pub trait ObserversTuple: MatchNameAndType + MatchType + serde::Serialize + serde::de::DeserializeOwned {
fn reset_all(&mut self) -> Result<(), AflError>; fn reset_all(&mut self) -> Result<(), AflError>;
fn post_exec_all(&mut self) -> Result<(), AflError>; fn post_exec_all(&mut self) -> Result<(), AflError>;
fn for_each(&self, f: fn(&dyn Observer)); //fn for_each(&self, f: fn(&dyn Observer));
//fn for_each_mut(&mut self, f: fn(&mut dyn Observer));
} }
impl ObserversTuple for () { impl ObserversTuple for () {
fn reset_all(&mut self) -> Result<(), AflError> { Ok(()) } fn reset_all(&mut self) -> Result<(), AflError> { Ok(()) }
fn post_exec_all(&mut self) -> Result<(), AflError> { Ok(()) } fn post_exec_all(&mut self) -> Result<(), AflError> { Ok(()) }
fn for_each(&self, f: fn(&dyn Observer)) { } //fn for_each(&self, f: fn(&dyn Observer)) { }
//fn for_each_mut(&mut self, f: fn(&mut dyn Observer)) { }
} }
impl<Head, Tail> ObserversTuple for (Head, Tail) where impl<Head, Tail> ObserversTuple for (Head, Tail) where
Head: Observer, Head: Observer + serde::Serialize + serde::de::DeserializeOwned,
Tail: ObserversTuple, Tail: ObserversTuple + TupleList,
{ {
fn reset_all(&mut self) -> Result<(), AflError> { fn reset_all(&mut self) -> Result<(), AflError> {
self.0.reset()?; self.0.reset()?;
@ -52,10 +51,15 @@ impl<Head, Tail> ObserversTuple for (Head, Tail) where
self.1.post_exec_all() self.1.post_exec_all()
} }
fn for_each(&self, f: fn(&dyn Observer)) { /*fn for_each(&self, f: fn(&dyn Observer)) {
f(self.0); f(&self.0);
self.1.for_each(f) self.1.for_each(f)
} }
fn for_each_mut(&mut self, f: fn(&mut dyn Observer)) {
f(&mut self.0);
self.1.for_each_mut(f)
}*/
} }
/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information /// A MapObserver observes the static map, as oftentimes used for afl-like coverage information

View File

@ -7,15 +7,16 @@ use crate::events::EventManager;
use crate::executors::{HasObservers, Executor}; use crate::executors::{HasObservers, Executor};
use crate::observers::ObserversTuple; use crate::observers::ObserversTuple;
use crate::feedbacks::FeedbacksTuple; use crate::feedbacks::FeedbacksTuple;
use crate::tuples::{TupleList, MatchType};
use crate::inputs::Input; use crate::inputs::Input;
use crate::utils::Rand; use crate::utils::Rand;
use crate::AflError; use crate::AflError;
/// A stage is one step in the fuzzing process. /// A stage is one step in the fuzzing process.
/// Multiple stages will be scheduled one by one for each input. /// Multiple stages will be scheduled one by one for each input.
pub trait Stage<EM, E, OT, C, I, R> pub trait Stage<EM, E, OT, FT, C, I, R>
where where
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
@ -34,3 +35,84 @@ where
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError>; ) -> Result<(), AflError>;
} }
pub trait StagesTuple<EM, E, OT, FT, C, I, R>
where
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
{
fn perform_all(
&mut self,
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError>;
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>));
fn for_each_mut(&mut self, f: fn(&mut dyn Stage<EM, E, OT, FT, C, I, R>));
}
impl<EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for ()
where
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
{
fn perform_all(
&mut self,
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError> { Ok(()) }
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>)) { }
fn for_each_mut(&mut self, f: fn(&mut dyn Stage<EM, E, OT, FT, C, I, R>)) { }
}
impl<Head, Tail, EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for (Head, Tail) where
Head: Stage<EM, E, OT, FT, C, I, R>,
Tail: StagesTuple<EM, E, OT, FT, C, I, R> + TupleList,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
{
fn perform_all(
&mut self,
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError> {
self.0.perform(rand, state, corpus, engine, manager, corpus_idx)?;
self.1.perform_all(rand, state, corpus, engine, manager, corpus_idx)
}
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>)) {
f(&self.0);
self.1.for_each(f)
}
fn for_each_mut(&mut self, f: fn(&mut dyn Stage<EM, E, OT, FT, C, I, R>)) {
f(&mut self.0);
self.1.for_each_mut(f)
}
}

View File

@ -1,8 +1,9 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::events::EventManager; use crate::events::EventManager;
use crate::executors::Executor; use crate::executors::{HasObservers, Executor};
use crate::observers::ObserversTuple; use crate::observers::ObserversTuple;
use crate::feedbacks::FeedbacksTuple;
use crate::inputs::Input; use crate::inputs::Input;
use crate::mutators::Mutator; use crate::mutators::Mutator;
use crate::stages::Corpus; use crate::stages::Corpus;
@ -18,12 +19,13 @@ use crate::serde_anymap::{Ptr, PtrMut};
/// A Mutational stage is the stage in a fuzzing run that mutates inputs. /// A Mutational stage is the stage in a fuzzing run that mutates inputs.
/// Mutational stages will usually have a range of mutations that are /// Mutational stages will usually have a range of mutations that are
/// being applied to the input one by one, between executions. /// being applied to the input one by one, between executions.
pub trait MutationalStage<M, EM, E, OT, C, I, R>: Stage<EM, E, OT, C, I, R> pub trait MutationalStage<M, EM, E, OT, FT, C, I, R>: Stage<EM, E, OT, FT, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I, OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -45,9 +47,9 @@ where
fn perform_mutational( fn perform_mutational(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, I>, engine: &mut Engine<E, OT, I>,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
@ -84,26 +86,28 @@ where
} }
/// The default mutational stage /// The default mutational stage
pub struct StdMutationalStage<M, EM, E, OT, C, I, R> pub struct StdMutationalStage<M, EM, E, OT, FT, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I, OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
{ {
mutator: M, mutator: M,
phantom: PhantomData<(EM, E, OT, C, I, R)>, phantom: PhantomData<(EM, E, OT, FT, C, I, R)>,
} }
impl<M, EM, E, OT, C, I, R> MutationalStage<M, EM, E, OT, C, I, R> for StdMutationalStage<M, EM, E, OT, C, I, R> impl<M, EM, E, OT, FT, C, I, R> MutationalStage<M, EM, E, OT, FT, C, I, R> for StdMutationalStage<M, EM, E, OT, FT, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I, OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -121,12 +125,13 @@ where
} }
} }
impl<M, EM, E, OT, C, I, R> Stage<EM, E, OT, C, I, R> for StdMutationalStage<M, EM, E, OT, C, I, R> impl<M, EM, E, OT, FT, C, I, R> Stage<EM, E, OT, FT, C, I, R> for StdMutationalStage<M, EM, E, OT, FT, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I, OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,
@ -135,9 +140,9 @@ where
fn perform( fn perform(
&mut self, &mut self,
rand: &mut R, rand: &mut R,
state: &mut State<I, R>, state: &mut State<I, R, FT>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<E, I>, engine: &mut Engine<E, OT, I>,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
@ -145,12 +150,13 @@ where
} }
} }
impl<M, EM, E, OT, C, I, R> StdMutationalStage<M, EM, E, OT, C, I, R> impl<M, EM, E, OT, FT, C, I, R> StdMutationalStage<M, EM, E, OT, FT, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
EM: EventManager<C, E, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I, OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
FT: FeedbacksTuple<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
R: Rand, R: Rand,