scheduler half finished

This commit is contained in:
Andrea Fioraldi 2021-02-28 23:22:18 +01:00
parent 0f40ac05d4
commit 3aa9439e80
5 changed files with 45 additions and 24 deletions

View File

@ -7,7 +7,7 @@ use libafl::{
bolts::{shmem::UnixShMem, tuples::tuple_list}, bolts::{shmem::UnixShMem, tuples::tuple_list},
corpus::{ corpus::{
Corpus, InMemoryCorpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, Corpus, InMemoryCorpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus,
RandCorpusScheduler, RandCorpusScheduler,QueueCorpusScheduler
}, },
events::setup_restarting_mgr, events::setup_restarting_mgr,
executors::{inprocess::InProcessExecutor, Executor, ExitKind}, executors::{inprocess::InProcessExecutor, Executor, ExitKind},
@ -119,8 +119,8 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
let stage = StdMutationalStage::new(mutator); let stage = StdMutationalStage::new(mutator);
// A fuzzer with just one stage and a minimization+queue policy to get testcasess from the corpus // A fuzzer with just one stage and a minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(RandCorpusScheduler::new()); //let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(RandCorpusScheduler::new());
//let scheduler = RandCorpusScheduler::new(); let scheduler = QueueCorpusScheduler::new();
let fuzzer = StdFuzzer::new(scheduler, tuple_list!(stage)); let fuzzer = StdFuzzer::new(scheduler, tuple_list!(stage));
// Create the executor for an in-process function with just one observer for edge coverage // Create the executor for an in-process function with just one observer for edge coverage
@ -140,6 +140,8 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
} }
} }
std::thread::sleep_ms(2000);
// 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

View File

@ -179,6 +179,9 @@ where
} }
pub fn cull(&self, state: &mut S) -> Result<(), Error> { pub fn cull(&self, state: &mut S) -> Result<(), Error> {
if state.metadatas().get::<TopRatedsMetadata>().is_none() {
return Ok(());
}
let mut acc = HashSet::new(); let mut acc = HashSet::new();
let top_rated = state.metadatas().get::<TopRatedsMetadata>().unwrap(); let top_rated = state.metadatas().get::<TopRatedsMetadata>().unwrap();

View File

@ -281,7 +281,7 @@ 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)?.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");
} }

View File

@ -55,7 +55,7 @@ where
.clone(); .clone();
self.mutator().mutate(state, &mut input_mut, i as i32)?; self.mutator().mutate(state, &mut input_mut, i as i32)?;
let fitness = state.evaluate_input(input_mut, executor, manager)?; let fitness = state.evaluate_input(input_mut, executor, manager, scheduler)?;
self.mutator().post_exec(state, fitness, i as i32)?; self.mutator().post_exec(state, fitness, i as i32)?;
} }

View File

