additional executors

This commit is contained in:
Andrea Fioraldi 2020-12-11 21:57:29 +01:00
parent 6d844e1fa3
commit 299634ccce
8 changed files with 156 additions and 73 deletions

View File

@ -7,12 +7,13 @@ use hashbrown::HashMap;
use crate::corpus::{Corpus, Testcase};
use crate::events::{Event, EventManager};
use crate::executors::{Executor, HasObservers};
use crate::executors::{Executor, ExecutorsTuple, HasObservers};
use crate::feedbacks::FeedbacksTuple;
use crate::generators::Generator;
use crate::inputs::Input;
use crate::observers::ObserversTuple;
use crate::stages::StagesTuple;
use crate::tuples::{tuple_list, tuple_list_type};
use crate::utils::{current_milliseconds, Rand};
use crate::AflError;
@ -179,12 +180,12 @@ where
}
}
pub fn generate_initial_inputs<G, C, E, OT, EM>(
pub fn generate_initial_inputs<G, C, E, OT, ET, EM>(
&mut self,
rand: &mut R,
corpus: &mut C,
generator: &mut G,
engine: &mut Engine<E, OT, I>,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
num: usize,
) -> Result<(), AflError>
@ -193,6 +194,7 @@ where
C: Corpus<I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<I>,
EM: EventManager<C, E, OT, FT, I, R>,
{
let mut added = 0;
@ -226,49 +228,71 @@ where
}
}
pub struct Engine<E, OT, I>
pub struct Engine<E, OT, ET, I>
where
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<I>,
I: Input,
{
executor: E,
main_executor: E,
additional_executors: ET,
phantom: PhantomData<(OT, I)>,
}
impl<E, OT, I> Engine<E, OT, I>
impl<E, OT, ET, I> Engine<E, OT, ET, I>
where
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<I>,
I: Input,
{
/// Return the executor
pub fn executor(&self) -> &E {
&self.executor
&self.main_executor
}
/// Return the executor (mutable)
pub fn executor_mut(&mut self) -> &mut E {
&mut self.executor
&mut self.main_executor
}
// TODO additional executors, Vec<Box<dyn Executor<I>>>
pub fn additional_executors(&self) -> &ET {
&self.additional_executors
}
pub fn new(executor: E) -> Self {
pub fn additional_executors_mut(&mut self) -> &mut ET {
&mut self.additional_executors
}
pub fn with_executors(main_executor: E, additional_executors: ET) -> Self {
Self {
executor: executor,
main_executor: main_executor,
additional_executors: additional_executors,
phantom: PhantomData,
}
}
}
pub trait Fuzzer<ST, EM, E, OT, FT, C, I, R>
impl<E, OT, I> Engine<E, OT, tuple_list_type!(), I>
where
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
I: Input,
{
pub fn new(main_executor: E) -> Self {
Self::with_executors(main_executor, tuple_list!())
}
}
pub trait Fuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -282,7 +306,7 @@ where
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
) -> Result<usize, AflError> {
let (_, idx) = corpus.next(rand)?;
@ -299,7 +323,7 @@ where
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
) -> Result<(), AflError> {
let mut last = current_milliseconds();
@ -317,29 +341,31 @@ where
}
}
pub struct StdFuzzer<ST, EM, E, OT, FT, C, I, R>
pub struct StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
{
stages: ST,
phantom: PhantomData<(EM, E, OT, FT, C, I, R)>,
phantom: PhantomData<(EM, E, OT, FT, ET, 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>
impl<ST, EM, E, OT, FT, ET, C, I, R> Fuzzer<ST, EM, E, OT, FT, ET, C, I, R>
for StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -353,13 +379,14 @@ where
}
}
impl<ST, EM, E, OT, FT, C, I, R> StdFuzzer<ST, EM, E, OT, FT, C, I, R>
impl<ST, EM, E, OT, FT, ET, C, I, R> StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -404,7 +431,7 @@ mod tests {
let testcase = Testcase::new(vec![0; 4]).into();
corpus.add(testcase);
let executor = InMemoryExecutor::<BytesInput, _>::new(harness, tuple_list!());
let executor = InMemoryExecutor::<BytesInput, _>::new("main", harness, tuple_list!());
let mut state = State::new(tuple_list!());
let mut events_manager = LoggerEventManager::new(stderr());

View File

@ -603,7 +603,7 @@ mod tests {
use crate::events::Event;
use crate::inputs::bytes::BytesInput;
use crate::observers::{Observer, ObserversTuple, StdMapObserver};
use crate::observers::StdMapObserver;
use crate::serde_anymap::{Ptr, PtrMut};
use crate::tuples::{tuple_list, tuple_list_type, MatchNameAndType, Named};

View File

@ -4,6 +4,7 @@ use core::ptr;
use crate::executors::{Executor, ExitKind, HasObservers};
use crate::inputs::{HasTargetBytes, Input};
use crate::observers::ObserversTuple;
use crate::tuples::Named;
use crate::AflError;
/// The (unsafe) pointer to the current inmem executor, for the current run.
@ -21,6 +22,7 @@ where
{
harness: HarnessFunction<I>,
observers: OT,
name: &'static str,
}
impl<I, OT> Executor<I> for InMemoryExecutor<I, OT>
@ -42,6 +44,16 @@ where
}
}
impl<I, OT> Named for InMemoryExecutor<I, OT>
where
I: Input + HasTargetBytes,
OT: ObserversTuple,
{
fn name(&self) -> &str {
self.name
}
}
impl<I, OT> HasObservers<OT> for InMemoryExecutor<I, OT>
where
I: Input + HasTargetBytes,
@ -63,7 +75,7 @@ where
I: Input + HasTargetBytes,
OT: ObserversTuple,
{
pub fn new(harness_fn: HarnessFunction<I>, observers: OT) -> Self {
pub fn new(name: &'static str, harness_fn: HarnessFunction<I>, observers: OT) -> Self {
#[cfg(feature = "std")]
unsafe {
os_signals::setup_crash_handlers::<I>();
@ -71,6 +83,7 @@ where
Self {
harness: harness_fn,
observers: observers,
name: name,
}
}
}
@ -178,7 +191,7 @@ mod tests {
use crate::executors::inmemory::InMemoryExecutor;
use crate::executors::{Executor, ExitKind};
use crate::inputs::{HasTargetBytes, Input, TargetBytes};
use crate::tuples::{tuple_list, tuple_list_type};
use crate::tuples::tuple_list;
use serde::{Deserialize, Serialize};
@ -204,7 +217,7 @@ mod tests {
#[test]
fn test_inmem_exec() {
let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop, tuple_list!());
let mut in_mem_executor = InMemoryExecutor::new("main", test_harness_fn_nop, tuple_list!());
let mut input = NopInput {};
assert!(in_mem_executor.run_target(&mut input).is_ok());
}

View File

@ -2,6 +2,7 @@ pub mod inmemory;
use crate::inputs::Input;
use crate::observers::ObserversTuple;
use crate::tuples::{MatchNameAndType, MatchType, Named, TupleList};
use crate::AflError;
/// How an execution finished.
@ -36,10 +37,43 @@ where
}
/// An executor takes the given inputs, and runs the harness/target.
pub trait Executor<I>
pub trait Executor<I>: Named
where
I: Input,
{
/// Instruct the target about the input and run
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError>;
}
pub trait ExecutorsTuple<I>: MatchType + MatchNameAndType
where
I: Input,
{
fn for_each(&self, f: fn(&dyn Executor<I>));
fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>));
}
impl<I> ExecutorsTuple<I> for ()
where
I: Input,
{
fn for_each(&self, _f: fn(&dyn Executor<I>)) {}
fn for_each_mut(&mut self, _f: fn(&mut dyn Executor<I>)) {}
}
impl<Head, Tail, I> ExecutorsTuple<I> for (Head, Tail)
where
Head: Executor<I> + 'static,
Tail: ExecutorsTuple<I> + TupleList,
I: Input,
{
fn for_each(&self, f: fn(&dyn Executor<I>)) {
f(&self.0);
self.1.for_each(f)
}
fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>)) {
f(&mut self.0);
self.1.for_each_mut(f)
}
}

