From 3aa9439e80e25ef8a45e67258bbbab999ffd4ca1 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Sun, 28 Feb 2021 23:22:18 +0100 Subject: [PATCH] scheduler half finished --- fuzzers/libfuzzer_libpng/src/fuzzer.rs | 10 +++-- libafl/src/corpus/minimizer.rs | 3 ++ libafl/src/events/llmp.rs | 2 +- libafl/src/stages/mutational.rs | 2 +- libafl/src/state/mod.rs | 52 +++++++++++++++++--------- 5 files changed, 45 insertions(+), 24 deletions(-) diff --git a/fuzzers/libfuzzer_libpng/src/fuzzer.rs b/fuzzers/libfuzzer_libpng/src/fuzzer.rs index 0586583013..9e510e66d0 100644 --- a/fuzzers/libfuzzer_libpng/src/fuzzer.rs +++ b/fuzzers/libfuzzer_libpng/src/fuzzer.rs @@ -7,7 +7,7 @@ use libafl::{ bolts::{shmem::UnixShMem, tuples::tuple_list}, corpus::{ Corpus, InMemoryCorpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, - RandCorpusScheduler, + RandCorpusScheduler,QueueCorpusScheduler }, events::setup_restarting_mgr, executors::{inprocess::InProcessExecutor, Executor, ExitKind}, @@ -119,8 +119,8 @@ fn fuzz(corpus_dirs: Vec, objective_dir: PathBuf, broker_port: u16) -> let stage = StdMutationalStage::new(mutator); // 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 = RandCorpusScheduler::new(); + //let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(RandCorpusScheduler::new()); + let scheduler = QueueCorpusScheduler::new(); let fuzzer = StdFuzzer::new(scheduler, tuple_list!(stage)); // Create the executor for an in-process function with just one observer for edge coverage @@ -139,6 +139,8 @@ fn fuzz(corpus_dirs: Vec, objective_dir: PathBuf, broker_port: u16) -> println!("Warning: LLVMFuzzerInitialize failed with -1") } } + + std::thread::sleep_ms(2000); // In case the corpus is empty (on first run), reset if state.corpus().count() < 1 { @@ -150,7 +152,7 @@ fn fuzz(corpus_dirs: Vec, objective_dir: PathBuf, broker_port: u16) -> )); println!("We imported {} inputs from disk.", state.corpus().count()); } - + fuzzer.fuzz_loop(&mut state, &mut executor, &mut restarting_mgr)?; // Never reached diff --git a/libafl/src/corpus/minimizer.rs b/libafl/src/corpus/minimizer.rs index 9c49aa3293..98b3ab9495 100644 --- a/libafl/src/corpus/minimizer.rs +++ b/libafl/src/corpus/minimizer.rs @@ -179,6 +179,9 @@ where } pub fn cull(&self, state: &mut S) -> Result<(), Error> { + if state.metadatas().get::().is_none() { + return Ok(()); + } let mut acc = HashSet::new(); let top_rated = state.metadatas().get::().unwrap(); diff --git a/libafl/src/events/llmp.rs b/libafl/src/events/llmp.rs index a9c83155d7..2c2af29130 100644 --- a/libafl/src/events/llmp.rs +++ b/libafl/src/events/llmp.rs @@ -281,7 +281,7 @@ where // TODO include ExitKind in NewTestcase let fitness = state.is_interesting(&input, &observers, ExitKind::Ok)?; 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")] println!("Added received Testcase"); } diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 59a283f893..bf891f510f 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -55,7 +55,7 @@ where .clone(); 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)?; } diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index ef028d0401..7467fe3cd7 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -10,7 +10,7 @@ use std::{ use crate::{ bolts::serdeany::{SerdeAny, SerdeAnyMap}, - corpus::{Corpus, Testcase}, + corpus::{Corpus, Testcase, CorpusScheduler}, events::{Event, EventManager, LogSeverity}, executors::{Executor, ExitKind, HasObservers}, feedbacks::FeedbacksTuple, @@ -175,7 +175,10 @@ where OT: ObserversTuple; /// 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, Error>; + fn add_if_interesting(&mut self, input: &I, fitness: u32, scheduler: &CS) -> Result, Error> + where + CS: CorpusScheduler, + Self: Sized; } /// Evaluate an input modyfing the state of the fuzzer and returning a fitness @@ -184,16 +187,18 @@ where I: Input, { /// Runs the input and triggers observers and feedback - fn evaluate_input( + fn evaluate_input( &mut self, input: I, executor: &mut E, - event_mgr: &mut EM, + manager: &mut EM, + scheduler: &CS, ) -> Result where E: Executor + HasObservers, OT: ObserversTuple, - EM: EventManager; + EM: EventManager, + CS: CorpusScheduler; } /// The state a fuzz run. @@ -450,10 +455,15 @@ where /// Adds this input to the corpus, if it's intersting, and return the index #[inline] - fn add_if_interesting(&mut self, input: &I, fitness: u32) -> Result, Error> { + fn add_if_interesting(&mut self, input: &I, fitness: u32, scheduler: &CS) -> Result, Error> + where + CS: CorpusScheduler + { if fitness > 0 { 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 { self.discard_feedbacks_metadata(input)?; Ok(None) @@ -472,18 +482,20 @@ where { /// Process one input, adding to the respective corpuses if needed and firing the right events #[inline] - fn evaluate_input( + fn evaluate_input( &mut self, // TODO probably we can take a ref to input and pass a cloned one to add_if_interesting input: I, executor: &mut E, manager: &mut EM, + scheduler: &CS, ) -> Result where E: Executor + HasObservers, OT: ObserversTuple, C: Corpus, EM: EventManager, + CS: CorpusScheduler { let (fitness, is_solution) = self.execute_input(&input, executor, manager)?; let observers = executor.observers(); @@ -493,7 +505,7 @@ where 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)?; manager.fire( self, @@ -521,17 +533,18 @@ where SC: Corpus, OFT: FeedbacksTuple, { - pub fn load_from_directory( + pub fn load_from_directory( &mut self, executor: &mut E, manager: &mut EM, + scheduler: &CS, in_dir: &Path, ) -> Result<(), Error> where - C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, EM: EventManager, + CS: CorpusScheduler { for entry in fs::read_dir(in_dir)? { let entry = entry?; @@ -549,34 +562,35 @@ where let bytes = fs::read(&path)?; let input = BytesInput::new(bytes); 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); } if is_solution { println!("File {:?} is a solution, however will be not considered as it is an initial testcase.", &path); } } else if attr.is_dir() { - self.load_from_directory(executor, manager, &path)?; + self.load_from_directory(executor, manager, scheduler, &path)?; } } Ok(()) } - pub fn load_initial_inputs( + pub fn load_initial_inputs( &mut self, executor: &mut E, manager: &mut EM, + scheduler: &CS, in_dirs: &[PathBuf], ) -> Result<(), Error> where - C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, EM: EventManager, + CS: CorpusScheduler, { 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( self, @@ -634,11 +648,12 @@ where Ok((fitness, is_solution)) } - pub fn generate_initial_inputs( + pub fn generate_initial_inputs( &mut self, executor: &mut E, generator: &mut G, manager: &mut EM, + scheduler: &CS, num: usize, ) -> Result<(), Error> where @@ -647,11 +662,12 @@ where E: Executor + HasObservers, OT: ObserversTuple, EM: EventManager, + CS: CorpusScheduler { let mut added = 0; for _ in 0..num { 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 { added += 1; }