This commit is contained in:
Andrea Fioraldi 2020-12-11 17:55:43 +01:00
parent 55c043ec73
commit 4f6a27ff14
10 changed files with 234 additions and 159 deletions

View File

@ -1,19 +1,18 @@
//! The engine is the core piece of every good fuzzer //! The engine is the core piece of every good fuzzer
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::vec::Vec;
use core::fmt::Debug; use core::fmt::Debug;
use core::marker::PhantomData; use core::marker::PhantomData;
use hashbrown::HashMap; use hashbrown::HashMap;
use crate::corpus::{Corpus, Testcase}; use crate::corpus::{Corpus, Testcase};
use crate::events::{Event, EventManager}; use crate::events::{Event, EventManager};
use crate::executors::{HasObservers, Executor}; use crate::executors::{Executor, HasObservers};
use crate::feedbacks::{FeedbacksTuple}; use crate::feedbacks::FeedbacksTuple;
use crate::observers::ObserversTuple;
use crate::generators::Generator; use crate::generators::Generator;
use crate::inputs::Input; use crate::inputs::Input;
use crate::stages::Stage; use crate::observers::ObserversTuple;
use crate::stages::StagesTuple;
use crate::utils::{current_milliseconds, Rand}; use crate::utils::{current_milliseconds, Rand};
use crate::AflError; use crate::AflError;
@ -27,7 +26,7 @@ pub struct State<I, R, FT>
where where
I: Input, I: Input,
R: Rand, R: Rand,
FT: FeedbacksTuple<I> FT: FeedbacksTuple<I>,
{ {
/// How many times the executor ran the harness/target /// How many times the executor ran the harness/target
executions: usize, executions: usize,
@ -37,14 +36,14 @@ where
metadatas: HashMap<&'static str, Box<dyn StateMetadata>>, metadatas: HashMap<&'static str, Box<dyn StateMetadata>>,
// additional_corpuses: HashMap<&'static str, Box<dyn Corpus>>, // additional_corpuses: HashMap<&'static str, Box<dyn Corpus>>,
feedbacks: FT, feedbacks: FT,
phantom: PhantomData<R>, phantom: PhantomData<(I, R)>,
} }
impl<I, R, FT> State<I, R, FT> impl<I, R, FT> State<I, R, FT>
where where
I: Input, I: Input,
R: Rand, R: Rand,
FT: FeedbacksTuple<I> FT: FeedbacksTuple<I>,
{ {
/// Get executions /// Get executions
#[inline] #[inline]
@ -117,7 +116,7 @@ where
pub fn evaluate_input<E, OT>(&mut self, input: &I, executor: &mut E) -> Result<u32, AflError> pub fn evaluate_input<E, OT>(&mut self, input: &I, executor: &mut E) -> Result<u32, AflError>
where where
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple OT: ObserversTuple,
{ {
executor.reset_observers()?; executor.reset_observers()?;
executor.run_target(&input)?; executor.run_target(&input)?;
@ -216,12 +215,12 @@ where
Ok(()) Ok(())
} }
pub fn new() -> Self { pub fn new(feedbacks: FT) -> Self {
Self { Self {
executions: 0, executions: 0,
start_time: current_milliseconds(), start_time: current_milliseconds(),
metadatas: HashMap::default(), metadatas: HashMap::default(),
feedbacks: vec![], feedbacks: feedbacks,
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -263,8 +262,9 @@ where
} }
} }
pub trait Fuzzer<EM, E, OT, FT, C, I, R> pub trait Fuzzer<ST, EM, E, OT, FT, C, I, R>
where where
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
@ -273,13 +273,9 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
fn stages(&self) -> &[Box<dyn Stage<EM, E, OT, FT, C, I, R>>]; fn stages(&self) -> &ST;
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<EM, E, OT, FT, C, I, R>>>; fn stages_mut(&mut self) -> &mut ST;
fn add_stage(&mut self, stage: Box<dyn Stage<EM, E, OT, FT, C, I, R>>) {
self.stages_mut().push(stage);
}
fn fuzz_one( fn fuzz_one(
&mut self, &mut self,
@ -288,13 +284,11 @@ where
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<usize, AflError> ) -> Result<usize, AflError> {
{
let (_, idx) = corpus.next(rand)?; let (_, idx) = corpus.next(rand)?;
for stage in self.stages_mut() { self.stages_mut()
stage.perform(rand, state, corpus, engine, manager, idx)?; .perform_all(rand, state, corpus, engine, manager, idx)?;
}
manager.process(state, corpus)?; manager.process(state, corpus)?;
Ok(idx) Ok(idx)
@ -307,8 +301,7 @@ where
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> ) -> Result<(), AflError> {
{
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)?;
@ -324,8 +317,9 @@ where
} }
} }
pub struct StdFuzzer<EM, E, OT, FT, C, I, R> pub struct StdFuzzer<ST, EM, E, OT, FT, C, I, R>
where where
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
@ -334,11 +328,14 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
stages: Vec<Box<dyn Stage<EM, E, OT, FT, C, I, R>>>, stages: ST,
phantom: PhantomData<(EM, E, OT, FT, 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> impl<ST, EM, E, OT, FT, C, I, R> Fuzzer<ST, EM, E, OT, FT, C, I, R>
for StdFuzzer<ST, EM, E, OT, FT, C, I, R>
where where
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
@ -347,17 +344,18 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
fn stages(&self) -> &[Box<dyn Stage<EM, E, OT, FT, C, I, R>>] { fn stages(&self) -> &ST {
&self.stages &self.stages
} }
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<EM, E, OT, FT, C, I, R>>> { fn stages_mut(&mut self) -> &mut ST {
&mut self.stages &mut self.stages
} }
} }
impl<EM, E, OT, FT, C, I, R> StdFuzzer<EM, E, OT, FT, C, I, R> impl<ST, EM, E, OT, FT, C, I, R> StdFuzzer<ST, EM, E, OT, FT, C, I, R>
where where
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
@ -366,8 +364,11 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
pub fn new() -> Self { pub fn new(stages: ST) -> Self {
Self { stages: vec![] } Self {
stages: stages,
phantom: PhantomData,
}
} }
} }
@ -376,8 +377,6 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use alloc::boxed::Box;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::io::stderr; use std::io::stderr;
@ -405,18 +404,15 @@ 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::new(harness, tuple_list!()); let executor = InMemoryExecutor::<BytesInput, _>::new(harness, tuple_list!());
let mut state = State::<BytesInput, _, _>::new(); let mut state = State::new(tuple_list!());
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);
let mut mutator = StdScheduledMutator::new(); let mut mutator = StdScheduledMutator::new();
mutator.add_mutation(mutation_bitflip); mutator.add_mutation(mutation_bitflip);
let stage = StdMutationalStage::new(mutator); let stage = StdMutationalStage::new(mutator);
let mut fuzzer = StdFuzzer::new(); let mut fuzzer = StdFuzzer::new(tuple_list!(stage));
fuzzer.add_stage(Box::new(stage));
//
for i in 0..1000 { for i in 0..1000 {
fuzzer fuzzer

View File

@ -14,15 +14,15 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::io::Write; use std::io::Write;
use crate::corpus::Corpus;
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::feedbacks::FeedbacksTuple;
use crate::inputs::Input; use crate::inputs::Input;
use crate::serde_anymap::{SerdeAny, Ptr, PtrMut}; use crate::observers::ObserversTuple;
use crate::serde_anymap::{Ptr, PtrMut, SerdeAny};
use crate::utils::Rand; use crate::utils::Rand;
use crate::AflError; use crate::AflError;
use crate::corpus::Corpus;
/// Indicate if an event worked or not /// Indicate if an event worked or not
pub enum BrokerEventResult { pub enum BrokerEventResult {
@ -53,7 +53,7 @@ where
pub enum Event<'a, I, OT> pub enum Event<'a, I, OT>
where where
I: Input, I: Input,
OT: ObserversTuple OT: ObserversTuple,
{ {
LoadInitial { LoadInitial {
sender_id: u64, sender_id: u64,
@ -100,8 +100,7 @@ where
impl<'a, I, OT> Event<'a, I, OT> impl<'a, I, OT> Event<'a, I, OT>
where where
I: Input, I: Input,
OT: ObserversTuple OT: ObserversTuple, //CE: CustomEvent<I, OT>,
//CE: CustomEvent<I, OT>,
{ {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
match self { match self {
@ -304,7 +303,8 @@ where
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<C, E, OT, FT, I, R, W> EventManager<C, E, OT, FT, I, R> for LoggerEventManager<C, E, OT, FT, 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>,
@ -325,7 +325,11 @@ where
Ok(()) Ok(())
} }
fn process(&mut self, _state: &mut State<I, R, FT>, _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)
@ -457,7 +461,8 @@ where
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<C, E, OT, FT, I, R> EventManager<C, E, OT, FT, I, R> for LlmpBrokerEventManager<C, E, OT, FT, 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>,
@ -474,7 +479,11 @@ where
Ok(()) Ok(())
} }
fn process(&mut self, _state: &mut State<I, R, FT>, _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![];
@ -594,15 +603,14 @@ mod tests {
use crate::events::Event; use crate::events::Event;
use crate::inputs::bytes::BytesInput; use crate::inputs::bytes::BytesInput;
use crate::observers::{Observer, StdMapObserver, ObserversTuple}; use crate::observers::{Observer, ObserversTuple, StdMapObserver};
use crate::tuples::{MatchNameAndType, Named, tuple_list, tuple_list_type};
use crate::serde_anymap::{Ptr, PtrMut}; use crate::serde_anymap::{Ptr, PtrMut};
use crate::tuples::{tuple_list, tuple_list_type, MatchNameAndType, Named};
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 obv = StdMapObserver::new("test", unsafe { &mut MAP }); let obv = StdMapObserver::new("test", unsafe { &mut MAP });
let mut map = tuple_list!(obv); let mut map = tuple_list!(obv);
@ -616,7 +624,8 @@ mod tests {
let j = serde_json::to_string(&e).unwrap(); let j = serde_json::to_string(&e).unwrap();
let d: Event<BytesInput, tuple_list_type!(StdMapObserver<u32>)> = 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: _,
@ -624,7 +633,10 @@ mod tests {
observers, observers,
corpus_count: _, corpus_count: _,
} => { } => {
let o = observers.as_ref().match_name_type::<StdMapObserver<u32>>("test").unwrap(); let o = observers
.as_ref()
.match_name_type::<StdMapObserver<u32>>("test")
.unwrap();
assert_eq!("test", o.name()); assert_eq!("test", o.name());
} }
_ => panic!("mistmatch".to_string()), _ => panic!("mistmatch".to_string()),

View File

@ -1,9 +1,9 @@
use core::ffi::c_void; use core::ffi::c_void;
use core::ptr; use core::ptr;
use crate::executors::{Executor, HasObservers, ExitKind}; use crate::executors::{Executor, ExitKind, HasObservers};
use crate::inputs::{HasTargetBytes, Input}; use crate::inputs::{HasTargetBytes, Input};
use crate::observers::{ObserversTuple}; use crate::observers::ObserversTuple;
use crate::AflError; use crate::AflError;
/// The (unsafe) pointer to the current inmem executor, for the current run. /// The (unsafe) pointer to the current inmem executor, for the current run.
@ -17,7 +17,7 @@ type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
pub struct InMemoryExecutor<I, OT> pub struct InMemoryExecutor<I, OT>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple OT: ObserversTuple,
{ {
harness: HarnessFunction<I>, harness: HarnessFunction<I>,
observers: OT, observers: OT,
@ -26,7 +26,7 @@ where
impl<I, OT> Executor<I> for InMemoryExecutor<I, OT> impl<I, OT> Executor<I> for InMemoryExecutor<I, OT>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple OT: ObserversTuple,
{ {
#[inline] #[inline]
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> { fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> {
@ -42,9 +42,11 @@ where
} }
} }
impl<I, OT> HasObservers<OT> for InMemoryExecutor<I, OT> where impl<I, OT> HasObservers<OT> for InMemoryExecutor<I, OT>
I: Input + HasTargetBytes, where
OT: ObserversTuple { I: Input + HasTargetBytes,
OT: ObserversTuple,
{
#[inline] #[inline]
fn observers(&self) -> &OT { fn observers(&self) -> &OT {
&self.observers &self.observers
@ -59,7 +61,7 @@ OT: ObserversTuple {
impl<I, OT> InMemoryExecutor<I, OT> impl<I, OT> InMemoryExecutor<I, OT>
where where
I: Input + HasTargetBytes, I: Input + HasTargetBytes,
OT: ObserversTuple OT: ObserversTuple,
{ {
pub fn new(harness_fn: HarnessFunction<I>, observers: OT) -> Self { pub fn new(harness_fn: HarnessFunction<I>, observers: OT) -> Self {
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -190,7 +192,7 @@ mod tests {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
fn test_harness_fn_nop(_executor: &dyn Executor<NopInput, tuple_list_type!()>, buf: &[u8]) -> ExitKind { fn test_harness_fn_nop(_executor: &dyn Executor<NopInput>, buf: &[u8]) -> ExitKind {
println!("Fake exec with buf of len {}", buf.len()); println!("Fake exec with buf of len {}", buf.len());
ExitKind::Ok ExitKind::Ok
} }

View File

@ -1,7 +1,7 @@
pub mod inmemory; pub mod inmemory;
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::{ObserversTuple}; use crate::observers::ObserversTuple;
use crate::AflError; use crate::AflError;
/// How an execution finished. /// How an execution finished.
@ -12,7 +12,10 @@ pub enum ExitKind {
Timeout, Timeout,
} }
pub trait HasObservers<OT> where OT: ObserversTuple { pub trait HasObservers<OT>
where
OT: ObserversTuple,
{
/// Get the linked observers /// Get the linked observers
fn observers(&self) -> &OT; fn observers(&self) -> &OT;

View File

@ -4,10 +4,10 @@ use alloc::vec::Vec;
use core::marker::PhantomData; use core::marker::PhantomData;
use num::Integer; use num::Integer;
use crate::inputs::Input;
use crate::observers::{ObserversTuple, Observer, MapObserver};
use crate::corpus::Testcase; use crate::corpus::Testcase;
use crate::tuples::{Named, TupleList, MatchNameAndType, MatchType}; use crate::inputs::Input;
use crate::observers::{MapObserver, Observer, ObserversTuple};
use crate::tuples::{MatchNameAndType, MatchType, Named, TupleList};
use crate::AflError; use crate::AflError;
pub type MaxMapFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>; pub type MaxMapFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
@ -24,7 +24,11 @@ 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>(&mut self, input: &I, observers: &OT) -> Result<u32, AflError>; fn is_interesting<OT: ObserversTuple>(
&mut self,
input: &I,
observers: &OT,
) -> Result<u32, AflError>;
/// 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]
@ -41,39 +45,61 @@ where
pub trait FeedbacksTuple<I>: MatchType + MatchNameAndType pub trait FeedbacksTuple<I>: MatchType + MatchNameAndType
where where
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>;
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), AflError>; fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), AflError>;
fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError>; fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError>;
//fn for_each(&self, f: fn(&dyn Feedback<I>)); //fn for_each(&self, f: fn(&dyn Feedback<I>));
//fn for_each_mut(&mut self, f: fn(&mut dyn Feedback<I>)); //fn for_each_mut(&mut self, f: fn(&mut dyn Feedback<I>));
} }
impl<I> FeedbacksTuple<I> for () where impl<I> FeedbacksTuple<I> for ()
I: Input{ where
fn is_interesting_all<OT: ObserversTuple>(&mut self, input: &I, observers: &OT) -> Result<u32, AflError> { Ok(0) } I: Input,
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), AflError> { Ok(())} {
fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError> { Ok(())} fn is_interesting_all<OT: ObserversTuple>(
&mut self,
input: &I,
observers: &OT,
) -> Result<u32, AflError> {
Ok(0)
}
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), AflError> {
Ok(())
}
fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError> {
Ok(())
}
//fn for_each(&self, f: fn(&dyn Feedback<I>)) {} //fn for_each(&self, f: fn(&dyn Feedback<I>)) {}
//fn for_each_mut(&mut self, f: fn(&mut dyn Feedback<I>)) {} //fn for_each_mut(&mut self, f: fn(&mut dyn Feedback<I>)) {}
} }
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> + TupleList, 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>(
Ok(self.0.is_interesting(input, observers)? + self.1.is_interesting_all(input, observers)?) &mut self,
input: &I,
observers: &OT,
) -> Result<u32, AflError> {
Ok(self.0.is_interesting(input, observers)?
+ self.1.is_interesting_all(input, observers)?)
} }
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), AflError>{ fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), AflError> {
self.0.append_metadata(testcase)?; self.0.append_metadata(testcase)?;
self.1.append_metadata_all(testcase) self.1.append_metadata_all(testcase)
} }
fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError>{ fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError> {
self.0.discard_metadata(input)?; self.0.discard_metadata(input)?;
self.1.discard_metadata_all(input) self.1.discard_metadata_all(input)
} }
@ -191,7 +217,7 @@ where
O: MapObserver<T> + 'static, O: MapObserver<T> + 'static,
{ {
#[inline] #[inline]
fn name(&self) -> &'static str { fn name(&self) -> &str {
self.name self.name
} }
} }
@ -211,13 +237,13 @@ where
} }
} }
pub fn new_with_observer(map_observer: &O) -> Self { /*pub fn new_with_observer(map_observer: &O) -> Self {
Self { Self {
history_map: vec![T::default(); map_observer.map().len()], history_map: vec![T::default(); map_observer.map().len()],
name: map_observer.name(), name: map_observer.name(),
phantom: PhantomData, phantom: PhantomData,
} }
} }*/
} }
impl<T, R, O> MapFeedback<T, R, O> impl<T, R, O> MapFeedback<T, R, O>

View File

@ -3,12 +3,12 @@ extern crate num;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::serde_anymap::ArrayMut; use crate::serde_anymap::ArrayMut;
use crate::tuples::{TupleList, MatchNameAndType, MatchType, Named}; use crate::tuples::{MatchNameAndType, MatchType, Named, TupleList};
use crate::AflError; use crate::AflError;
/// Observers observe different information about the target. /// Observers observe different information about the target.
/// They can then be used by various sorts of feedback. /// They can then be used by various sorts of feedback.
pub trait Observer: Named + '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.
#[inline] #[inline]
fn flush(&mut self) -> Result<(), AflError> { fn flush(&mut self) -> Result<(), AflError> {
@ -23,7 +23,9 @@ pub trait Observer: Named + 'static {
} }
} }
pub trait ObserversTuple: 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));
@ -31,14 +33,19 @@ pub trait ObserversTuple: MatchNameAndType + MatchType + serde::Serialize + serd
} }
impl ObserversTuple for () { impl ObserversTuple for () {
fn reset_all(&mut self) -> Result<(), AflError> { Ok(()) } fn reset_all(&mut self) -> Result<(), AflError> {
fn post_exec_all(&mut self) -> Result<(), AflError> { Ok(()) } 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)) { } //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)
Head: Observer + serde::Serialize + serde::de::DeserializeOwned, where
Head: Observer,
Tail: ObserversTuple + TupleList, Tail: ObserversTuple + TupleList,
{ {
fn reset_all(&mut self) -> Result<(), AflError> { fn reset_all(&mut self) -> Result<(), AflError> {
@ -105,7 +112,7 @@ where
{ {
map: ArrayMut<T>, map: ArrayMut<T>,
initial: T, initial: T,
name: &'static str, name: String,
} }
impl<T> Observer for StdMapObserver<T> impl<T> Observer for StdMapObserver<T>
@ -118,12 +125,13 @@ where
} }
} }
impl<T> Named for StdMapObserver<T> where impl<T> Named for StdMapObserver<T>
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, where
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
{ {
#[inline] #[inline]
fn name(&self) -> &'static str { fn name(&self) -> &str {
self.name self.name.as_str()
} }
} }