View File

@ -1,5 +1,3 @@
use alloc::string::String;
use alloc::string::ToString;
use alloc::vec::Vec;
use core::marker::PhantomData;
use num::Integer;
@ -64,15 +62,15 @@ where
{
fn is_interesting_all<OT: ObserversTuple>(
&mut self,
input: &I,
observers: &OT,
_input: &I,
_observers: &OT,
) -> Result<u32, AflError> {
Ok(0)
}
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), AflError> {
fn append_metadata_all(&mut self, _testcase: &mut Testcase<I>) -> Result<(), AflError> {
Ok(())
}
fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError> {
fn discard_metadata_all(&mut self, _input: &I) -> Result<(), AflError> {
Ok(())
}
//fn for_each(&self, f: fn(&dyn Feedback<I>)) {}

View File

@ -4,22 +4,23 @@ pub use mutational::StdMutationalStage;
use crate::corpus::Corpus;
use crate::engines::{Engine, State};
use crate::events::EventManager;
use crate::executors::{Executor, HasObservers};
use crate::executors::{Executor, ExecutorsTuple, HasObservers};
use crate::feedbacks::FeedbacksTuple;
use crate::inputs::Input;
use crate::observers::ObserversTuple;
use crate::tuples::{MatchType, TupleList};
use crate::tuples::TupleList;
use crate::utils::Rand;
use crate::AflError;
/// A stage is one step in the fuzzing process.
/// Multiple stages will be scheduled one by one for each input.
pub trait Stage<EM, E, OT, FT, C, I, R>
pub trait Stage<EM, E, OT, FT, ET, C, I, R>
where
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -30,18 +31,19 @@ where
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError>;
}
pub trait StagesTuple<EM, E, OT, FT, C, I, R>
pub trait StagesTuple<EM, E, OT, FT, ET, C, I, R>
where
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -51,47 +53,50 @@ where
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
engine: &mut Engine<E, OT, ET, 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>));
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, ET, C, I, R>));
fn for_each_mut(&mut self, f: fn(&mut dyn Stage<EM, E, OT, FT, ET, C, I, R>));
}
impl<EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for ()
impl<EM, E, OT, FT, ET, C, I, R> StagesTuple<EM, E, OT, FT, ET, C, I, R> for ()
where
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<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,
_rand: &mut R,
_state: &mut State<I, R, FT>,
_corpus: &mut C,
_engine: &mut Engine<E, OT, ET, 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>)) {}
fn for_each(&self, _f: fn(&dyn Stage<EM, E, OT, FT, ET, C, I, R>)) {}
fn for_each_mut(&mut self, _f: fn(&mut dyn Stage<EM, E, OT, FT, ET, C, I, R>)) {}
}
impl<Head, Tail, EM, E, OT, FT, C, I, R> StagesTuple<EM, E, OT, FT, C, I, R> for (Head, Tail)
impl<Head, Tail, EM, E, OT, FT, ET, C, I, R> StagesTuple<EM, E, OT, FT, ET, 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,
Head: Stage<EM, E, OT, FT, ET, C, I, R>,
Tail: StagesTuple<EM, E, OT, FT, ET, C, I, R> + TupleList,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -101,7 +106,7 @@ where
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError> {
@ -111,12 +116,12 @@ where
.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, ET, 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>)) {
fn for_each_mut(&mut self, f: fn(&mut dyn Stage<EM, E, OT, FT, ET, C, I, R>)) {
f(&mut self.0);
self.1.for_each_mut(f)
}

View File

@ -1,7 +1,7 @@
use core::marker::PhantomData;
use crate::events::EventManager;
use crate::executors::{Executor, HasObservers};
use crate::executors::{Executor, ExecutorsTuple, HasObservers};
use crate::feedbacks::FeedbacksTuple;
use crate::inputs::Input;
use crate::mutators::Mutator;
@ -19,13 +19,15 @@ use crate::serde_anymap::{Ptr, PtrMut};
/// A Mutational stage is the stage in a fuzzing run that mutates inputs.
/// Mutational stages will usually have a range of mutations that are
/// being applied to the input one by one, between executions.
pub trait MutationalStage<M, EM, E, OT, FT, C, I, R>: Stage<EM, E, OT, FT, C, I, R>
pub trait MutationalStage<M, EM, E, OT, FT, ET, C, I, R>:
Stage<EM, E, OT, FT, ET, C, I, R>
where
M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -49,7 +51,7 @@ where
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError> {
@ -86,29 +88,31 @@ where
}
/// The default mutational stage
pub struct StdMutationalStage<M, EM, E, OT, FT, C, I, R>
pub struct StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where
M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
{
mutator: M,
phantom: PhantomData<(EM, E, OT, FT, C, I, R)>,
phantom: PhantomData<(EM, E, OT, FT, ET, 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, ET, C, I, R> MutationalStage<M, EM, E, OT, FT, ET, C, I, R>
for StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where
M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -126,14 +130,15 @@ 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, ET, C, I, R> Stage<EM, E, OT, FT, ET, C, I, R>
for StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where
M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,
@ -144,7 +149,7 @@ where
rand: &mut R,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, I>,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError> {
@ -152,13 +157,14 @@ where
}
}
impl<M, EM, E, OT, FT, C, I, R> StdMutationalStage<M, EM, E, OT, FT, C, I, R>
impl<M, EM, E, OT, FT, ET, C, I, R> StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where
M: Mutator<C, I, R>,
EM: EventManager<C, E, OT, FT, I, R>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
ET: ExecutorsTuple<I>,
C: Corpus<I, R>,
I: Input,
R: Rand,

View File

@ -65,10 +65,10 @@ pub trait MatchType {
}
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)) {
()
}
}
@ -103,10 +103,10 @@ pub trait MatchNameAndType {
}
impl MatchNameAndType for () {
fn match_name_type<T: 'static>(&self, name: &'static str) -> Option<&T> {
fn match_name_type<T: 'static>(&self, _name: &'static str) -> Option<&T> {
None
}
fn match_name_type_mut<T: 'static>(&mut self, name: &'static str) -> Option<&mut T> {
fn match_name_type_mut<T: 'static>(&mut self, _name: &'static str) -> Option<&mut T> {
None
}
}