removed Engine (for now)

This commit is contained in:
Dominik Maier 2021-02-04 21:06:05 +01:00
parent 28ed6dbf35
commit beca91e3d3
6 changed files with 90 additions and 143 deletions

View File

@ -18,7 +18,6 @@ use crate::{
observers::ObserversTuple,
serde_anymap::{SerdeAny, SerdeAnyMap},
stages::StagesTuple,
tuples::{tuple_list, tuple_list_type},
utils::{current_milliseconds, Rand},
AflError,
};
@ -37,7 +36,6 @@ pub trait StateMetadata: Debug {
pub struct State<I, R, FT>
where
I: Input,
R: Rand,
FT: FeedbacksTuple<I>,
{
/// How many times the executor ran the harness/target
@ -49,7 +47,7 @@ where
// additional_corpuses, maybe another TupleList?
// Feedbacks used to evaluate an input
feedbacks: FT,
phantom: PhantomData<(I, R)>,
phantom: PhantomData<(R, I)>,
}
#[cfg(feature = "std")]
@ -58,11 +56,11 @@ where
R: Rand,
FT: FeedbacksTuple<BytesInput>,
{
pub fn load_from_directory<G, C, E, OT, ET, EM>(
pub fn load_from_directory<G, C, E, OT, EM>(
&mut self,
executor: &mut E,
corpus: &mut C,
generator: &mut G,
engine: &mut Engine<E, OT, ET, BytesInput>,
manager: &mut EM,
in_dir: &Path,
) -> Result<(), AflError>
@ -71,7 +69,6 @@ where
C: Corpus<BytesInput, R>,
E: Executor<BytesInput> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<BytesInput>,
EM: EventManager<BytesInput>,
{
for entry in fs::read_dir(in_dir)? {
@ -89,24 +86,23 @@ where
println!("Loading file {:?} ...", &path);
let bytes = fs::read(&path)?;
let input = BytesInput::new(bytes);
let fitness =
self.evaluate_input(&input, engine.executor_mut(), corpus, manager)?;
let fitness = self.evaluate_input(&input, executor, corpus, manager)?;
if self.add_if_interesting(corpus, input, fitness)?.is_none() {
println!("File {:?} was not interesting, skipped.", &path);
}
} else if attr.is_dir() {
self.load_from_directory(corpus, generator, engine, manager, &path)?;
self.load_from_directory(executor, corpus, generator, manager, &path)?;
}
}
Ok(())
}
pub fn load_initial_inputs<G, C, E, OT, ET, EM>(
pub fn load_initial_inputs<G, C, E, OT, EM>(
&mut self,
executor: &mut E,
corpus: &mut C,
generator: &mut G,
engine: &mut Engine<E, OT, ET, BytesInput>,
manager: &mut EM,
in_dirs: &[PathBuf],
) -> Result<(), AflError>
@ -115,11 +111,10 @@ where
C: Corpus<BytesInput, R>,
E: Executor<BytesInput> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<BytesInput>,
EM: EventManager<BytesInput>,
{
for in_dir in in_dirs {
self.load_from_directory(corpus, generator, engine, manager, in_dir)?;
self.load_from_directory(executor, corpus, generator, manager, in_dir)?;
}
manager.log(
0,
@ -296,9 +291,9 @@ where
pub fn generate_initial_inputs<G, C, E, OT, ET, EM>(
&mut self,
rand: &mut R,
executor: &mut E,
corpus: &mut C,
generator: &mut G,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
num: usize,
) -> Result<(), AflError>
@ -313,7 +308,7 @@ where
let mut added = 0;
for _ in 0..num {
let input = generator.generate(rand)?;
let fitness = self.evaluate_input(&input, engine.executor_mut(), corpus, manager)?;
let fitness = self.evaluate_input(&input, executor, corpus, manager)?;
if !self.add_if_interesting(corpus, input, fitness)?.is_none() {
added += 1;
}
@ -337,64 +332,6 @@ where
}
}
#[derive(Clone, Debug)]
pub struct Engine<E, OT, ET, I>
where
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<I>,
I: Input,
{
main_executor: E,
additional_executors: ET,
phantom: PhantomData<(OT, I)>,
}
impl<E, OT, ET, I> Engine<E, OT, ET, I>
where
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
ET: ExecutorsTuple<I>,
I: Input,
{
/// Return the executor
pub fn executor(&self) -> &E {
&self.main_executor
}
/// Return the executor (mutable)
pub fn executor_mut(&mut self) -> &mut E {
&mut self.main_executor
}
pub fn additional_executors(&self) -> &ET {
&self.additional_executors
}
pub fn additional_executors_mut(&mut self) -> &mut ET {
&mut self.additional_executors
}
pub fn with_executors(main_executor: E, additional_executors: ET) -> Self {
Self {
main_executor: main_executor,
additional_executors: additional_executors,
phantom: PhantomData,
}
}
}
impl<E, OT, I> Engine<E, OT, tuple_list_type!(), I>
where
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
I: Input,
{
pub fn new(main_executor: E) -> Self {
Self::with_executors(main_executor, tuple_list!())
}
}
pub trait Fuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
@ -414,15 +351,15 @@ where
fn fuzz_one(
&mut self,
rand: &mut R,
executor: &mut E,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
) -> Result<usize, AflError> {
let (_, idx) = corpus.next(rand)?;
self.stages_mut()
.perform_all(rand, state, corpus, engine, manager, idx)?;
.perform_all(rand, executor, state, corpus, manager, idx)?;
manager.process(state, corpus)?;
Ok(idx)
@ -431,14 +368,14 @@ where
fn fuzz_loop(
&mut self,
rand: &mut R,
executor: &mut E,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
) -> Result<(), AflError> {
let mut last = current_milliseconds();
loop {
self.fuzz_one(rand, state, corpus, engine, manager)?;
self.fuzz_one(rand, executor, state, corpus, manager)?;
let cur = current_milliseconds();
if cur - last > 60 * 100 {
last = cur;
@ -514,7 +451,7 @@ mod tests {
use crate::{
corpus::{Corpus, InMemoryCorpus, Testcase},
engines::{Engine, Fuzzer, State, StdFuzzer},
engines::{Fuzzer, State, StdFuzzer},
executors::{Executor, ExitKind, InMemoryExecutor},
inputs::{BytesInput, Input},
mutators::{mutation_bitflip, ComposedByMutations, StdScheduledMutator},
@ -554,7 +491,6 @@ mod tests {
&mut event_manager,
);
let mut engine = Engine::new(executor);
let mut mutator = StdScheduledMutator::new();
mutator.add_mutation(mutation_bitflip);
let stage = StdMutationalStage::new(mutator);
@ -564,9 +500,9 @@ mod tests {
fuzzer
.fuzz_one(
&mut rand,
&mut executor,
&mut state,
&mut corpus,
&mut engine,
&mut event_manager,
)
.expect(&format!("Error in iter {}", i));

View File

@ -729,23 +729,26 @@ where
// Converts a hex u8 to its u8 value: 'A' -> 10 etc.
fn from_hex(hex: u8) -> Result<u8, AflError> {
if hex >= 48 && hex <= 57 { return Ok(hex - 48); }
if hex >= 65 && hex <= 70 { return Ok(hex - 55); }
if hex >= 97 && hex <= 102 { return Ok(hex - 87); }
if hex >= 48 && hex <= 57 {
return Ok(hex - 48);
}
if hex >= 65 && hex <= 70 {
return Ok(hex - 55);
}
if hex >= 97 && hex <= 102 {
return Ok(hex - 87);
}
return Err(AflError::IllegalArgument("".to_owned()));
}
/// Decodes a dictionary token: 'foo\x41\\and\"bar' -> 'fooA\and"bar'
pub fn str_decode(item: &str) -> Result<Vec<u8>, AflError> {
let mut token : Vec<u8> = Vec::new();
let item : Vec<u8> = item.as_bytes().to_vec();
let backslash : u8 = 92; // '\\'
let mut take_next : bool = false;
let mut take_next_two : u32 = 0;
let mut decoded : u8 = 0;
let mut token: Vec<u8> = Vec::new();
let item: Vec<u8> = item.as_bytes().to_vec();
let backslash: u8 = 92; // '\\'
let mut take_next: bool = false;
let mut take_next_two: u32 = 0;
let mut decoded: u8 = 0;
for c in item {
if take_next_two == 1 {
@ -770,30 +773,24 @@ pub fn str_decode(item: &str) -> Result<Vec<u8>, AflError> {
}
return Ok(token);
}
/// Adds a token to a dictionary, checking it is not a duplicate
pub fn add_token_to_dictionary(dict : &mut Vec<Vec<u8>>, token: &Vec<u8>) -> u32 {
if dict.contains(token) { return 0; }
pub fn add_token_to_dictionary(dict: &mut Vec<Vec<u8>>, token: &Vec<u8>) -> u32 {
if dict.contains(token) {
return 0;
}
dict.push(token.to_vec());
return 1;
}
/// Read a dictionary file and return the number of entries read
pub fn read_dict_file(
f: &str,
dict : &mut Vec<Vec<u8>>,
) -> Result<u32, AflError> {
pub fn read_dict_file(f: &str, dict: &mut Vec<Vec<u8>>) -> Result<u32, AflError> {
let mut entries = 0;
println!("Loading dictionary {:?} ...", &f);
let file = File::open(&f)?; // panic if not found
let file = File::open(&f)?; // panic if not found
let reader = BufReader::new(file);
for line in reader.lines() {
@ -802,46 +799,60 @@ pub fn read_dict_file(
// we are only interested in '"..."', not prefixed 'foo = '
let start = line.chars().nth(0);
if line.len() == 0 || start == Some('#') { continue; }
if line.len() == 0 || start == Some('#') {
continue;
}
let pos_quote = match line.find("\"") {
Some(x) => x,
_ => return Err(AflError::IllegalArgument("Illegal line: ".to_owned() + line)),
_ => {
return Err(AflError::IllegalArgument(
"Illegal line: ".to_owned() + line,
))
}
};
if line.chars().nth(line.len() - 1) != Some('"') {
return Err(AflError::IllegalArgument("Illegal line: ".to_owned() + line));
return Err(AflError::IllegalArgument(
"Illegal line: ".to_owned() + line,
));
}
// extract item
let item = match line.get(pos_quote + 1 .. line.len() - 1) {
// extract item
let item = match line.get(pos_quote + 1..line.len() - 1) {
Some(x) => x,
_ => return Err(AflError::IllegalArgument("Illegal line: ".to_owned() + line)),
_ => {
return Err(AflError::IllegalArgument(
"Illegal line: ".to_owned() + line,
))
}
};
if item.len() == 0 { continue; }
if item.len() == 0 {
continue;
}
// decode
let token: Vec<u8> = match str_decode(item) {
Ok(val) => val,
Err(_) => return Err(AflError::IllegalArgument("Illegal line (hex decoding): ".to_owned() + line)),
Err(_) => {
return Err(AflError::IllegalArgument(
"Illegal line (hex decoding): ".to_owned() + line,
))
}
};
println!("Debug: {:?} -> {:?}", item, token);
entries += add_token_to_dictionary(dict, &token);
}
Ok(entries)
}
#[cfg(test)]
mod tests {
use crate::{
mutators::{read_dict_file},
};
use crate::mutators::read_dict_file;
#[test]
fn test_read_dict() {
println!("For this testcase to success create \"test.dic\".");
let mut v : Vec<Vec<u8>> = Vec::new();
let mut v: Vec<Vec<u8>> = Vec::new();
let res = read_dict_file(&"test.dic".to_string(), &mut v).unwrap();
#[cfg(feature = "std")]
println!("Dictionary entries: {:?}", res);

View File

@ -3,7 +3,7 @@ pub use mutational::StdMutationalStage;
use crate::{
corpus::Corpus,
engines::{Engine, State},
engines::State,
events::EventManager,
executors::{Executor, ExecutorsTuple, HasObservers},
feedbacks::FeedbacksTuple,
@ -31,9 +31,9 @@ where
fn perform(
&mut self,
rand: &mut R,
executor: &mut E,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError>;
@ -53,9 +53,9 @@ where
fn perform_all(
&mut self,
rand: &mut R,
executor: &mut E,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError>;
@ -77,9 +77,9 @@ where
fn perform_all(
&mut self,
_rand: &mut R,
_executor: &mut E,
_state: &mut State<I, R, FT>,
_corpus: &mut C,
_engine: &mut Engine<E, OT, ET, I>,
_manager: &mut EM,
_corpus_idx: usize,
) -> Result<(), AflError> {
@ -106,16 +106,16 @@ where
fn perform_all(
&mut self,
rand: &mut R,
executor: &mut E,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError> {
self.0
.perform(rand, state, corpus, engine, manager, corpus_idx)?;
.perform(rand, executor, state, corpus, manager, corpus_idx)?;
self.1
.perform_all(rand, state, corpus, engine, manager, corpus_idx)
.perform_all(rand, executor, state, corpus, manager, corpus_idx)
}
fn for_each(&self, f: fn(&dyn Stage<EM, E, OT, FT, ET, C, I, R>)) {

View File

@ -9,7 +9,7 @@ use crate::{
mutators::Mutator,
observers::ObserversTuple,
stages::Corpus,
stages::{Engine, Stage},
stages::Stage,
utils::Rand,
AflError,
};
@ -49,9 +49,9 @@ where
fn perform_mutational(
&mut self,
rand: &mut R,
executor: &mut E,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError> {
@ -61,13 +61,12 @@ where
self.mutator_mut()
.mutate(rand, corpus, &mut input_mut, i as i32)?;
let fitness =
state.evaluate_input(&input_mut, engine.executor_mut(), corpus, manager)?;
let fitness = state.evaluate_input(&input_mut, executor, corpus, manager)?;
self.mutator_mut()
.post_exec(fitness, &input_mut, i as i32)?;
let observers = engine.executor_mut().observers();
let observers = executor.observers();
// put all this shit in some overridable function in engine maybe? or in corpus.
// consider a corpus that strores new testcases in a temporary queue, for later processing
@ -148,13 +147,13 @@ where
fn perform(
&mut self,
rand: &mut R,
executor: &mut E,
state: &mut State<I, R, FT>,
corpus: &mut C,
engine: &mut Engine<E, OT, ET, I>,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), AflError> {
self.perform_mutational(rand, state, corpus, engine, manager, corpus_idx)
self.perform_mutational(rand, executor, state, corpus, manager, corpus_idx)
}
}

View File

@ -3,6 +3,7 @@
use alloc::vec::Vec;
use core::{cell::RefCell, debug_assert, fmt::Debug, time};
use postcard;
use serde::{Deserialize, Serialize};
use xxhash_rust::xxh3::xxh3_64_with_seed;
#[cfg(feature = "std")]
@ -110,7 +111,7 @@ where
}
/// Ways to get random around here
pub trait Rand: Debug {
pub trait Rand: Debug + Serialize {
// Sets the seed of this Rand
fn set_seed(&mut self, seed: u64);
@ -200,7 +201,7 @@ pub fn current_nanos() -> u64 {
/// XXH3 Based, hopefully speedy, rnd implementation
///
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct Xoshiro256StarRand {
rand_seed: [u64; 4],
seeded: bool,
@ -255,7 +256,7 @@ impl Xoshiro256StarRand {
/// XXH3 Based, hopefully speedy, rnd implementation
///
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct XorShift64Rand {
rand_seed: u64,
seeded: bool,
@ -296,7 +297,7 @@ impl XorShift64Rand {
/// XXH3 Based, hopefully speedy, rnd implementation
///
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct Lehmer64Rand {
rand_seed: u128,
seeded: bool,
@ -333,7 +334,7 @@ impl Lehmer64Rand {
/// Extremely quick rand implementation
/// see https://arxiv.org/pdf/2002.11331.pdf
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct RomuTrioRand {
x_state: u64,
y_state: u64,
@ -375,7 +376,7 @@ impl Rand for RomuTrioRand {
}
/// see https://arxiv.org/pdf/2002.11331.pdf
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct RomuDuoJrRand {
x_state: u64,
y_state: u64,
@ -426,7 +427,7 @@ pub fn current_milliseconds() -> u64 {
/// fake rand, for testing purposes
#[cfg(test)]
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct XKCDRand {
val: u64,
}

View File

@ -1,13 +1,13 @@
#[macro_use]
extern crate clap;
use clap::{App, Arg};
use std::{env, path::PathBuf, process::Command};
use afl::{
corpus::{Corpus, InMemoryCorpus},
engines::{Engine, Fuzzer, State, StdFuzzer},
events::{EventManager, LlmpEventManager, SimpleStats},
events::{LlmpEventManager, SimpleStats},
executors::{inmemory::InMemoryExecutor, Executor, ExitKind},
feedbacks::MaxMapFeedback,
generators::RandPrintablesGenerator,
@ -18,7 +18,7 @@ use afl::{
shmem::{AflShmem, ShMem},
stages::mutational::StdMutationalStage,
tuples::tuple_list,
utils::{deserialize_state_corpus_mgr, serialize_state_corpus_mgr, StdRand},
utils::{deserialize_state_corpus_mgr, StdRand},
AflError,
};