@ -10,7 +10,7 @@ use std::{
use crate::{ use crate::{
bolts::serdeany::{SerdeAny, SerdeAnyMap}, bolts::serdeany::{SerdeAny, SerdeAnyMap},
corpus::{Corpus, Testcase}, corpus::{Corpus, Testcase, CorpusScheduler},
events::{Event, EventManager, LogSeverity}, events::{Event, EventManager, LogSeverity},
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
feedbacks::FeedbacksTuple, feedbacks::FeedbacksTuple,
@ -175,7 +175,10 @@ 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(&mut self, input: &I, fitness: u32) -> Result<Option<usize>, Error>; fn add_if_interesting<CS>(&mut self, input: &I, fitness: u32, scheduler: &CS) -> Result<Option<usize>, Error>
where
CS: CorpusScheduler<I, Self>,
Self: Sized;
} }
/// Evaluate an input modyfing the state of the fuzzer and returning a fitness /// Evaluate an input modyfing the state of the fuzzer and returning a fitness
@ -184,16 +187,18 @@ where
I: Input, I: Input,
{ {
/// Runs the input and triggers observers and feedback /// Runs the input and triggers observers and feedback
fn evaluate_input<E, EM, OT>( fn evaluate_input<CS, E, EM, OT>(
&mut self, &mut self,
input: I, input: I,
executor: &mut E, executor: &mut E,
event_mgr: &mut EM, manager: &mut EM,
scheduler: &CS,
) -> Result<u32, Error> ) -> Result<u32, Error>
where 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>;
} }
/// The state a fuzz run. /// The state a fuzz run.
@ -450,10 +455,15 @@ 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(&mut self, input: &I, fitness: u32) -> Result<Option<usize>, Error> { fn add_if_interesting<CS>(&mut self, input: &I, fitness: u32, scheduler: &CS) -> Result<Option<usize>, Error>
where
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)?;
Ok(Some(self.corpus.add(testcase)?)) // TODO scheduler hook let idx = self.corpus.add(testcase)?;
scheduler.on_add(self, idx)?;
Ok(Some(idx))
} else { } else {
self.discard_feedbacks_metadata(input)?; self.discard_feedbacks_metadata(input)?;
Ok(None) Ok(None)
@ -472,18 +482,20 @@ where
{ {
/// Process one input, adding to the respective corpuses if needed and firing the right events /// Process one input, adding to the respective corpuses if needed and firing the right events
#[inline] #[inline]
fn evaluate_input<E, EM, OT>( fn evaluate_input<CS, E, EM, OT>(
&mut self, &mut self,
// TODO probably we can take a ref to input and pass a cloned one to add_if_interesting // TODO probably we can take a ref to input and pass a cloned one to add_if_interesting
input: I, input: I,
executor: &mut E, executor: &mut E,
manager: &mut EM, manager: &mut EM,
scheduler: &CS,
) -> Result<u32, Error> ) -> Result<u32, Error>
where where
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
C: Corpus<I>, C: Corpus<I>,
EM: EventManager<I, Self>, EM: EventManager<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();
@ -493,7 +505,7 @@ where
self.solutions_mut().add(Testcase::new(input.clone()))?; self.solutions_mut().add(Testcase::new(input.clone()))?;
} }
if !self.add_if_interesting(&input, fitness)?.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,
@ -521,17 +533,18 @@ where
SC: Corpus<BytesInput>, SC: Corpus<BytesInput>,
OFT: FeedbacksTuple<BytesInput>, OFT: FeedbacksTuple<BytesInput>,
{ {
pub fn load_from_directory<E, OT, EM>( pub fn load_from_directory<CS, E, OT, EM>(
&mut self, &mut self,
executor: &mut E, executor: &mut E,
manager: &mut EM, manager: &mut EM,
scheduler: &CS,
in_dir: &Path, in_dir: &Path,
) -> Result<(), Error> ) -> Result<(), Error>
where where
C: Corpus<BytesInput>,
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>
{ {
for entry in fs::read_dir(in_dir)? { for entry in fs::read_dir(in_dir)? {
let entry = entry?; let entry = entry?;
@ -549,34 +562,35 @@ 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)?.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 {
println!("File {:?} is a solution, however will be not considered as it is an initial testcase.", &path); println!("File {:?} is a solution, however will be not considered as it is an initial testcase.", &path);
} }
} else if attr.is_dir() { } else if attr.is_dir() {
self.load_from_directory(executor, manager, &path)?; self.load_from_directory(executor, manager, scheduler, &path)?;
} }
} }
Ok(()) Ok(())
} }
pub fn load_initial_inputs<E, OT, EM>( pub fn load_initial_inputs<CS, E, OT, EM>(
&mut self, &mut self,
executor: &mut E, executor: &mut E,
manager: &mut EM, manager: &mut EM,
scheduler: &CS,
in_dirs: &[PathBuf], in_dirs: &[PathBuf],
) -> Result<(), Error> ) -> Result<(), Error>
where where
C: Corpus<BytesInput>,
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>,
{ {
for in_dir in in_dirs { for in_dir in in_dirs {
self.load_from_directory(executor, manager, in_dir)?; self.load_from_directory(executor, manager, scheduler, in_dir)?;
} }
manager.fire( manager.fire(
self, self,
@ -634,11 +648,12 @@ where
Ok((fitness, is_solution)) Ok((fitness, is_solution))
} }
pub fn generate_initial_inputs<G, E, OT, EM>( pub fn generate_initial_inputs<CS, G, E, OT, EM>(
&mut self, &mut self,
executor: &mut E, executor: &mut E,
generator: &mut G, generator: &mut G,
manager: &mut EM, manager: &mut EM,
scheduler: &CS,
num: usize, num: usize,
) -> Result<(), Error> ) -> Result<(), Error>
where where
@ -647,11 +662,12 @@ 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>
{ {
let mut added = 0; let mut added = 0;
for _ in 0..num { for _ in 0..num {
let input = generator.generate(self.rand_mut())?; let input = generator.generate(self.rand_mut())?;
let fitness = self.evaluate_input(input, executor, manager)?; let fitness = self.evaluate_input(input, executor, manager, scheduler)?;
if fitness > 0 { if fitness > 0 {
added += 1; added += 1;
} }