fixed testcases, removed mutator param from mutators

This commit is contained in:
Dominik Maier 2021-02-25 18:55:37 +01:00
parent 07a7ce4fe2
commit ea278a0dd6
13 changed files with 144 additions and 274 deletions

View File

@ -88,7 +88,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
StdRand::new(current_nanos()), StdRand::new(current_nanos()),
// Corpus that will be evolved, we keep it in memory for performance // Corpus that will be evolved, we keep it in memory for performance
InMemoryCorpus::new(), InMemoryCorpus::new(),
// Feedbacks to rate the interestingness of an input // Feedbacks to rate the interestingness of an input
tuple_list!(MaxMapFeedback::new_with_observer("edges", &edges_observer)), tuple_list!(MaxMapFeedback::new_with_observer("edges", &edges_observer)),
// Corpus in which we store solutions (crashes in this example), // Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer // on disk so the user can get them after stopping the fuzzer
@ -137,7 +137,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
// 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
.load_initial_inputs(&mut executor, &mut restarting_mgr, &corpus_dirs) .load_initial_inputs(&mut executor, &mut restarting_mgr, &corpus_dirs)
.expect(&format!( .expect(&format!(
"Failed to load initial corpus at {:?}", "Failed to load initial corpus at {:?}",

View File

@ -1,3 +1,4 @@
//! Poor-rust-man's downcasts for stuff we send over the wire (or shared maps)
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use alloc::boxed::Box; use alloc::boxed::Box;

View File

@ -1,3 +1,5 @@
//! Compiletime lists used throughout the libafl universe
pub use tuple_list::{tuple_list, tuple_list_type, TupleList}; pub use tuple_list::{tuple_list, tuple_list_type, TupleList};
use core::any::TypeId; use core::any::TypeId;

View File

@ -1,7 +1,7 @@
//! Eventmanager manages all events that go to other instances of the fuzzer. //! Eventmanager manages all events that go to other instances of the fuzzer.
pub mod logger; pub mod simple;
pub use logger::*; pub use simple::*;
pub mod llmp; pub mod llmp;
pub use llmp::*; pub use llmp::*;

View File

@ -1,3 +1,4 @@
//! A very simple event manager, that just supports log outputs, but no multiprocessing
use alloc::{string::ToString, vec::Vec}; use alloc::{string::ToString, vec::Vec};
use core::marker::PhantomData; use core::marker::PhantomData;
@ -12,7 +13,7 @@ use crate::{
/// A simple, single-threaded event manager that just logs /// A simple, single-threaded event manager that just logs
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct LoggerEventManager<I, S, ST> pub struct SimpleEventManager<I, S, ST>
where where
I: Input, I: Input,
ST: Stats, //CE: CustomEvent<I, OT>, ST: Stats, //CE: CustomEvent<I, OT>,
@ -24,7 +25,7 @@ where
phantom: PhantomData<S>, phantom: PhantomData<S>,
} }
impl<I, S, ST> EventManager<I, S> for LoggerEventManager<I, S, ST> impl<I, S, ST> EventManager<I, S> for SimpleEventManager<I, S, ST>
where where
I: Input, I: Input,
ST: Stats, //CE: CustomEvent<I, OT>, ST: Stats, //CE: CustomEvent<I, OT>,
@ -51,7 +52,7 @@ where
} }
} }
impl<I, S, ST> LoggerEventManager<I, S, ST> impl<I, S, ST> SimpleEventManager<I, S, ST>
where where
I: Input, I: Input,
ST: Stats, //TODO CE: CustomEvent, ST: Stats, //TODO CE: CustomEvent,

View File

