Restart loading initial inputs even after a crash/timeout (#1040)
* Track initial inputs loading * libfuzzer libpng * fuzzbench * fix no_std * fix no_std * clippy * fuzzers
This commit is contained in:
parent
86ab682e5a
commit
eaf5ff9de0
@ -190,7 +190,7 @@ pub fn main() {
|
|||||||
.expect("Failed to create the executor.");
|
.expect("Failed to create the executor.");
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
|
@ -190,7 +190,7 @@ pub fn main() {
|
|||||||
.expect("Failed to create the executor.");
|
.expect("Failed to create the executor.");
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
|
@ -198,7 +198,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
@ -313,7 +313,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
@ -443,7 +443,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -196,7 +196,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
@ -311,7 +311,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
@ -441,7 +441,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -369,7 +369,7 @@ fn fuzz(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -356,7 +356,7 @@ fn fuzz(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.corpus().count() < 1 {
|
if state.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -371,7 +371,7 @@ fn fuzz(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.corpus().count() < 1 {
|
if state.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -430,7 +430,7 @@ fn fuzz_binary(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
@ -647,7 +647,7 @@ fn fuzz_text(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -318,7 +318,7 @@ pub fn LLVMFuzzerRunDriver(
|
|||||||
let mut stages = tuple_list!(tracing, i2s, mutational);
|
let mut stages = tuple_list!(tracing, i2s, mutational);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
if input_dirs.is_empty() {
|
if input_dirs.is_empty() {
|
||||||
// Generator of printable bytearrays of max size 32
|
// Generator of printable bytearrays of max size 32
|
||||||
let mut generator = RandBytesGenerator::new(32);
|
let mut generator = RandBytesGenerator::new(32);
|
||||||
|
@ -157,7 +157,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
||||||
|
@ -191,7 +191,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
||||||
|
@ -226,7 +226,7 @@ pub fn libafl_main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, &opt.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, &opt.input)
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
|
@ -190,7 +190,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
||||||
|
@ -217,7 +217,7 @@ pub fn libafl_main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, &opt.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, &opt.input)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &opt.input));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &opt.input));
|
||||||
|
@ -222,7 +222,7 @@ pub fn libafl_main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, &opt.input)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, &opt.input)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &opt.input));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &opt.input));
|
||||||
|
@ -136,7 +136,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", corpus_dirs));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", corpus_dirs));
|
||||||
|
@ -142,7 +142,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", corpus_dirs));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", corpus_dirs));
|
||||||
|
@ -179,7 +179,7 @@ fn fuzz(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {corpus_dirs:?}"));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {corpus_dirs:?}"));
|
||||||
|
@ -154,7 +154,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
||||||
|
@ -195,7 +195,7 @@ pub fn fuzz() {
|
|||||||
// Wrap the executor to keep track of the timeout
|
// Wrap the executor to keep track of the timeout
|
||||||
let mut executor = TimeoutExecutor::new(executor, timeout);
|
let mut executor = TimeoutExecutor::new(executor, timeout);
|
||||||
|
|
||||||
if state.corpus().count() < 1 {
|
if state.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -176,7 +176,7 @@ pub fn fuzz() {
|
|||||||
// Wrap the executor to keep track of the timeout
|
// Wrap the executor to keep track of the timeout
|
||||||
let mut executor = TimeoutExecutor::new(executor, timeout);
|
let mut executor = TimeoutExecutor::new(executor, timeout);
|
||||||
|
|
||||||
if state.corpus().count() < 1 {
|
if state.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -204,7 +204,7 @@ pub fn fuzz() {
|
|||||||
// Wrap the executor to keep track of the timeout
|
// Wrap the executor to keep track of the timeout
|
||||||
let mut executor = TimeoutExecutor::new(executor, timeout);
|
let mut executor = TimeoutExecutor::new(executor, timeout);
|
||||||
|
|
||||||
if state.corpus().count() < 1 {
|
if state.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -158,7 +158,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
state
|
state
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs)
|
||||||
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
.unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", &corpus_dirs));
|
||||||
|
@ -5,6 +5,7 @@ use core::{fmt::Debug, marker::PhantomData, time::Duration};
|
|||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
@ -194,6 +195,9 @@ pub struct StdState<I, C, R, SC> {
|
|||||||
/// Performance statistics for this fuzzer
|
/// Performance statistics for this fuzzer
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
introspection_monitor: ClientPerfMonitor,
|
introspection_monitor: ClientPerfMonitor,
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
/// Remaining initial inputs to load, if any
|
||||||
|
remaining_initial_files: Option<Vec<PathBuf>>,
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,23 +351,15 @@ where
|
|||||||
R: Rand,
|
R: Rand,
|
||||||
SC: Corpus<Input = <Self as UsesInput>::Input>,
|
SC: Corpus<Input = <Self as UsesInput>::Input>,
|
||||||
{
|
{
|
||||||
/// Loads inputs from a directory.
|
/// Decide if the state nust load the inputs
|
||||||
/// If `forced` is `true`, the value will be loaded,
|
pub fn must_load_initial_inputs(&self) -> bool {
|
||||||
/// even if it's not considered to be `interesting`.
|
self.corpus().count() == 0
|
||||||
pub fn load_from_directory<E, EM, Z>(
|
|| (self.remaining_initial_files.is_some()
|
||||||
&mut self,
|
&& !self.remaining_initial_files.as_ref().unwrap().is_empty())
|
||||||
fuzzer: &mut Z,
|
}
|
||||||
executor: &mut E,
|
|
||||||
manager: &mut EM,
|
/// List initial inputs from a directory.
|
||||||
in_dir: &Path,
|
fn visit_initial_directory(files: &mut Vec<PathBuf>, in_dir: &Path) -> Result<(), Error> {
|
||||||
forced: bool,
|
|
||||||
loader: &mut dyn FnMut(&mut Z, &mut Self, &Path) -> Result<I, Error>,
|
|
||||||
) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
E: UsesState<State = Self>,
|
|
||||||
EM: UsesState<State = Self>,
|
|
||||||
Z: Evaluator<E, EM, State = Self>,
|
|
||||||
{
|
|
||||||
for entry in fs::read_dir(in_dir)? {
|
for entry in fs::read_dir(in_dir)? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
@ -380,18 +376,9 @@ where
|
|||||||
let attr = attributes?;
|
let attr = attributes?;
|
||||||
|
|
||||||
if attr.is_file() && attr.len() > 0 {
|
if attr.is_file() && attr.len() > 0 {
|
||||||
println!("Loading file {:?} ...", &path);
|
files.push(path);
|
||||||
let input = loader(fuzzer, self, &path)?;
|
|
||||||
if forced {
|
|
||||||
let _ = fuzzer.add_input(self, executor, manager, input)?;
|
|
||||||
} else {
|
|
||||||
let (res, _) = fuzzer.evaluate_input(self, executor, manager, input)?;
|
|
||||||
if res == ExecuteInputResult::None {
|
|
||||||
println!("File {:?} was not interesting, skipped.", &path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if attr.is_dir() {
|
} else if attr.is_dir() {
|
||||||
self.load_from_directory(fuzzer, executor, manager, &path, forced, loader)?;
|
Self::visit_initial_directory(files, in_dir)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,29 +387,48 @@ where
|
|||||||
|
|
||||||
/// Loads initial inputs from the passed-in `in_dirs`.
|
/// Loads initial inputs from the passed-in `in_dirs`.
|
||||||
/// If `forced` is true, will add all testcases, no matter what.
|
/// If `forced` is true, will add all testcases, no matter what.
|
||||||
fn load_initial_inputs_internal<E, EM, Z>(
|
fn load_initial_inputs_custom<E, EM, Z>(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
in_dirs: &[PathBuf],
|
in_dirs: &[PathBuf],
|
||||||
forced: bool,
|
forced: bool,
|
||||||
|
loader: &mut dyn FnMut(&mut Z, &mut Self, &Path) -> Result<I, Error>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
E: UsesState<State = Self>,
|
E: UsesState<State = Self>,
|
||||||
EM: EventFirer<State = Self>,
|
EM: EventFirer<State = Self>,
|
||||||
Z: Evaluator<E, EM, State = Self>,
|
Z: Evaluator<E, EM, State = Self>,
|
||||||
{
|
{
|
||||||
for in_dir in in_dirs {
|
if let Some(remaining) = self.remaining_initial_files.as_ref() {
|
||||||
self.load_from_directory(
|
// everything was loaded
|
||||||
fuzzer,
|
if remaining.is_empty() {
|
||||||
executor,
|
return Ok(());
|
||||||
manager,
|
}
|
||||||
in_dir,
|
} else {
|
||||||
forced,
|
let mut files = vec![];
|
||||||
&mut |_, _, path| I::from_file(path),
|
for in_dir in in_dirs {
|
||||||
)?;
|
Self::visit_initial_directory(&mut files, in_dir)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.remaining_initial_files = Some(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO option to shuffle the initial files
|
||||||
|
while let Some(path) = self.remaining_initial_files.as_mut().unwrap().pop() {
|
||||||
|
println!("Loading file {:?} ...", &path);
|
||||||
|
let input = loader(fuzzer, self, &path)?;
|
||||||
|
if forced {
|
||||||
|
let _ = fuzzer.add_input(self, executor, manager, input)?;
|
||||||
|
} else {
|
||||||
|
let (res, _) = fuzzer.evaluate_input(self, executor, manager, input)?;
|
||||||
|
if res == ExecuteInputResult::None {
|
||||||
|
println!("File {:?} was not interesting, skipped.", &path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
manager.fire(
|
manager.fire(
|
||||||
self,
|
self,
|
||||||
Event::Log {
|
Event::Log {
|
||||||
@ -449,7 +455,14 @@ where
|
|||||||
EM: EventFirer<State = Self>,
|
EM: EventFirer<State = Self>,
|
||||||
Z: Evaluator<E, EM, State = Self>,
|
Z: Evaluator<E, EM, State = Self>,
|
||||||
{
|
{
|
||||||
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, true)
|
self.load_initial_inputs_custom(
|
||||||
|
fuzzer,
|
||||||
|
executor,
|
||||||
|
manager,
|
||||||
|
in_dirs,
|
||||||
|
true,
|
||||||
|
&mut |_, _, path| I::from_file(path),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads initial inputs from the passed-in `in_dirs`.
|
/// Loads initial inputs from the passed-in `in_dirs`.
|
||||||
@ -465,7 +478,14 @@ where
|
|||||||
EM: EventFirer<State = Self>,
|
EM: EventFirer<State = Self>,
|
||||||
Z: Evaluator<E, EM, State = Self>,
|
Z: Evaluator<E, EM, State = Self>,
|
||||||
{
|
{
|
||||||
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, false)
|
self.load_initial_inputs_custom(
|
||||||
|
fuzzer,
|
||||||
|
executor,
|
||||||
|
manager,
|
||||||
|
in_dirs,
|
||||||
|
false,
|
||||||
|
&mut |_, _, path| I::from_file(path),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,6 +594,8 @@ where
|
|||||||
max_size: DEFAULT_MAX_SIZE,
|
max_size: DEFAULT_MAX_SIZE,
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
introspection_monitor: ClientPerfMonitor::new(),
|
introspection_monitor: ClientPerfMonitor::new(),
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
remaining_initial_files: None,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
};
|
};
|
||||||
feedback.init_state(&mut state)?;
|
feedback.init_state(&mut state)?;
|
||||||
|
@ -196,7 +196,7 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
|||||||
.expect("Failed to create the executor.");
|
.expect("Failed to create the executor.");
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
if self.input_dirs.is_empty() {
|
if self.input_dirs.is_empty() {
|
||||||
// Generator of printable bytearrays of max size 32
|
// Generator of printable bytearrays of max size 32
|
||||||
let mut generator = RandBytesGenerator::new(32);
|
let mut generator = RandBytesGenerator::new(32);
|
||||||
|
@ -216,7 +216,7 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
if self.input_dirs.is_empty() {
|
if self.input_dirs.is_empty() {
|
||||||
// Generator of printable bytearrays of max size 32
|
// Generator of printable bytearrays of max size 32
|
||||||
let mut generator = RandBytesGenerator::new(32);
|
let mut generator = RandBytesGenerator::new(32);
|
||||||
|
@ -232,7 +232,7 @@ where
|
|||||||
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
|
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
if self.input_dirs.is_empty() {
|
if self.input_dirs.is_empty() {
|
||||||
// Generator of printable bytearrays of max size 32
|
// Generator of printable bytearrays of max size 32
|
||||||
let mut generator = RandBytesGenerator::new(32);
|
let mut generator = RandBytesGenerator::new(32);
|
||||||
@ -335,7 +335,7 @@ where
|
|||||||
let mut executor = TimeoutExecutor::new(executor, timeout);
|
let mut executor = TimeoutExecutor::new(executor, timeout);
|
||||||
|
|
||||||
// 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.must_load_initial_inputs() {
|
||||||
if self.input_dirs.is_empty() {
|
if self.input_dirs.is_empty() {
|
||||||
// Generator of printable bytearrays of max size 32
|
// Generator of printable bytearrays of max size 32
|
||||||
let mut generator = RandBytesGenerator::new(32);
|
let mut generator = RandBytesGenerator::new(32);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user