Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
This commit is contained in:
parent
308e9c7fe9
commit
6b235472e0
@ -106,6 +106,18 @@ pub trait Evaluator<E, EM, I, S> {
|
|||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: I,
|
input: I,
|
||||||
) -> Result<(bool, Option<usize>), Error>;
|
) -> Result<(bool, Option<usize>), Error>;
|
||||||
|
|
||||||
|
/// Runs the input and triggers observers and feedback.
|
||||||
|
/// Adds an input, to the corpus even if it's not considered `interesting` by the `feedback`.
|
||||||
|
/// Returns the `index` of the new testcase in the corpus.
|
||||||
|
/// Usually, you want to use [`Evaluator::evaluate_input`], unless you know what you are doing.
|
||||||
|
fn add_input(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: I,
|
||||||
|
) -> Result<usize, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The main fuzzer trait.
|
/// The main fuzzer trait.
|
||||||
@ -391,6 +403,42 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds an input, even if it's not conisered `interesting` by any of the executors
|
||||||
|
fn add_input(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: I,
|
||||||
|
) -> Result<usize, Error> {
|
||||||
|
let _ = self.execute_input(state, executor, manager, &input)?;
|
||||||
|
let observers = executor.observers();
|
||||||
|
// Always consider this to be "interesting"
|
||||||
|
|
||||||
|
// Not a solution
|
||||||
|
self.objective_mut().discard_metadata(state, &input)?;
|
||||||
|
|
||||||
|
// Add the input to the main corpus
|
||||||
|
let mut testcase = Testcase::new(input.clone());
|
||||||
|
self.feedback_mut().append_metadata(state, &mut testcase)?;
|
||||||
|
let idx = state.corpus_mut().add(testcase)?;
|
||||||
|
self.scheduler_mut().on_add(state, idx)?;
|
||||||
|
|
||||||
|
let observers_buf = manager.serialize_observers(observers)?;
|
||||||
|
manager.fire(
|
||||||
|
state,
|
||||||
|
Event::NewTestcase {
|
||||||
|
input,
|
||||||
|
observers_buf,
|
||||||
|
corpus_size: state.corpus().count(),
|
||||||
|
client_config: "TODO".into(),
|
||||||
|
time: current_time(),
|
||||||
|
executions: *state.executions(),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
Ok(idx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, CS, E, EM, F, I, OF, OT, S, ST, SC> Fuzzer<E, EM, I, S, ST>
|
impl<C, CS, E, EM, F, I, OF, OT, S, ST, SC> Fuzzer<E, EM, I, S, ST>
|
||||||
|
@ -355,12 +355,15 @@ where
|
|||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
/// loads inputs from a directory
|
/// loads inputs from a directory
|
||||||
|
/// If `forced` is `true`, the value will be loaded,
|
||||||
|
/// even if it's not considered to be `interesting`.
|
||||||
fn load_from_directory<E, EM, Z>(
|
fn load_from_directory<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_dir: &Path,
|
in_dir: &Path,
|
||||||
|
forced: bool,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Z: Evaluator<E, EM, I, Self>,
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
@ -379,18 +382,69 @@ where
|
|||||||
if attr.is_file() && attr.len() > 0 {
|
if attr.is_file() && attr.len() > 0 {
|
||||||
println!("Loading file {:?} ...", &path);
|
println!("Loading file {:?} ...", &path);
|
||||||
let input = I::from_file(&path)?;
|
let input = I::from_file(&path)?;
|
||||||
let (is_interesting, _) = fuzzer.evaluate_input(self, executor, manager, input)?;
|
if forced {
|
||||||
if !is_interesting {
|
let _ = fuzzer.add_input(self, executor, manager, input)?;
|
||||||
println!("File {:?} was not interesting, skipped.", &path);
|
} else {
|
||||||
|
let (is_interesting, _) =
|
||||||
|
fuzzer.evaluate_input(self, executor, manager, input)?;
|
||||||
|
if !is_interesting {
|
||||||
|
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)?;
|
self.load_from_directory(fuzzer, executor, manager, &path, forced)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loads initial inputs from the passed-in `in_dirs`.
|
||||||
|
/// If `forced` is true, will add all testcases, no matter what.
|
||||||
|
fn load_initial_inputs_internal<E, EM, Z>(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
in_dirs: &[PathBuf],
|
||||||
|
forced: bool,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
|
EM: EventManager<E, I, Self, Z>,
|
||||||
|
{
|
||||||
|
for in_dir in in_dirs {
|
||||||
|
self.load_from_directory(fuzzer, executor, manager, in_dir, forced)?;
|
||||||
|
}
|
||||||
|
manager.fire(
|
||||||
|
self,
|
||||||
|
Event::Log {
|
||||||
|
severity_level: LogSeverity::Debug,
|
||||||
|
message: format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
|
||||||
|
phantom: PhantomData,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
manager.process(fuzzer, self, executor)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads all intial inputs, even if they are not consiered `intesting`.
|
||||||
|
/// This is rarely the right method, use `load_initial_inputs`,
|
||||||
|
/// and potentially fix your `Feedback`, instead.
|
||||||
|
pub fn load_initial_inputs_forced<E, EM, Z>(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
in_dirs: &[PathBuf],
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
|
EM: EventManager<E, I, Self, Z>,
|
||||||
|
{
|
||||||
|
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, true)
|
||||||
|
}
|
||||||
|
|
||||||
/// Loads initial inputs from the passed-in `in_dirs`.
|
/// Loads initial inputs from the passed-in `in_dirs`.
|
||||||
pub fn load_initial_inputs<E, EM, Z>(
|
pub fn load_initial_inputs<E, EM, Z>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -403,19 +457,7 @@ where
|
|||||||
Z: Evaluator<E, EM, I, Self>,
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
EM: EventManager<E, I, Self, Z>,
|
EM: EventManager<E, I, Self, Z>,
|
||||||
{
|
{
|
||||||
for in_dir in in_dirs {
|
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, false)
|
||||||
self.load_from_directory(fuzzer, executor, manager, in_dir)?;
|
|
||||||
}
|
|
||||||
manager.fire(
|
|
||||||
self,
|
|
||||||
Event::Log {
|
|
||||||
severity_level: LogSeverity::Debug,
|
|
||||||
message: format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
|
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
manager.process(fuzzer, self, executor)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user