This commit is contained in:
Andrea Fioraldi 2021-03-01 10:04:59 +01:00
parent 9ba508f77a
commit dc39a5591a
8 changed files with 95 additions and 37 deletions

View File

@ -6,12 +6,13 @@ use std::{env, path::PathBuf};
use libafl::{ use libafl::{
bolts::{shmem::UnixShMem, tuples::tuple_list}, bolts::{shmem::UnixShMem, tuples::tuple_list},
corpus::{ corpus::{
Corpus, InMemoryCorpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler Corpus, InMemoryCorpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus,
QueueCorpusScheduler,
}, },
events::setup_restarting_mgr, events::setup_restarting_mgr,
executors::{inprocess::InProcessExecutor, Executor, ExitKind}, executors::{inprocess::InProcessExecutor, Executor, ExitKind},
feedbacks::{CrashFeedback, MaxMapFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer, HasCorpusScheduler}, fuzzer::{Fuzzer, HasCorpusScheduler, StdFuzzer},
inputs::Input, inputs::Input,
mutators::scheduled::HavocBytesMutator, mutators::scheduled::HavocBytesMutator,
mutators::token_mutations::TokensMetadata, mutators::token_mutations::TokensMetadata,
@ -91,7 +92,11 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
// Corpus that will be evolved, we keep it in memory for performance // Corpus that will be evolved, we keep it in memory for performance
InMemoryCorpus::new(), InMemoryCorpus::new(),
// Feedbacks to rate the interestingness of an input // Feedbacks to rate the interestingness of an input
tuple_list!(MaxMapFeedback::new_with_observer_track(&edges_observer, true, false)), tuple_list!(MaxMapFeedback::new_with_observer_track(
&edges_observer,
true,
false
)),
// Corpus in which we store solutions (crashes in this example), // Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer // on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir), OnDiskCorpus::new(objective_dir),
@ -142,7 +147,12 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
// In case the corpus is empty (on first run), reset // In case the corpus is empty (on first run), reset
if state.corpus().count() < 1 { if state.corpus().count() < 1 {
state state
.load_initial_inputs(&mut executor, &mut restarting_mgr, fuzzer.scheduler(), &corpus_dirs) .load_initial_inputs(
&mut executor,
&mut restarting_mgr,
fuzzer.scheduler(),
&corpus_dirs,
)
.expect(&format!( .expect(&format!(
"Failed to load initial corpus at {:?}", "Failed to load initial corpus at {:?}",
&corpus_dirs &corpus_dirs

View File

@ -17,12 +17,12 @@ use crate::{
llmp::{self, LlmpClient, LlmpClientDescription, Tag}, llmp::{self, LlmpClient, LlmpClientDescription, Tag},
shmem::ShMem, shmem::ShMem,
}, },
corpus::CorpusScheduler,
events::{BrokerEventResult, Event, EventManager}, events::{BrokerEventResult, Event, EventManager},
executors::ExitKind, executors::ExitKind,
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
inputs::Input, inputs::Input,
observers::ObserversTuple, observers::ObserversTuple,
corpus::CorpusScheduler,
state::IfInteresting, state::IfInteresting,
stats::Stats, stats::Stats,
Error, Error,
@ -284,7 +284,10 @@ where
// TODO include ExitKind in NewTestcase // TODO include ExitKind in NewTestcase
let fitness = state.is_interesting(&input, &observers, ExitKind::Ok)?; let fitness = state.is_interesting(&input, &observers, ExitKind::Ok)?;
if fitness > 0 { if fitness > 0 {
if !state.add_if_interesting(&input, fitness, scheduler)?.is_none() { if !state
.add_if_interesting(&input, fitness, scheduler)?
.is_none()
{
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Added received Testcase"); println!("Added received Testcase");
} }
@ -318,11 +321,16 @@ where
} }
} }
fn process<CS, E, OT>(&mut self, state: &mut S, executor: &mut E, scheduler: &CS) -> Result<usize, Error> fn process<CS, E, OT>(
&mut self,
state: &mut S,
executor: &mut E,
scheduler: &CS,
) -> Result<usize, Error>
where where
CS: CorpusScheduler<I, S>, CS: CorpusScheduler<I, S>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple OT: ObserversTuple,
{ {
// TODO: Get around local event copy by moving handle_in_client // TODO: Get around local event copy by moving handle_in_client
let mut events = vec![]; let mut events = vec![];
@ -430,11 +438,16 @@ where
.send_buf(_LLMP_TAG_RESTART, &state_corpus_serialized) .send_buf(_LLMP_TAG_RESTART, &state_corpus_serialized)
} }
fn process<CS, E, OT>(&mut self, state: &mut S, executor: &mut E, scheduler: &CS) -> Result<usize, Error> fn process<CS, E, OT>(
&mut self,
state: &mut S,
executor: &mut E,
scheduler: &CS,
) -> Result<usize, Error>
where where
CS: CorpusScheduler<I, S>, CS: CorpusScheduler<I, S>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple OT: ObserversTuple,
{ {
self.llmp_mgr.process(state, executor, scheduler) self.llmp_mgr.process(state, executor, scheduler)
} }

View File

@ -10,9 +10,9 @@ use core::{fmt, marker::PhantomData, time::Duration};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::CorpusScheduler,
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
inputs::Input, inputs::Input,
corpus::{ CorpusScheduler},
observers::ObserversTuple, observers::ObserversTuple,
Error, Error,
}; };
@ -160,7 +160,12 @@ where
/// 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<CS, E, OT>(&mut self, state: &mut S, executor: &mut E, scheduler: &CS) -> Result<usize, Error> fn process<CS, E, OT>(
&mut self,
state: &mut S,
executor: &mut E,
scheduler: &CS,
) -> Result<usize, Error>
where where
CS: CorpusScheduler<I, S>, CS: CorpusScheduler<I, S>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
@ -205,7 +210,12 @@ impl<I, S> EventManager<I, S> for NopEventManager<I, S>
where where
I: Input, I: Input,
{ {
fn process<CS, E, OT>(&mut self, _state: &mut S, _executor: &mut E, _scheduler: &CS) -> Result<usize, Error> fn process<CS, E, OT>(
&mut self,
_state: &mut S,
_executor: &mut E,
_scheduler: &CS,
) -> Result<usize, Error>
where where
CS: CorpusScheduler<I, S>, CS: CorpusScheduler<I, S>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,

View File

@ -3,11 +3,11 @@ use alloc::{string::ToString, vec::Vec};
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::{ use crate::{
corpus::CorpusScheduler,
events::{BrokerEventResult, Event, EventManager}, events::{BrokerEventResult, Event, EventManager},
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
inputs::Input, inputs::Input,
observers::ObserversTuple, observers::ObserversTuple,
corpus::CorpusScheduler,
stats::Stats, stats::Stats,
Error, Error,
}; };
@ -31,11 +31,16 @@ where
I: Input, I: Input,
ST: Stats, //CE: CustomEvent<I, OT>, ST: Stats, //CE: CustomEvent<I, OT>,
{ {
fn process<CS, E, OT>(&mut self, state: &mut S, _executor: &mut E, _scheduler: &CS) -> Result<usize, Error> fn process<CS, E, OT>(
&mut self,
state: &mut S,
_executor: &mut E,
_scheduler: &CS,
) -> Result<usize, Error>
where where
CS: CorpusScheduler<I, S>, CS: CorpusScheduler<I, S>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple OT: ObserversTuple,
{ {
let count = self.events.len(); let count = self.events.len();
while self.events.len() > 0 { while self.events.len() > 0 {

View File

@ -105,7 +105,8 @@ where
fn fuzz_one(&self, state: &mut S, executor: &mut E, manager: &mut EM) -> Result<usize, Error> { fn fuzz_one(&self, state: &mut S, executor: &mut E, manager: &mut EM) -> Result<usize, Error> {
let idx = self.scheduler().next(state)?; let idx = self.scheduler().next(state)?;
self.stages().perform_all(state, executor, manager, self.scheduler(), idx)?; self.stages()
.perform_all(state, executor, manager, self.scheduler(), idx)?;
manager.process(state, executor, self.scheduler())?; manager.process(state, executor, self.scheduler())?;
Ok(idx) Ok(idx)

View File

@ -7,7 +7,7 @@ use crate::{
/// 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<CS, E, EM, I, S> pub trait Stage<CS, E, EM, I, S>
where where
EM: EventManager<I, S>, EM: EventManager<I, S>,
E: Executor<I>, E: Executor<I>,
@ -24,7 +24,7 @@ where
) -> Result<(), Error>; ) -> Result<(), Error>;
} }
pub trait StagesTuple<CS, E, EM, I, S> pub trait StagesTuple<CS, E, EM, I, S>
where where
EM: EventManager<I, S>, EM: EventManager<I, S>,
E: Executor<I>, E: Executor<I>,
@ -40,7 +40,7 @@ where
) -> Result<(), Error>; ) -> Result<(), Error>;
} }
impl<CS, E, EM, I, S> StagesTuple<CS, E, EM, I, S> for () impl<CS, E, EM, I, S> StagesTuple<CS, E, EM, I, S> for ()
where where
EM: EventManager<I, S>, EM: EventManager<I, S>,
E: Executor<I>, E: Executor<I>,
@ -51,10 +51,10 @@ where
} }
} }
impl<Head, Tail, CS, E, EM, I, S> StagesTuple<CS, E, EM, I, S> for (Head, Tail) impl<Head, Tail, CS, E, EM, I, S> StagesTuple<CS, E, EM, I, S> for (Head, Tail)
where where
Head: Stage<CS, E, EM, I, S>, Head: Stage<CS, E, EM, I, S>,
Tail: StagesTuple<CS, E, EM, I, S> + TupleList, Tail: StagesTuple<CS, E, EM, I, S> + TupleList,
EM: EventManager<I, S>, EM: EventManager<I, S>,
E: Executor<I>, E: Executor<I>,
I: Input, I: Input,
@ -67,7 +67,9 @@ where
scheduler: &CS, scheduler: &CS,
corpus_idx: usize, corpus_idx: usize,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.0.perform(state, executor, manager, scheduler, corpus_idx)?; self.0
self.1.perform_all(state, executor, manager, scheduler, corpus_idx) .perform(state, executor, manager, scheduler, corpus_idx)?;
self.1
.perform_all(state, executor, manager, scheduler, corpus_idx)
} }
} }