View File

@ -4,11 +4,11 @@ pub use mutational::StdMutationalStage;
use crate::corpus::Corpus; use crate::corpus::Corpus;
use crate::engines::{Engine, State}; use crate::engines::{Engine, State};
use crate::events::EventManager; use crate::events::EventManager;
use crate::executors::{HasObservers, Executor}; use crate::executors::{Executor, HasObservers};
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::observers::ObserversTuple;
use crate::tuples::{MatchType, TupleList};
use crate::utils::Rand; use crate::utils::Rand;
use crate::AflError; use crate::AflError;
@ -77,12 +77,15 @@ where
engine: &mut Engine<E, OT, I>, engine: &mut Engine<E, OT, I>,
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError> { Ok(()) } ) -> Result<(), AflError> {
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>)) { } Ok(())
fn for_each_mut(&mut self, f: fn(&mut dyn Stage<EM, E, OT, FT, C, I, R>)) { } }
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 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>, Head: Stage<EM, E, OT, FT, C, I, R>,
Tail: StagesTuple<EM, E, OT, FT, C, I, R> + TupleList, Tail: StagesTuple<EM, E, OT, FT, C, I, R> + TupleList,
EM: EventManager<C, E, OT, FT, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
@ -102,8 +105,10 @@ impl<Head, Tail, EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for
manager: &mut EM, manager: &mut EM,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
self.0.perform(rand, state, corpus, engine, manager, corpus_idx)?; self.0
self.1.perform_all(rand, state, corpus, engine, manager, corpus_idx) .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>)) { fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, C, I, R>)) {

View File

@ -1,11 +1,11 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::events::EventManager; use crate::events::EventManager;
use crate::executors::{HasObservers, Executor}; use crate::executors::{Executor, HasObservers};
use crate::observers::ObserversTuple;
use crate::feedbacks::FeedbacksTuple; use crate::feedbacks::FeedbacksTuple;
use crate::inputs::Input; use crate::inputs::Input;
use crate::mutators::Mutator; use crate::mutators::Mutator;
use crate::observers::ObserversTuple;
use crate::stages::Corpus; use crate::stages::Corpus;
use crate::stages::{Engine, Stage}; use crate::stages::{Engine, Stage};
use crate::utils::Rand; use crate::utils::Rand;
@ -101,7 +101,8 @@ where
phantom: PhantomData<(EM, E, OT, FT, C, I, R)>, phantom: PhantomData<(EM, E, OT, FT, 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> 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, OT, FT, I, R>, EM: EventManager<C, E, OT, FT, I, R>,
@ -125,7 +126,8 @@ where
} }
} }
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> 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, OT, FT, I, R>, EM: EventManager<C, E, OT, FT, I, R>,