@ -38,7 +38,7 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: &u32) {
//*trace_byte = (*trace_byte).wrapping_add(1); //*trace_byte = (*trace_byte).wrapping_add(1);
} }
/// Called when the targetprogram starts /// Called when the target program starts
#[no_mangle] #[no_mangle]
#[inline] #[inline]
pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) { pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) {

View File

@ -137,7 +137,7 @@ mod tests {
}; };
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::events::LoggerEventManager; use crate::events::SimpleEventManager;
fn harness<E: Executor<I>, I: Input>(_executor: &E, _buf: &[u8]) -> ExitKind { fn harness<E: Executor<I>, I: Input>(_executor: &E, _buf: &[u8]) -> ExitKind {
ExitKind::Ok ExitKind::Ok
@ -147,21 +147,22 @@ mod tests {
fn test_fuzzer() { fn test_fuzzer() {
let mut rand = StdRand::new(0); let mut rand = StdRand::new(0);
let mut corpus = InMemoryCorpus::<BytesInput, StdRand>::new(); let mut corpus = InMemoryCorpus::<BytesInput>::new();
let testcase = Testcase::new(vec![0; 4]).into(); let testcase = Testcase::new(vec![0; 4]).into();
corpus.add(testcase); corpus.add(testcase);
let mut state = State::new( let mut state = State::new(
rand,
corpus, corpus,
tuple_list!(), tuple_list!(),
InMemoryCorpus::<BytesInput, StdRand>::new(), InMemoryCorpus::<BytesInput>::new(),
tuple_list!(), tuple_list!(),
); );
let stats = SimpleStats::new(|s| { let stats = SimpleStats::new(|s| {
println!("{}", s); println!("{}", s);
}); });
let mut event_manager = LoggerEventManager::new(stats); let mut event_manager = SimpleEventManager::new(stats);
let mut executor = InProcessExecutor::new( let mut executor = InProcessExecutor::new(
"main", "main",
@ -185,10 +186,10 @@ mod tests {
let state_serialized = postcard::to_allocvec(&state).unwrap(); let state_serialized = postcard::to_allocvec(&state).unwrap();
let state_deserialized: State< let state_deserialized: State<
InMemoryCorpus<BytesInput, _>, InMemoryCorpus<BytesInput>,
(), (),
BytesInput, BytesInput,
InMemoryCorpus<BytesInput, _>, InMemoryCorpus<BytesInput>,
(), (),
StdRand, StdRand,
> = postcard::from_bytes(state_serialized.as_slice()).unwrap(); > = postcard::from_bytes(state_serialized.as_slice()).unwrap();

View File

@ -31,14 +31,3 @@ where
Ok(()) Ok(())
} }
} }
/// The maximum size of a testcase
pub const DEFAULT_MAX_SIZE: usize = 1048576;
/// Interact with the maximum size
pub trait HasMaxSize {
/// The maximum size of the contents returned
fn max_size(&self) -> usize;
/// Sets the maximum size of the contents returned
fn set_max_size(&mut self, max_size: usize);
}

View File

@ -1,8 +1,9 @@
//! A wide variety of mutations used during fuzzing.
use crate::{ use crate::{
corpus::Corpus, corpus::Corpus,
inputs::{HasBytesVec, Input}, inputs::{HasBytesVec, Input},
mutators::*, state::{HasCorpus, HasMaxSize, HasRand},
state::{HasCorpus, HasRand},
utils::Rand, utils::Rand,
Error, Error,
}; };
@ -27,20 +28,20 @@ pub enum MutationResult {
// TODO maybe the mutator arg is not needed // TODO maybe the mutator arg is not needed
/// The generic function type that identifies mutations /// The generic function type that identifies mutations
pub type MutationFunction<I, M, S> = fn(&M, &mut S, &mut I) -> Result<MutationResult, Error>; pub type MutationFunction<I, S> = fn(&mut S, &mut I) -> Result<MutationResult, Error>;
pub trait ComposedByMutations<I, S> pub trait ComposedByMutations<I, S>
where where
I: Input, I: Input,
{ {
/// Get a mutation by index /// Get a mutation by index
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, S>; fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, S>;
/// Get the number of mutations /// Get the number of mutations
fn mutations_count(&self) -> usize; fn mutations_count(&self) -> usize;
/// Add a mutation /// Add a mutation
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, S>); fn add_mutation(&mut self, mutation: MutationFunction<I, S>);
} }
/// Mem move in the own vec /// Mem move in the own vec
@ -123,15 +124,10 @@ const INTERESTING_32: [i32; 27] = [
]; ];
/// Bitflip mutation for inputs with a bytes vector /// Bitflip mutation for inputs with a bytes vector
pub fn mutation_bitflip<I, M, R, S>( pub fn mutation_bitflip<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R> + HasMaxSize,
R: Rand, R: Rand,
{ {
if input.bytes().len() == 0 { if input.bytes().len() == 0 {
@ -146,12 +142,7 @@ where
} }
} }
pub fn mutation_byteflip<I, M, R, S>( pub fn mutation_byteflip<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -169,12 +160,7 @@ where
} }
} }
pub fn mutation_byteinc<I, M, R, S>( pub fn mutation_byteinc<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -193,12 +179,7 @@ where
} }
} }
pub fn mutation_bytedec<I, M, R, S>( pub fn mutation_bytedec<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -217,12 +198,7 @@ where
} }
} }
pub fn mutation_byteneg<I, M, R, S>( pub fn mutation_byteneg<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -240,12 +216,7 @@ where
} }
} }
pub fn mutation_byterand<I, M, R, S>( pub fn mutation_byterand<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -263,12 +234,7 @@ where
} }
} }
pub fn mutation_byteadd<I, M, R, S>( pub fn mutation_byteadd<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -291,12 +257,7 @@ where
} }
} }
pub fn mutation_wordadd<I, M, R, S>( pub fn mutation_wordadd<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -321,12 +282,7 @@ where
} }
} }
pub fn mutation_dwordadd<I, M, R, S>( pub fn mutation_dwordadd<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -351,12 +307,7 @@ where
} }
} }
pub fn mutation_qwordadd<I, M, R, S>( pub fn mutation_qwordadd<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -381,9 +332,7 @@ where
} }
} }
pub fn mutation_byteinteresting<I, M, R, S>( pub fn mutation_byteinteresting<I, R, S>(
_: &M,
state: &mut S, state: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, Error> ) -> Result<MutationResult, Error>
@ -405,9 +354,7 @@ where
} }
} }
pub fn mutation_wordinteresting<I, M, R, S>( pub fn mutation_wordinteresting<I, R, S>(
_: &M,
state: &mut S, state: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, Error> ) -> Result<MutationResult, Error>
@ -435,9 +382,7 @@ where
} }
} }
pub fn mutation_dwordinteresting<I, M, R, S>( pub fn mutation_dwordinteresting<I, R, S>(
_: &M,
state: &mut S, state: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, Error> ) -> Result<MutationResult, Error>
@ -465,12 +410,7 @@ where
} }
} }
pub fn mutation_bytesdelete<I, M, R, S>( pub fn mutation_bytesdelete<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -488,25 +428,20 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesexpand<I, M, R, S>( pub fn mutation_bytesexpand<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
mutator: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
M: HasMaxSize,
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R> + HasMaxSize,
R: Rand, R: Rand,
{ {
let max_size = state.max_size();
let size = input.bytes().len(); let size = input.bytes().len();
let off = state.rand_mut().below((size + 1) as u64) as usize; let off = state.rand_mut().below((size + 1) as u64) as usize;
let mut len = 1 + state.rand_mut().below(16) as usize; let mut len = 1 + state.rand_mut().below(16) as usize;
if size + len > mutator.max_size() { if size + len > max_size {
if mutator.max_size() > size { if max_size > size {
len = mutator.max_size() - size; len = max_size - size;
} else { } else {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
} }
@ -518,25 +453,23 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesinsert<I, M, R, S>( pub fn mutation_bytesinsert<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
mutator: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
M: HasMaxSize,
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R> + HasMaxSize,
R: Rand, R: Rand,
{ {
let max_size = state.max_size();
let size = input.bytes().len(); let size = input.bytes().len();
if size == 0 {
return Ok(MutationResult::Skipped);
}
let off = state.rand_mut().below((size + 1) as u64) as usize; let off = state.rand_mut().below((size + 1) as u64) as usize;
let mut len = 1 + state.rand_mut().below(16) as usize; let mut len = 1 + state.rand_mut().below(16) as usize;
if size + len > mutator.max_size() { if size + len > max_size {
if mutator.max_size() > size { if max_size > size {
len = mutator.max_size() - size; len = max_size - size;
} else { } else {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
} }
@ -551,25 +484,23 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesrandinsert<I, M, R, S>( pub fn mutation_bytesrandinsert<I, R, S>(
mutator: &M,
state: &mut S, state: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, Error> ) -> Result<MutationResult, Error>
where where
M: HasMaxSize,
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R> + HasMaxSize,
R: Rand, R: Rand,
{ {
let max_size = state.max_size();
let size = input.bytes().len(); let size = input.bytes().len();
let off = state.rand_mut().below((size + 1) as u64) as usize; let off = state.rand_mut().below((size + 1) as u64) as usize;
let mut len = 1 + state.rand_mut().below(16) as usize; let mut len = 1 + state.rand_mut().below(16) as usize;
if size + len > mutator.max_size() { if size + len > max_size {
if mutator.max_size() > size { if max_size > size {
len = mutator.max_size() - size; len = max_size - size;
} else { } else {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
} }
@ -584,12 +515,7 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesset<I, M, R, S>( pub fn mutation_bytesset<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -609,12 +535,7 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesrandset<I, M, R, S>( pub fn mutation_bytesrandset<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -634,12 +555,7 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytescopy<I, M, R, S>( pub fn mutation_bytescopy<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -659,12 +575,7 @@ where
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
pub fn mutation_bytesswap<I, M, R, S>( pub fn mutation_bytesswap<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R>, S: HasRand<R>,
@ -687,18 +598,15 @@ where
} }
/// Crossover insert mutation /// Crossover insert mutation
pub fn mutation_crossover_insert<C, I, M, R, S>( pub fn mutation_crossover_insert<C, I, R, S>(
mutator: &M,
state: &mut S, state: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, Error> ) -> Result<MutationResult, Error>
where where
M: HasMaxSize,
C: Corpus<I>, C: Corpus<I>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
R: Rand, R: Rand,
S: HasRand<R> + HasCorpus<C, I>, S: HasRand<R> + HasCorpus<C, I> + HasMaxSize,
{ {
let size = input.bytes().len(); let size = input.bytes().len();
@ -722,6 +630,7 @@ where
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
} }
let max_size = state.max_size();
let from = state.rand_mut().below(other_size as u64) as usize; let from = state.rand_mut().below(other_size as u64) as usize;
let to = state.rand_mut().below(size as u64) as usize; let to = state.rand_mut().below(size as u64) as usize;
let mut len = state.rand_mut().below((other_size - from) as u64) as usize; let mut len = state.rand_mut().below((other_size - from) as u64) as usize;
@ -729,9 +638,9 @@ where
let mut other_testcase = state.corpus().get(idx)?.borrow_mut(); let mut other_testcase = state.corpus().get(idx)?.borrow_mut();
let other = other_testcase.load_input()?; let other = other_testcase.load_input()?;
if size + len > mutator.max_size() { if size + len > max_size {
if mutator.max_size() > size { if max_size > size {
len = mutator.max_size() - size; len = max_size - size;
} else { } else {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
} }
@ -745,9 +654,7 @@ where
} }
/// Crossover replace mutation /// Crossover replace mutation
pub fn mutation_crossover_replace<C, I, M, R, S>( pub fn mutation_crossover_replace<C, I, R, S>(
_: &M,
state: &mut S, state: &mut S,
input: &mut I, input: &mut I,
) -> Result<MutationResult, Error> ) -> Result<MutationResult, Error>
@ -808,12 +715,7 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
} }
/// Splicing mutation from AFL /// Splicing mutation from AFL
pub fn mutation_splice<C, I, M, R, S>( pub fn mutation_splice<C, I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
C: Corpus<I>, C: Corpus<I>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
@ -970,7 +872,6 @@ pub fn read_tokens_file(f: &str, tokens: &mut Vec<Vec<u8>>) -> Result<u32, Error
Ok(entries) Ok(entries)
} }
/*
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -1007,17 +908,6 @@ token2="B"
let _ = fs::remove_file("test.tkns"); let _ = fs::remove_file("test.tkns");
} }
struct WithMaxSize {}
impl HasMaxSize for WithMaxSize {
fn max_size(&self) -> usize {
16000 as usize
}
fn set_max_size(&mut self, _max_size: usize) {
todo!("Not needed");
}
}
#[test] #[test]
fn test_mutators() { fn test_mutators() {
let mut inputs = vec![ let mut inputs = vec![
@ -1030,16 +920,16 @@ token2="B"
BytesInput::new(vec![1; 4]), BytesInput::new(vec![1; 4]),
]; ];
let mut mutator = WithMaxSize {}; let rand = StdRand::new(1337);
let mut corpus = InMemoryCorpus::new();
let mut rand = StdRand::new(1337); corpus
let mut corpus: InMemoryCorpus<_, StdRand> = InMemoryCorpus::new(); .add(BytesInput::new(vec![0x42; 0x1337]).into())
.unwrap();
corpus.add(BytesInput::new(vec![0x42; 0x1337]).into()); let mut state = State::new(rand, corpus, (), InMemoryCorpus::new(), ());
let mut state = State::new(corpus, (), InMemoryCorpus::new(), ()); let mut mutations: Vec<MutationFunction<_, _>> = vec![];
let mut mutations: Vec<MutationFunction<BytesInput, WithMaxSize, StdRand, _>> = vec![];
mutations.push(mutation_bitflip); mutations.push(mutation_bitflip);
mutations.push(mutation_byteflip); mutations.push(mutation_byteflip);
@ -1072,7 +962,7 @@ token2="B"
for mutation in &mutations { for mutation in &mutations {
for input in inputs.iter() { for input in inputs.iter() {
let mut mutant = input.clone(); let mut mutant = input.clone();
match mutation(&mut mutator, &mut rand, &mut state, &mut mutant).unwrap() { match mutation(&mut state, &mut mutant).unwrap() {
MutationResult::Mutated => new_testcases.push(mutant), MutationResult::Mutated => new_testcases.push(mutant),
MutationResult::Skipped => (), MutationResult::Skipped => (),
}; };
@ -1087,4 +977,3 @@ token2="B"
*/ */
} }
} }
*/

View File

@ -1,13 +1,15 @@
use crate::inputs::HasBytesVec;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::{default::Default, fmt, marker::PhantomData}; use core::{
use fmt::Debug; default::Default,
fmt::{self, Debug},
marker::PhantomData,
};
use crate::{ use crate::{
corpus::Corpus, corpus::Corpus,
inputs::Input, inputs::{HasBytesVec, Input},
mutators::{HasMaxSize, Mutator, DEFAULT_MAX_SIZE}, mutators::Mutator,
state::{HasCorpus, HasMetadata, HasRand}, state::{HasCorpus, HasMaxSize, HasMetadata, HasRand},
utils::Rand, utils::Rand,
Error, Error,
}; };
@ -31,7 +33,7 @@ where
let num = self.iterations(state, input); let num = self.iterations(state, input);
for _ in 0..num { for _ in 0..num {
let idx = self.schedule(self.mutations_count(), state, input); let idx = self.schedule(self.mutations_count(), state, input);
self.mutation_by_idx(idx)(self, state, input)?; self.mutation_by_idx(idx)(state, input)?;
} }
Ok(()) Ok(())
} }
@ -43,8 +45,7 @@ where
S: HasRand<R>, S: HasRand<R>,
R: Rand, R: Rand,
{ {
mutations: Vec<MutationFunction<I, Self, S>>, mutations: Vec<MutationFunction<I, S>>,
max_size: usize,
phantom: PhantomData<R>, phantom: PhantomData<R>,
} }
@ -57,9 +58,8 @@ where
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
"StdScheduledMutator with {} Mutations, max_size: {}, for Input type {}", "StdScheduledMutator with {} Mutations for Input type {}",
self.mutations.len(), self.mutations.len(),
self.max_size,
core::any::type_name::<I>() core::any::type_name::<I>()
) )
} }
@ -83,7 +83,7 @@ where
R: Rand, R: Rand,
{ {
#[inline] #[inline]
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, S> { fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, S> {
self.mutations[index] self.mutations[index]
} }
@ -93,7 +93,7 @@ where
} }
#[inline] #[inline]
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, S>) { fn add_mutation(&mut self, mutation: MutationFunction<I, S>) {
self.mutations.push(mutation) self.mutations.push(mutation)
} }
} }
@ -116,23 +116,6 @@ where
} }
} }
impl<I, R, S> HasMaxSize for StdScheduledMutator<I, R, S>
where
I: Input,
S: HasRand<R>,
R: Rand,
{
#[inline]
fn max_size(&self) -> usize {
self.max_size
}
#[inline]
fn set_max_size(&mut self, max_size: usize) {
self.max_size = max_size;
}
}
impl<I, R, S> StdScheduledMutator<I, R, S> impl<I, R, S> StdScheduledMutator<I, R, S>
where where
I: Input, I: Input,
@ -143,16 +126,14 @@ where
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
mutations: vec![], mutations: vec![],
max_size: DEFAULT_MAX_SIZE,
phantom: PhantomData, phantom: PhantomData,
} }
} }
/// Create a new StdScheduledMutator instance specifying mutations /// Create a new StdScheduledMutator instance specifying mutations
pub fn with_mutations(mutations: Vec<MutationFunction<I, Self, S>>) -> Self { pub fn with_mutations(mutations: Vec<MutationFunction<I, S>>) -> Self {
StdScheduledMutator { StdScheduledMutator {
mutations: mutations, mutations: mutations,
max_size: DEFAULT_MAX_SIZE,
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -162,9 +143,9 @@ where
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct HavocBytesMutator<C, I, R, S, SM> pub struct HavocBytesMutator<C, I, R, S, SM>
where where
SM: ScheduledMutator<I, S> + HasMaxSize, SM: ScheduledMutator<I, S>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata, S: HasRand<R> + HasCorpus<C, I> + HasMetadata + HasMaxSize,
C: Corpus<I>, C: Corpus<I>,
R: Rand, R: Rand,
{ {
@ -174,9 +155,9 @@ where
impl<C, I, R, S, SM> Mutator<I, S> for HavocBytesMutator<C, I, R, S, SM> impl<C, I, R, S, SM> Mutator<I, S> for HavocBytesMutator<C, I, R, S, SM>
where where
SM: ScheduledMutator<I, S> + HasMaxSize, SM: ScheduledMutator<I, S>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata, S: HasRand<R> + HasCorpus<C, I> + HasMetadata + HasMaxSize,
C: Corpus<I>, C: Corpus<I>,
R: Rand, R: Rand,
{ {
@ -208,30 +189,11 @@ where
} }
} }
impl<C, I, R, S, SM> HasMaxSize for HavocBytesMutator<C, I, R, S, SM>
where
SM: ScheduledMutator<I, S> + HasMaxSize,
I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
C: Corpus<I>,
R: Rand,
{
#[inline]
fn max_size(&self) -> usize {
self.scheduled.max_size()
}
#[inline]
fn set_max_size(&mut self, max_size: usize) {
self.scheduled.set_max_size(max_size);
}
}
impl<C, I, R, S, SM> HavocBytesMutator<C, I, R, S, SM> impl<C, I, R, S, SM> HavocBytesMutator<C, I, R, S, SM>
where where
SM: ScheduledMutator<I, S> + HasMaxSize, SM: ScheduledMutator<I, S>,
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata, S: HasRand<R> + HasCorpus<C, I> + HasMetadata + HasMaxSize,
C: Corpus<I>, C: Corpus<I>,
R: Rand, R: Rand,
{ {
@ -249,7 +211,7 @@ where
impl<C, I, R, S> Default for HavocBytesMutator<C, I, R, S, StdScheduledMutator<I, R, S>> impl<C, I, R, S> Default for HavocBytesMutator<C, I, R, S, StdScheduledMutator<I, R, S>>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasRand<R> + HasCorpus<C, I> + HasMetadata, S: HasRand<R> + HasCorpus<C, I> + HasMetadata + HasMaxSize,
C: Corpus<I>, C: Corpus<I>,
R: Rand, R: Rand,
{ {

View File

@ -4,7 +4,7 @@
use crate::{ use crate::{
inputs::{HasBytesVec, Input}, inputs::{HasBytesVec, Input},
mutators::*, mutators::*,
state::{HasMetadata, HasRand}, state::{HasMaxSize, HasMetadata, HasRand},
utils::Rand, utils::Rand,
Error, Error,
}; };
@ -30,17 +30,13 @@ impl TokensMetadata {
} }
/// Insert a dictionary token /// Insert a dictionary token
pub fn mutation_tokeninsert<I, M, R, S>( pub fn mutation_tokeninsert<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
mutator: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
M: HasMaxSize,
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasMetadata + HasRand<R>, S: HasMetadata + HasRand<R> + HasMaxSize,
R: Rand, R: Rand,
{ {
let max_size = state.max_size();
let tokens_len = { let tokens_len = {
let meta = state.metadata().get::<TokensMetadata>(); let meta = state.metadata().get::<TokensMetadata>();
if meta.is_none() { if meta.is_none() {
@ -60,9 +56,9 @@ where
let token = &meta.tokens[token_idx]; let token = &meta.tokens[token_idx];
let mut len = token.len(); let mut len = token.len();
if size + len > mutator.max_size() { if size + len > max_size {
if mutator.max_size() > size { if max_size > size {
len = mutator.max_size() - size; len = max_size - size;
} else { } else {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
} }
@ -76,13 +72,8 @@ where
} }
/// Overwrite with a dictionary token /// Overwrite with a dictionary token
pub fn mutation_tokenreplace<I, M, R, S>( pub fn mutation_tokenreplace<I, R, S>(state: &mut S, input: &mut I) -> Result<MutationResult, Error>
_: &M,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, Error>
where where
M: HasMaxSize,
I: Input + HasBytesVec, I: Input + HasBytesVec,
S: HasMetadata + HasRand<R>, S: HasMetadata + HasRand<R>,
R: Rand, R: Rand,

View File

@ -24,6 +24,9 @@ use crate::{
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::inputs::bytes::BytesInput; use crate::inputs::bytes::BytesInput;
/// The maximum size of a testcase
pub const DEFAULT_MAX_SIZE: usize = 1048576;
/// Trait for elements offering a corpus /// Trait for elements offering a corpus
pub trait HasCorpus<C, I> pub trait HasCorpus<C, I>
where where
@ -36,6 +39,14 @@ where
fn corpus_mut(&mut self) -> &mut C; fn corpus_mut(&mut self) -> &mut C;
} }
/// Interact with the maximum size
pub trait HasMaxSize {
/// The maximum size hint for items and mutations returned
fn max_size(&self) -> usize;
/// Sets the maximum size hint for the items and mutations
fn set_max_size(&mut self, max_size: usize);
}
/// Trait for elements offering a corpus of solutions /// Trait for elements offering a corpus of solutions
pub trait HasSolutions<C, I> pub trait HasSolutions<C, I>
where where
@ -204,6 +215,8 @@ where
objectives: OFT, objectives: OFT,
/// Metadata stored for this state by one of the components /// Metadata stored for this state by one of the components
metadata: SerdeAnyMap, metadata: SerdeAnyMap,
/// MaxSize testcase size for mutators that appreciate it
max_size: usize,
phantom: PhantomData<I>, phantom: PhantomData<I>,
} }
@ -362,6 +375,24 @@ where
} }
} }
impl<C, FT, I, OFT, R, SC> HasMaxSize for State<C, FT, I, OFT, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbacksTuple<I>,
SC: Corpus<I>,
OFT: FeedbacksTuple<I>,
{
fn max_size(&self) -> usize {
self.max_size
}
fn set_max_size(&mut self, max_size: usize) {
self.max_size = max_size
}
}
impl<C, FT, I, OFT, R, SC> HasStartTime for State<C, FT, I, OFT, R, SC> impl<C, FT, I, OFT, R, SC> HasStartTime for State<C, FT, I, OFT, R, SC>
where where
C: Corpus<I>, C: Corpus<I>,
@ -638,6 +669,7 @@ where
feedbacks, feedbacks,
solutions, solutions,
objectives, objectives,
max_size: DEFAULT_MAX_SIZE,
phantom: PhantomData, phantom: PhantomData,
} }
} }

View File

@ -311,6 +311,7 @@ impl Rand for RomuDuoJrRand {
} }
} }
/// Get the current milliseconds
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn current_milliseconds() -> u64 { pub fn current_milliseconds() -> u64 {
SystemTime::now() SystemTime::now()
@ -319,6 +320,7 @@ pub fn current_milliseconds() -> u64 {
.as_millis() as u64 .as_millis() as u64
} }
/// Returns a fixed value of 1k for no_std (for now)
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
pub fn current_milliseconds() -> u64 { pub fn current_milliseconds() -> u64 {
1000 1000