View File

@ -27,7 +27,7 @@ where
EM: EventManager<I, S>, EM: EventManager<I, S>,
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
CS: CorpusScheduler<I, S> CS: CorpusScheduler<I, S>,
{ {
/// The mutator registered for this stage /// The mutator registered for this stage
fn mutator(&self) -> &M; fn mutator(&self) -> &M;
@ -116,7 +116,8 @@ where
} }
} }
impl<C, CS, E, EM, I, M, OT, R, S> Stage<CS, E, EM, I, S> for StdMutationalStage<C, CS, E, EM, I, M, OT, R, S> impl<C, CS, E, EM, I, M, OT, R, S> Stage<CS, E, EM, I, S>
for StdMutationalStage<C, CS, E, EM, I, M, OT, R, S>
where where
M: Mutator<I, S>, M: Mutator<I, S>,
I: Input, I: Input,

View File

@ -10,7 +10,7 @@ use std::{
use crate::{ use crate::{
bolts::serdeany::{SerdeAny, SerdeAnyMap}, bolts::serdeany::{SerdeAny, SerdeAnyMap},
corpus::{Corpus, Testcase, CorpusScheduler}, corpus::{Corpus, CorpusScheduler, Testcase},
events::{Event, EventManager, LogSeverity}, events::{Event, EventManager, LogSeverity},
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
feedbacks::FeedbacksTuple, feedbacks::FeedbacksTuple,
@ -175,7 +175,12 @@ where
OT: ObserversTuple; OT: ObserversTuple;
/// Adds this input to the corpus, if it's intersting, and return the index /// Adds this input to the corpus, if it's intersting, and return the index
fn add_if_interesting<CS>(&mut self, input: &I, fitness: u32, scheduler: &CS) -> Result<Option<usize>, Error> fn add_if_interesting<CS>(
&mut self,
input: &I,
fitness: u32,
scheduler: &CS,
) -> Result<Option<usize>, Error>
where where
CS: CorpusScheduler<I, Self>, CS: CorpusScheduler<I, Self>,
Self: Sized; Self: Sized;
@ -455,9 +460,14 @@ where
/// Adds this input to the corpus, if it's intersting, and return the index /// Adds this input to the corpus, if it's intersting, and return the index
#[inline] #[inline]
fn add_if_interesting<CS>(&mut self, input: &I, fitness: u32, scheduler: &CS) -> Result<Option<usize>, Error> fn add_if_interesting<CS>(
&mut self,
input: &I,
fitness: u32,
scheduler: &CS,
) -> Result<Option<usize>, Error>
where 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 testcase = self.testcase_with_feedbacks_metadata(input.clone(), fitness)?;
@ -495,7 +505,7 @@ where
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I>, C: Corpus<I>,
EM: EventManager<I, Self>, EM: EventManager<I, Self>,
CS: CorpusScheduler<I, Self> CS: CorpusScheduler<I, Self>,
{ {
let (fitness, is_solution) = self.execute_input(&input, executor, manager)?; let (fitness, is_solution) = self.execute_input(&input, executor, manager)?;
let observers = executor.observers(); let observers = executor.observers();
@ -505,7 +515,10 @@ where
self.solutions_mut().add(Testcase::new(input.clone()))?; self.solutions_mut().add(Testcase::new(input.clone()))?;
} }
if !self.add_if_interesting(&input, fitness, scheduler)?.is_none() { if !self
.add_if_interesting(&input, fitness, scheduler)?
.is_none()
{
let observers_buf = manager.serialize_observers(observers)?; let observers_buf = manager.serialize_observers(observers)?;
manager.fire( manager.fire(
self, self,
@ -544,7 +557,7 @@ where
E: Executor<BytesInput> + HasObservers<OT>, E: Executor<BytesInput> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
EM: EventManager<BytesInput, Self>, EM: EventManager<BytesInput, Self>,
CS: CorpusScheduler<BytesInput, Self> CS: CorpusScheduler<BytesInput, Self>,
{ {
for entry in fs::read_dir(in_dir)? { for entry in fs::read_dir(in_dir)? {
let entry = entry?; let entry = entry?;
@ -562,7 +575,10 @@ where
let bytes = fs::read(&path)?; let bytes = fs::read(&path)?;
let input = BytesInput::new(bytes); let input = BytesInput::new(bytes);
let (fitness, is_solution) = self.execute_input(&input, executor, manager)?; let (fitness, is_solution) = self.execute_input(&input, executor, manager)?;
if self.add_if_interesting(&input, fitness, scheduler)?.is_none() { if self
.add_if_interesting(&input, fitness, scheduler)?
.is_none()
{
println!("File {:?} was not interesting, skipped.", &path); println!("File {:?} was not interesting, skipped.", &path);
} }
if is_solution { if is_solution {
@ -662,7 +678,7 @@ where
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
EM: EventManager<I, Self>, EM: EventManager<I, Self>,
CS: CorpusScheduler<I, Self> CS: CorpusScheduler<I, Self>,
{ {
let mut added = 0; let mut added = 0;
for _ in 0..num { for _ in 0..num {