View File

@ -1,6 +1,6 @@
pub use tuple_list::TupleList;
pub use tuple_list::tuple_list; pub use tuple_list::tuple_list;
pub use tuple_list::tuple_list_type; pub use tuple_list::tuple_list_type;
pub use tuple_list::TupleList;
use core::any::TypeId; use core::any::TypeId;
@ -9,10 +9,13 @@ pub trait HasLen {
} }
impl HasLen for () { impl HasLen for () {
fn len(&self) -> usize { 0 } fn len(&self) -> usize {
0
}
} }
impl<Head, Tail> HasLen for (Head, Tail) where impl<Head, Tail> HasLen for (Head, Tail)
where
Tail: TupleList + HasLen, Tail: TupleList + HasLen,
{ {
fn len(&self) -> usize { fn len(&self) -> usize {
@ -26,11 +29,16 @@ pub trait MatchFirstType {
} }
impl MatchFirstType for () { impl MatchFirstType for () {
fn match_first_type<T: 'static>(&self) -> Option<&T> { None } fn match_first_type<T: 'static>(&self) -> Option<&T> {
fn match_first_type_mut<T: 'static>(&mut self) -> Option<&mut T> { None } None
}
fn match_first_type_mut<T: 'static>(&mut self) -> Option<&mut T> {
None
}
} }
impl<Head, Tail> MatchFirstType for (Head, Tail) where impl<Head, Tail> MatchFirstType for (Head, Tail)
where
Head: 'static, Head: 'static,
Tail: TupleList + MatchFirstType, Tail: TupleList + MatchFirstType,
{ {
@ -57,11 +65,16 @@ pub trait MatchType {
} }
impl MatchType for () { impl MatchType for () {
fn match_type<T: 'static>(&self, f: fn(t: &T)) { () } fn match_type<T: 'static>(&self, f: fn(t: &T)) {
fn match_type_mut<T: 'static>(&mut self, f: fn(t: &mut T)) { () } ()
}
fn match_type_mut<T: 'static>(&mut self, f: fn(t: &mut T)) {
()
}
} }
impl<Head, Tail> MatchType for (Head, Tail) where impl<Head, Tail> MatchType for (Head, Tail)
where
Head: 'static, Head: 'static,
Tail: TupleList + MatchType, Tail: TupleList + MatchType,
{ {
@ -81,7 +94,7 @@ impl<Head, Tail> MatchType for (Head, Tail) where
} }
pub trait Named { pub trait Named {
fn name(&self) -> &'static str; fn name(&self) -> &str;
} }
pub trait MatchNameAndType { pub trait MatchNameAndType {
@ -90,11 +103,16 @@ pub trait MatchNameAndType {
} }
impl MatchNameAndType for () { impl MatchNameAndType for () {
fn match_name_type<T: 'static>(&self, name: &'static str) -> Option<&T> { None } fn match_name_type<T: 'static>(&self, name: &'static str) -> Option<&T> {
fn match_name_type_mut<T: 'static>(&mut self, name: &'static str) -> Option<&mut T> { None } None
}
fn match_name_type_mut<T: 'static>(&mut self, name: &'static str) -> Option<&mut T> {
None
}
} }
impl<Head, Tail> MatchNameAndType for (Head, Tail) where impl<Head, Tail> MatchNameAndType for (Head, Tail)
where
Head: 'static + Named, Head: 'static + Named,
Tail: TupleList + MatchNameAndType, Tail: TupleList + MatchNameAndType,
{ {
@ -122,7 +140,10 @@ pub trait Prepend<T>: TupleList {
} }
/// Implement prepend for tuple list. /// Implement prepend for tuple list.
impl<Tail, T> Prepend<T> for Tail where Tail: TupleList { impl<Tail, T> Prepend<T> for Tail
where
Tail: TupleList,
{
type PreprendResult = Self; type PreprendResult = Self;
fn prepend(self, value: T) -> (T, Self::PreprendResult) { fn prepend(self, value: T) -> (T, Self::PreprendResult) {
@ -140,11 +161,14 @@ pub trait Append<T>: TupleList {
impl<T> Append<T> for () { impl<T> Append<T> for () {
type AppendResult = (T, ()); type AppendResult = (T, ());
fn append(self, value: T) -> Self::AppendResult { (value, ()) } fn append(self, value: T) -> Self::AppendResult {
(value, ())
}
} }
/// Implement append for non-empty tuple list. /// Implement append for non-empty tuple list.
impl<Head, Tail, T> Append<T> for (Head, Tail) where impl<Head, Tail, T> Append<T> for (Head, Tail)
where
Self: TupleList, Self: TupleList,
Tail: Append<T>, Tail: Append<T>,
(Head, Tail::AppendResult): TupleList, (Head, Tail::AppendResult): TupleList,

View File

@ -22,8 +22,9 @@ use afl::mutators::HasMaxSize;
use afl::observers::StdMapObserver; use afl::observers::StdMapObserver;
use afl::stages::mutational::StdMutationalStage; use afl::stages::mutational::StdMutationalStage;
use afl::utils::StdRand; use afl::utils::StdRand;
use afl::tuples::tuple_list;
// const MAP_SIZE: usize = 65536; const MAP_SIZE: usize = 65536;
#[no_mangle] #[no_mangle]
extern "C" { extern "C" {
@ -59,18 +60,12 @@ pub extern "C" fn afl_libfuzzer_main() {
StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { __lafl_edges_map }, unsafe { StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { __lafl_edges_map }, unsafe {
__lafl_max_edges_size as usize __lafl_max_edges_size as usize
}); });
let edges_feedback = MaxMapFeedback::new_with_observer(&edges_observer); let edges_feedback = MaxMapFeedback::<u8, StdMapObserver<u8>>::new(&NAME_COV_MAP, MAP_SIZE);
let mut executor = InMemoryExecutor::new(harness); let executor = InMemoryExecutor::new(harness, tuple_list!(edges_observer));
let mut state = State::new(); let mut state = State::new(tuple_list!(edges_feedback));
executor.add_observer(Box::new(edges_observer));
state.add_feedback(Box::new(edges_feedback));
let mut engine = Engine::new(executor); let mut engine = Engine::new(executor);
let mut mutator = HavocBytesMutator::new_default();
mutator.set_max_size(4096);
let stage = StdMutationalStage::new(mutator);
state state
.generate_initial_inputs( .generate_initial_inputs(
@ -83,9 +78,11 @@ pub extern "C" fn afl_libfuzzer_main() {
) )
.expect("Failed to load initial inputs"); .expect("Failed to load initial inputs");
let mut fuzzer = StdFuzzer::new(); let mut mutator = HavocBytesMutator::new_default();
mutator.set_max_size(4096);
fuzzer.add_stage(Box::new(stage)); let stage = StdMutationalStage::new(mutator);
let mut fuzzer = StdFuzzer::new(tuple_list!(stage));
fuzzer fuzzer
.fuzz_loop(&mut rand, &mut state, &mut corpus, &mut engine, &mut events) .fuzz_loop(&mut rand, &mut state, &mut corpus, &mut engine, &mut events)