From 762461e75d3daf253aad4754ad6c36314b828c68 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Sat, 13 Jul 2024 16:34:01 +0000 Subject: [PATCH 01/32] introducing MappingMutator --- libafl/src/mutators/mapping.rs | 65 ++++++++++++++++++++++++++++++++++ libafl/src/mutators/mod.rs | 2 ++ 2 files changed, 67 insertions(+) create mode 100644 libafl/src/mutators/mapping.rs diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs new file mode 100644 index 00000000000..1731329bfb5 --- /dev/null +++ b/libafl/src/mutators/mapping.rs @@ -0,0 +1,65 @@ +//! Allowing mixing and matching between [`Mutator`] and [`crate::inputs::Input`] types. +use std::borrow::Cow; + +use crate::{ + mutators::{MutationResult, Mutator}, + Error, +}; + +use libafl_bolts::Named; + +/// Mutator that allows using [`Mutator`]s that expect different [`crate::inputs::Input`] types. +/// +/// Only use when necessary, as it introduces a function call on each mutation. +/// +/// ```rust +/// use libafl::{ +/// inputs::{BytesInput, HasMutatorBytes}, +/// mutators::{MappingMutator, Mutator, MutationResult}, +/// prelude::{ByteIncMutator, NopState}, +/// }; +/// +/// struct CustomInput(pub BytesInput); // dummy custom input that shows how to apply mutators for any BytesInput +/// +/// let mut mutator = MappingMutator::new( +/// |custom_input: &mut CustomInput| -> &mut BytesInput { &mut custom_input.0 }, +/// ByteIncMutator::new(), // example for a mutator of a different type +/// ); +/// +/// let mut state: NopState = NopState::new(); +/// +/// let input_content = 1; +/// let mut input = CustomInput(BytesInput::new(vec![input_content])); +/// +/// let res = mutator.mutate(&mut state, &mut input); +/// +/// assert_eq!(res.unwrap(), MutationResult::Mutated); +/// assert_eq!(input.0.bytes(), vec![input_content + 1]); +/// ``` +#[derive(Debug)] +pub struct MappingMutator { + mapper: for<'a> fn(&'a mut OI) -> &'a mut II, + inner: M, +} + +impl MappingMutator { + /// Creates a new [`MappingMutator`] based on another [`Mutator`] and a function that maps the outer [`crate::inputs::Input`] to what the inner [`Mutator`] expects. + pub fn new(mapper: for<'a> fn(&'a mut OI) -> &'a mut II, inner: M) -> Self { + Self { mapper, inner } + } +} + +impl Mutator for MappingMutator +where + M: Mutator, +{ + fn mutate(&mut self, state: &mut S, input: &mut OI) -> Result { + self.inner.mutate(state, (self.mapper)(input)) + } +} + +impl Named for MappingMutator { + fn name(&self) -> &Cow<'static, str> { + &Cow::Borrowed("MappingMutator") + } +} diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index 0bea70e79d9..d3f52d96487 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -17,6 +17,8 @@ pub mod gramatron; pub use gramatron::*; pub mod grimoire; pub use grimoire::*; +pub mod mapping; +pub use mapping::*; pub mod tuneable; pub use tuneable::*; From 95716193ac39b1ef54fdcaf5f79f32651cbf5100 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 17 Jul 2024 19:53:53 +0000 Subject: [PATCH 02/32] extending mapping mutators --- libafl/src/mutators/havoc_mutations.rs | 359 +++++++++++++++++++++++++ libafl/src/mutators/mapping.rs | 207 +++++++++++--- libafl/src/mutators/mod.rs | 2 + libafl/src/mutators/mutations.rs | 183 +++++++++++-- libafl/src/mutators/scheduled.rs | 126 +-------- 5 files changed, 694 insertions(+), 183 deletions(-) create mode 100644 libafl/src/mutators/havoc_mutations.rs diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs new file mode 100644 index 00000000000..5a83958f1d3 --- /dev/null +++ b/libafl/src/mutators/havoc_mutations.rs @@ -0,0 +1,359 @@ +//! [`Mutator`] collection equivalent to AFL++'s havoc mutations + +use crate::mutators::{ + mapping::{ + FunctionMappingMutator, MutVecMappingMutator, ToFunctionMappingMutatorMapper, + ToMutVecMappingMutatorMapper, + }, + mutations::{ + BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator, ByteIncMutator, + ByteInterestingMutator, ByteNegMutator, ByteRandMutator, BytesCopyMutator, + BytesDeleteMutator, BytesExpandMutator, BytesInsertCopyMutator, BytesInsertMutator, + BytesRandInsertMutator, BytesRandSetMutator, BytesSetMutator, BytesSwapMutator, + CrossoverInsertMutator, CrossoverReplaceMutator, DwordAddMutator, DwordInterestingMutator, + MappedCrossoverInsertMutator, MappedCrossoverReplaceMutator, QwordAddMutator, + WordAddMutator, WordInterestingMutator, + }, +}; + +use alloc::vec::Vec; +use libafl_bolts::tuples::{Map, Merge}; +use tuple_list::{tuple_list, tuple_list_type}; + +/// Tuple type of the mutations that compose the Havoc mutator without crossover mutations +pub type HavocMutationsNoCrossoverType = tuple_list_type!( + BitFlipMutator, + ByteFlipMutator, + ByteIncMutator, + ByteDecMutator, + ByteNegMutator, + ByteRandMutator, + ByteAddMutator, + WordAddMutator, + DwordAddMutator, + QwordAddMutator, + ByteInterestingMutator, + WordInterestingMutator, + DwordInterestingMutator, + BytesDeleteMutator, + BytesDeleteMutator, + BytesDeleteMutator, + BytesDeleteMutator, + BytesExpandMutator, + BytesInsertMutator, + BytesRandInsertMutator, + BytesSetMutator, + BytesRandSetMutator, + BytesCopyMutator, + BytesInsertCopyMutator, + BytesSwapMutator, +); + +/// Tuple type of the mutations that compose the Havoc mutator without crossover mutations for mapped input types +pub type MappedHavocMutationsNoCrossoverType = tuple_list_type!( + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, +); + +/// Tuple type of the mutations that compose the Havoc mutator without crossover mutations for mapped optional input types +// pub type OptionMappedHavocMutationsNoCrossoverType = tuple_list_type!( +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// FunctionMappingMutator< +// OptionMappingMutator>, +// I, +// Option<&mut Vec>, +// >, +// ); + +/// Tuple type of the mutations that compose the Havoc mutator's crossover mutations +pub type HavocCrossoverType = + tuple_list_type!(CrossoverInsertMutator, CrossoverReplaceMutator); + +/// Tuple type of the mutations that compose the Havoc mutator's crossover mutations for mapped input types +pub type MappedHavocCrossoverType = tuple_list_type!( + MappedCrossoverInsertMutator, + MappedCrossoverReplaceMutator +); + +/// Tuple type of the mutations that compose the Havoc mutator +pub type HavocMutationsType = tuple_list_type!( + BitFlipMutator, + ByteFlipMutator, + ByteIncMutator, + ByteDecMutator, + ByteNegMutator, + ByteRandMutator, + ByteAddMutator, + WordAddMutator, + DwordAddMutator, + QwordAddMutator, + ByteInterestingMutator, + WordInterestingMutator, + DwordInterestingMutator, + BytesDeleteMutator, + BytesDeleteMutator, + BytesDeleteMutator, + BytesDeleteMutator, + BytesExpandMutator, + BytesInsertMutator, + BytesRandInsertMutator, + BytesSetMutator, + BytesRandSetMutator, + BytesCopyMutator, + BytesInsertCopyMutator, + BytesSwapMutator, + CrossoverInsertMutator, + CrossoverReplaceMutator, +); + +/// Tuple type of the mutations that compose the Havoc mutator for mapped input types +pub type MappedHavocMutationsType = tuple_list_type!( + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + FunctionMappingMutator, I, Vec>, + MappedCrossoverInsertMutator, + MappedCrossoverReplaceMutator, +); + +/// Get the mutations that compose the Havoc mutator (only applied to single inputs) +#[must_use] +pub fn havoc_mutations_no_crossover() -> HavocMutationsNoCrossoverType { + tuple_list!( + BitFlipMutator::new(), + ByteFlipMutator::new(), + ByteIncMutator::new(), + ByteDecMutator::new(), + ByteNegMutator::new(), + ByteRandMutator::new(), + ByteAddMutator::new(), + WordAddMutator::new(), + DwordAddMutator::new(), + QwordAddMutator::new(), + ByteInterestingMutator::new(), + WordInterestingMutator::new(), + DwordInterestingMutator::new(), + BytesDeleteMutator::new(), + BytesDeleteMutator::new(), + BytesDeleteMutator::new(), + BytesDeleteMutator::new(), + BytesExpandMutator::new(), + BytesInsertMutator::new(), + BytesRandInsertMutator::new(), + BytesSetMutator::new(), + BytesRandSetMutator::new(), + BytesCopyMutator::new(), + BytesInsertCopyMutator::new(), + BytesSwapMutator::new(), + ) +} + +/// Get the mutations that compose the Havoc mutator (only applied to single inputs) for mapped input types +#[must_use] +pub fn mapped_havoc_mutations_no_crossover( + mapper: for<'b> fn(&'b mut I) -> &'b mut Vec, +) -> MappedHavocMutationsNoCrossoverType { + havoc_mutations_no_crossover() + .map(ToMutVecMappingMutatorMapper) + .map(ToFunctionMappingMutatorMapper::new(mapper)) +} + +/// Get the mutations that compose the Havoc mutator's crossover strategy +#[must_use] +pub fn havoc_crossover() -> HavocCrossoverType { + tuple_list!( + CrossoverInsertMutator::new(), + CrossoverReplaceMutator::new(), + ) +} + +/// Get the mutations that compose the Havoc mutator's crossover strategy for mapped input types +#[must_use] +pub fn mapped_havoc_crossover( + mapper: for<'b> fn(&'b I) -> &'b Vec, + mapper_mut: for<'b> fn(&'b mut I) -> &'b mut Vec, +) -> MappedHavocCrossoverType { + tuple_list!( + MappedCrossoverInsertMutator::new(mapper, mapper_mut), + MappedCrossoverReplaceMutator::new(mapper, mapper_mut), + ) +} + +/// Get the mutations that compose the Havoc mutator +#[must_use] +pub fn havoc_mutations() -> HavocMutationsType { + havoc_mutations_no_crossover().merge(havoc_crossover()) +} + +/// Get the mutations that compose the Havoc mutator for mapped input types +#[must_use] +pub fn mapped_havoc_mutations( + mapper: for<'b> fn(&'b I) -> &'b Vec, + mapper_mut: for<'b> fn(&'b mut I) -> &'b mut Vec, +) -> MappedHavocMutationsType { + mapped_havoc_mutations_no_crossover(mapper_mut) + .merge(mapped_havoc_crossover(mapper, mapper_mut)) +} diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index 1731329bfb5..5120a27f179 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -2,64 +2,193 @@ use std::borrow::Cow; use crate::{ + inputs::MutVecInput, mutators::{MutationResult, Mutator}, Error, }; -use libafl_bolts::Named; - -/// Mutator that allows using [`Mutator`]s that expect different [`crate::inputs::Input`] types. -/// -/// Only use when necessary, as it introduces a function call on each mutation. -/// -/// ```rust -/// use libafl::{ -/// inputs::{BytesInput, HasMutatorBytes}, -/// mutators::{MappingMutator, Mutator, MutationResult}, -/// prelude::{ByteIncMutator, NopState}, -/// }; -/// -/// struct CustomInput(pub BytesInput); // dummy custom input that shows how to apply mutators for any BytesInput -/// -/// let mut mutator = MappingMutator::new( -/// |custom_input: &mut CustomInput| -> &mut BytesInput { &mut custom_input.0 }, -/// ByteIncMutator::new(), // example for a mutator of a different type -/// ); -/// -/// let mut state: NopState = NopState::new(); -/// -/// let input_content = 1; -/// let mut input = CustomInput(BytesInput::new(vec![input_content])); -/// -/// let res = mutator.mutate(&mut state, &mut input); -/// -/// assert_eq!(res.unwrap(), MutationResult::Mutated); -/// assert_eq!(input.0.bytes(), vec![input_content + 1]); -/// ``` +use alloc::vec::Vec; +use libafl_bolts::{tuples::MappingFunctor, Named}; + #[derive(Debug)] -pub struct MappingMutator { - mapper: for<'a> fn(&'a mut OI) -> &'a mut II, +pub struct MutVecMappingMutator { inner: M, } -impl MappingMutator { - /// Creates a new [`MappingMutator`] based on another [`Mutator`] and a function that maps the outer [`crate::inputs::Input`] to what the inner [`Mutator`] expects. - pub fn new(mapper: for<'a> fn(&'a mut OI) -> &'a mut II, inner: M) -> Self { +impl MutVecMappingMutator { + pub fn new(inner: M) -> Self { + Self { inner } + } +} + +impl Mutator, S> for MutVecMappingMutator +where + M: for<'a> Mutator, S>, +{ + fn mutate(&mut self, state: &mut S, input: &mut Vec) -> Result { + self.inner.mutate(state, &mut input.into()) + } +} + +impl Named for MutVecMappingMutator +where + M: Named, +{ + fn name(&self) -> &Cow<'static, str> { + &Cow::Borrowed("MutVecMappingMutator") + } +} + +#[derive(Debug)] +pub struct ToMutVecMappingMutatorMapper; + +impl MappingFunctor for ToMutVecMappingMutatorMapper { + type Output = MutVecMappingMutator; + + fn apply(&mut self, from: M) -> Self::Output { + MutVecMappingMutator::new(from) + } +} + +#[derive(Debug)] +pub struct FunctionMappingMutator { + mapper: fn(&mut IO) -> &mut II, + inner: M, +} + +impl FunctionMappingMutator { + fn new(mapper: fn(&mut IO) -> &mut II, inner: M) -> Self { Self { mapper, inner } } } -impl Mutator for MappingMutator +impl Mutator for FunctionMappingMutator where M: Mutator, { - fn mutate(&mut self, state: &mut S, input: &mut OI) -> Result { + fn mutate(&mut self, state: &mut S, input: &mut IO) -> Result { self.inner.mutate(state, (self.mapper)(input)) } } -impl Named for MappingMutator { +impl Named for FunctionMappingMutator +where + M: Named, +{ + fn name(&self) -> &Cow<'static, str> { + &Cow::Borrowed("FunctionMappingMutator") + } +} + +#[derive(Debug)] +pub struct ToFunctionMappingMutatorMapper { + mapper: for<'a> fn(&'a mut IO) -> &'a mut II, +} + +impl ToFunctionMappingMutatorMapper { + pub fn new(mapper: for<'a> fn(&'a mut IO) -> &'a mut II) -> Self { + Self { mapper } + } +} + +impl MappingFunctor for ToFunctionMappingMutatorMapper { + type Output = FunctionMappingMutator; + + fn apply(&mut self, from: M) -> Self::Output { + FunctionMappingMutator::new(self.mapper, from) + } +} + +#[derive(Debug)] +pub struct OptionMappingMutator { + inner: M, +} + +impl OptionMappingMutator { + pub fn new(inner: M) -> Self { + Self { inner } + } +} + +impl Mutator, S> for OptionMappingMutator +where + M: Mutator, +{ + fn mutate(&mut self, state: &mut S, input: &mut Option) -> Result { + match input { + None => Ok(MutationResult::Skipped), + Some(i) => self.inner.mutate(state, i), + } + } +} + +impl Named for OptionMappingMutator +where + M: Named, +{ fn name(&self) -> &Cow<'static, str> { - &Cow::Borrowed("MappingMutator") + &Cow::Borrowed("OptionMappingMutator") + } +} + +#[derive(Debug)] +pub struct ToOptionMappingMutatorMapper; + +impl MappingFunctor for ToOptionMappingMutatorMapper { + type Output = OptionMappingMutator; + + fn apply(&mut self, from: M) -> Self::Output { + OptionMappingMutator::new(from) + } +} + +#[cfg(test)] +mod test { + + use libafl_bolts::tuples::Map; + use tuple_list::tuple_list; + + use crate::{ + inputs::MutVecInput, + prelude::{ByteIncMutator, MutationResult, Mutator, NopState}, + }; + + use super::{OptionMappingMutator, ToOptionMappingMutatorMapper}; + + #[test] + fn test_option_mapping_mutator() { + let inner = ByteIncMutator::new(); + let mut outer = OptionMappingMutator::new(inner); + + let mut input_raw = vec![1]; + let input: MutVecInput = (&mut input_raw).into(); + let mut input_wrapped = Some(input); + let mut state: NopState> = NopState::new(); + let res = outer.mutate(&mut state, &mut input_wrapped).unwrap(); + assert_eq!(res, MutationResult::Mutated); + assert_eq!(input_raw, vec![2]); + + let mut empty_input: Option = None; + let res2 = outer.mutate(&mut state, &mut empty_input).unwrap(); + assert_eq!(res2, MutationResult::Skipped); + } + + #[test] + fn test_option_mapping_mutator_tuple_mapper() { + let inner = tuple_list!(ByteIncMutator::new()); + let outer_list = inner.map(ToOptionMappingMutatorMapper); + let mut outer = outer_list.0; + + let mut input_raw = vec![1]; + let input: MutVecInput = (&mut input_raw).into(); + let mut input_wrapped = Some(input); + let mut state: NopState> = NopState::new(); + let res = outer.mutate(&mut state, &mut input_wrapped).unwrap(); + assert_eq!(res, MutationResult::Mutated); + assert_eq!(input_raw, vec![2]); + + let mut empty_input: Option = None; + let res2 = outer.mutate(&mut state, &mut empty_input).unwrap(); + assert_eq!(res2, MutationResult::Skipped); } } diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index d3f52d96487..efa5e072b7e 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -9,6 +9,8 @@ pub use mutations::*; pub mod token_mutations; use serde::{Deserialize, Serialize}; pub use token_mutations::*; +pub mod havoc_mutations; +pub use havoc_mutations::*; pub mod encoded_mutations; pub use encoded_mutations::*; pub mod mopt_mutator; diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index 6351ec05df4..aa38b976991 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -10,7 +10,7 @@ use libafl_bolts::{rands::Rand, Named}; use crate::{ corpus::Corpus, - inputs::HasMutatorBytes, + inputs::{HasMutatorBytes, MutVecInput, UsesInput}, mutators::{MutationResult, Mutator}, random_corpus_id_with_disabled, state::{HasCorpus, HasMaxSize, HasRand}, @@ -1030,12 +1030,12 @@ pub struct CrossoverInsertMutator { } impl CrossoverInsertMutator { - pub(crate) fn crossover_insert( + pub(crate) fn crossover_insert( input: &mut I, size: usize, target: usize, range: Range, - other: &I2, + other: &[u8], ) -> MutationResult { input.resize(size + range.len(), 0); unsafe { @@ -1048,13 +1048,7 @@ impl CrossoverInsertMutator { } unsafe { - buffer_copy( - input.bytes_mut(), - other.bytes(), - range.start, - target, - range.len(), - ); + buffer_copy(input.bytes_mut(), other, range.start, target, range.len()); } MutationResult::Mutated } @@ -1097,7 +1091,13 @@ where // No need to load the input again, it'll still be cached. let other = other_testcase.input().as_ref().unwrap(); - Ok(Self::crossover_insert(input, size, target, range, other)) + Ok(Self::crossover_insert( + input, + size, + target, + range, + other.bytes(), + )) } } @@ -1125,20 +1125,14 @@ pub struct CrossoverReplaceMutator { } impl CrossoverReplaceMutator { - pub(crate) fn crossover_replace( + pub(crate) fn crossover_replace( input: &mut I, target: usize, range: Range, - other: &I2, + other: &[u8], ) -> MutationResult { unsafe { - buffer_copy( - input.bytes_mut(), - other.bytes(), - range.start, - target, - range.len(), - ); + buffer_copy(input.bytes_mut(), other, range.start, target, range.len()); } MutationResult::Mutated } @@ -1180,7 +1174,7 @@ where // No need to load the input again, it'll still be cached. let other = other_testcase.input().as_ref().unwrap(); - Ok(Self::crossover_replace(input, target, range, other)) + Ok(Self::crossover_replace(input, target, range, other.bytes())) } } @@ -1200,6 +1194,153 @@ impl CrossoverReplaceMutator { } } } +/// Crossover insert mutation for inputs mapped to a bytes vector +#[derive(Debug)] +pub struct MappedCrossoverInsertMutator { + input_from_corpus_mapper: for<'a> fn(&'a I) -> &Vec, + input_to_mutate_mapper: for<'a> fn(&'a mut I) -> &mut Vec, +} + +impl Mutator for MappedCrossoverInsertMutator +where + S: HasCorpus + HasMaxSize + HasRand + UsesInput, +{ + fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result { + let mapped_input: &mut MutVecInput = &mut (self.input_to_mutate_mapper)(input).into(); + let size = mapped_input.bytes().len(); + let max_size = state.max_size(); + if size >= max_size { + return Ok(MutationResult::Skipped); + } + + let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut()); + // We don't want to use the testcase we're already using for splicing + if let Some(cur) = state.corpus().current() { + if id == *cur { + return Ok(MutationResult::Skipped); + } + } + + let other_size = { + let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); + let other_input = other_testcase.load_input(state.corpus())?; + (self.input_from_corpus_mapper)(other_input).len() + }; + + if other_size < 2 { + return Ok(MutationResult::Skipped); + } + + let range = rand_range(state, other_size, min(other_size, max_size - size)); + let target = state.rand_mut().below(size); // TODO: fix bug if size is 0 + + let other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); + // No need to load the input again, it'll still be cached. + let other = &mut other_testcase.input().as_ref().unwrap(); + let mapped_other = (self.input_from_corpus_mapper)(other); + + Ok(CrossoverInsertMutator::crossover_insert( + mapped_input, + size, + target, + range, + mapped_other, + )) + } +} + +impl Named for MappedCrossoverInsertMutator { + fn name(&self) -> &Cow<'static, str> { + static NAME: Cow<'static, str> = Cow::Borrowed("MappedCrossoverInsertMutator"); + &NAME + } +} + +impl MappedCrossoverInsertMutator { + /// Creates a new [`MappedCrossoverInsertMutator`]. + pub fn new( + input_from_corpus_mapper: for<'a> fn(&'a I) -> &'a Vec, + input_to_mutate_mapper: for<'a> fn(&'a mut I) -> &'a mut Vec, + ) -> Self { + Self { + input_from_corpus_mapper, + input_to_mutate_mapper, + } + } +} + +/// Crossover replace mutation for inputs mapped to a bytes vector +#[derive(Debug)] +pub struct MappedCrossoverReplaceMutator { + input_from_corpus_mapper: for<'a> fn(&'a I) -> &Vec, + input_to_mutate_mapper: for<'a> fn(&'a mut I) -> &mut Vec, +} + +impl Mutator for MappedCrossoverReplaceMutator +where + S: HasCorpus + HasRand + HasMaxSize + UsesInput, +{ + fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result { + let mapped_input: &mut MutVecInput = &mut (self.input_to_mutate_mapper)(input).into(); + let size = mapped_input.bytes().len(); + if size == 0 { + return Ok(MutationResult::Skipped); + } + + let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut()); + // We don't want to use the testcase we're already using for splicing + if let Some(cur) = state.corpus().current() { + if id == *cur { + return Ok(MutationResult::Skipped); + } + } + + let other_size = { + let mut testcase = state.corpus().get_from_all(id)?.borrow_mut(); + let other_input = testcase.load_input(state.corpus())?; + (self.input_from_corpus_mapper)(other_input).len() + }; + + if other_size < 2 { + return Ok(MutationResult::Skipped); + } + + let target = state.rand_mut().below(size); + let range = rand_range(state, other_size, min(other_size, size - target)); + + let other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); + // No need to load the input again, it'll still be cached. + let other = &mut other_testcase.input().as_ref().unwrap(); + let mapped_other = (self.input_from_corpus_mapper)(other); + + Ok(CrossoverReplaceMutator::crossover_replace( + mapped_input, + target, + range, + mapped_other, + )) + } +} + +impl Named for MappedCrossoverReplaceMutator { + fn name(&self) -> &Cow<'static, str> { + static NAME: Cow<'static, str> = Cow::Borrowed("MappedCrossoverReplaceMutator"); + &NAME + } +} + +impl MappedCrossoverReplaceMutator { + /// Creates a new [`MappedCrossoverReplaceMutator`]. + pub fn new( + input_from_corpus_mapper: for<'a> fn(&'a I) -> &Vec, + input_to_mutate_mapper: for<'a> fn(&'a mut I) -> &mut Vec, + ) -> Self { + Self { + input_from_corpus_mapper, + input_to_mutate_mapper, + } + } +} /// Returns the first and last diff position between the given vectors, stopping at the min len fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) { diff --git a/libafl/src/mutators/scheduled.rs b/libafl/src/mutators/scheduled.rs index 6b00b506be1..850cfc959dd 100644 --- a/libafl/src/mutators/scheduled.rs +++ b/libafl/src/mutators/scheduled.rs @@ -9,7 +9,7 @@ use core::{ use libafl_bolts::{ rands::Rand, - tuples::{tuple_list, tuple_list_type, Merge, NamedTuple}, + tuples::{tuple_list, tuple_list_type, NamedTuple}, Named, }; use serde::{Deserialize, Serialize}; @@ -18,14 +18,6 @@ use super::MutationId; use crate::{ corpus::{Corpus, CorpusId}, mutators::{ - mutations::{ - BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator, ByteIncMutator, - ByteInterestingMutator, ByteNegMutator, ByteRandMutator, BytesCopyMutator, - BytesDeleteMutator, BytesExpandMutator, BytesInsertCopyMutator, BytesInsertMutator, - BytesRandInsertMutator, BytesRandSetMutator, BytesSetMutator, BytesSwapMutator, - CrossoverInsertMutator, CrossoverReplaceMutator, DwordAddMutator, - DwordInterestingMutator, QwordAddMutator, WordAddMutator, WordInterestingMutator, - }, token_mutations::{TokenInsert, TokenReplace}, MutationResult, Mutator, MutatorsTuple, }, @@ -221,117 +213,6 @@ where } } -/// Tuple type of the mutations that compose the Havoc mutator without crossover mutations -pub type HavocMutationsNoCrossoverType = tuple_list_type!( - BitFlipMutator, - ByteFlipMutator, - ByteIncMutator, - ByteDecMutator, - ByteNegMutator, - ByteRandMutator, - ByteAddMutator, - WordAddMutator, - DwordAddMutator, - QwordAddMutator, - ByteInterestingMutator, - WordInterestingMutator, - DwordInterestingMutator, - BytesDeleteMutator, - BytesDeleteMutator, - BytesDeleteMutator, - BytesDeleteMutator, - BytesExpandMutator, - BytesInsertMutator, - BytesRandInsertMutator, - BytesSetMutator, - BytesRandSetMutator, - BytesCopyMutator, - BytesInsertCopyMutator, - BytesSwapMutator, -); - -/// Tuple type of the mutations that compose the Havoc mutator's crossover mutations -pub type HavocCrossoverType = - tuple_list_type!(CrossoverInsertMutator, CrossoverReplaceMutator); - -/// Tuple type of the mutations that compose the Havoc mutator -pub type HavocMutationsType = tuple_list_type!( - BitFlipMutator, - ByteFlipMutator, - ByteIncMutator, - ByteDecMutator, - ByteNegMutator, - ByteRandMutator, - ByteAddMutator, - WordAddMutator, - DwordAddMutator, - QwordAddMutator, - ByteInterestingMutator, - WordInterestingMutator, - DwordInterestingMutator, - BytesDeleteMutator, - BytesDeleteMutator, - BytesDeleteMutator, - BytesDeleteMutator, - BytesExpandMutator, - BytesInsertMutator, - BytesRandInsertMutator, - BytesSetMutator, - BytesRandSetMutator, - BytesCopyMutator, - BytesInsertCopyMutator, - BytesSwapMutator, - CrossoverInsertMutator, - CrossoverReplaceMutator, -); - -/// Get the mutations that compose the Havoc mutator (only applied to single inputs) -#[must_use] -pub fn havoc_mutations_no_crossover() -> HavocMutationsNoCrossoverType { - tuple_list!( - BitFlipMutator::new(), - ByteFlipMutator::new(), - ByteIncMutator::new(), - ByteDecMutator::new(), - ByteNegMutator::new(), - ByteRandMutator::new(), - ByteAddMutator::new(), - WordAddMutator::new(), - DwordAddMutator::new(), - QwordAddMutator::new(), - ByteInterestingMutator::new(), - WordInterestingMutator::new(), - DwordInterestingMutator::new(), - BytesDeleteMutator::new(), - BytesDeleteMutator::new(), - BytesDeleteMutator::new(), - BytesDeleteMutator::new(), - BytesExpandMutator::new(), - BytesInsertMutator::new(), - BytesRandInsertMutator::new(), - BytesSetMutator::new(), - BytesRandSetMutator::new(), - BytesCopyMutator::new(), - BytesInsertCopyMutator::new(), - BytesSwapMutator::new(), - ) -} - -/// Get the mutations that compose the Havoc mutator's crossover strategy -#[must_use] -pub fn havoc_crossover() -> HavocCrossoverType { - tuple_list!( - CrossoverInsertMutator::new(), - CrossoverReplaceMutator::new(), - ) -} - -/// Get the mutations that compose the Havoc mutator -#[must_use] -pub fn havoc_mutations() -> HavocMutationsType { - havoc_mutations_no_crossover().merge(havoc_crossover()) -} - /// Get the mutations that uses the Tokens metadata #[must_use] pub fn tokens_mutations() -> tuple_list_type!(TokenInsert, TokenReplace) { @@ -482,9 +363,8 @@ mod tests { feedbacks::ConstFeedback, inputs::{BytesInput, HasMutatorBytes}, mutators::{ - mutations::SpliceMutator, - scheduled::{havoc_mutations, StdScheduledMutator}, - Mutator, + havoc_mutations::havoc_mutations, mutations::SpliceMutator, + scheduled::StdScheduledMutator, Mutator, }, state::StdState, }; From fda42e75e66aab8720310422404ea65828ca6cf4 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 17 Jul 2024 19:54:03 +0000 Subject: [PATCH 03/32] adding example fuzzer --- fuzzers/baby_fuzzer_custom_input/Cargo.toml | 20 +++ fuzzers/baby_fuzzer_custom_input/README.md | 7 + fuzzers/baby_fuzzer_custom_input/src/input.rs | 67 ++++++++ fuzzers/baby_fuzzer_custom_input/src/main.rs | 143 ++++++++++++++++++ 4 files changed, 237 insertions(+) create mode 100644 fuzzers/baby_fuzzer_custom_input/Cargo.toml create mode 100644 fuzzers/baby_fuzzer_custom_input/README.md create mode 100644 fuzzers/baby_fuzzer_custom_input/src/input.rs create mode 100644 fuzzers/baby_fuzzer_custom_input/src/main.rs diff --git a/fuzzers/baby_fuzzer_custom_input/Cargo.toml b/fuzzers/baby_fuzzer_custom_input/Cargo.toml new file mode 100644 index 00000000000..b9eec645570 --- /dev/null +++ b/fuzzers/baby_fuzzer_custom_input/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "baby_fuzzer_custom_input" +version = "0.1.0" +authors = ["Valentin Huber "] +edition = "2021" + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" +lto = true +codegen-units = 1 +opt-level = 3 +debug = true + +[dependencies] +libafl = { path = "../../libafl/" } +libafl_bolts = { path = "../../libafl_bolts/" } +serde = "*" diff --git a/fuzzers/baby_fuzzer_custom_input/README.md b/fuzzers/baby_fuzzer_custom_input/README.md new file mode 100644 index 00000000000..99514c9b33c --- /dev/null +++ b/fuzzers/baby_fuzzer_custom_input/README.md @@ -0,0 +1,7 @@ +# Baby fuzzer + +This is a minimalistic fuzzer demonstrating how to employ mapping mutators to use default mutators on custom inputs. Custom inputs are necessary when the input to your program is a combination of parts, especially when those parts have different data types. Check multipart inputs if you have an input consisting of multiple parts of the same datatype and you don't need your mutation scheduler to be able to select which mutation is performed on which part. + +The fuzzer runs on a single core until a crash occurs and then exits. The tested program is a simple Rust function without any instrumentation. For real fuzzing, you will want to add some sort to add coverage or other feedback. + +You can run this example using `cargo run`. \ No newline at end of file diff --git a/fuzzers/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby_fuzzer_custom_input/src/input.rs new file mode 100644 index 00000000000..829fb286845 --- /dev/null +++ b/fuzzers/baby_fuzzer_custom_input/src/input.rs @@ -0,0 +1,67 @@ +use libafl_bolts::rands::Rand; +use serde::{Deserialize, Serialize}; +use std::hash::{DefaultHasher, Hash, Hasher}; + +use libafl::{ + corpus::CorpusId, generators::Generator, inputs::Input, state::HasRand, Error, SerdeAny, +}; + +#[derive(Serialize, Deserialize, Clone, Debug, Hash, SerdeAny)] +pub struct CustomInput { + pub byte_array: Vec, + pub optional_byte_array: Option>, + pub boolean: bool, +} + +/// Hash-based implementation +impl Input for CustomInput { + fn generate_name(&self, _id: Option) -> String { + let mut hasher = DefaultHasher::new(); + self.hash(&mut hasher); + format!("{:016x}", hasher.finish()) + } +} + +pub struct CustomInputGenerator { + pub max_len: usize, +} + +impl CustomInputGenerator { + pub fn new(max_len: usize) -> Self { + Self { max_len } + } +} + +impl Generator for CustomInputGenerator +where + S: HasRand, +{ + fn generate(&mut self, state: &mut S) -> Result { + let byte_array = generate_bytes(self.max_len, state); + let optional_byte_array = state + .rand_mut() + .coinflip(0.5) + .then(|| generate_bytes(self.max_len, state)); + let boolean = state.rand_mut().coinflip(0.5); + + Ok(CustomInput { + byte_array, + optional_byte_array, + boolean, + }) + } +} + +fn generate_bytes(length: usize, state: &mut S) -> Vec { + let rand = state.rand_mut(); + Vec::with_capacity(rand.below(length)) + .iter() + .map(|_: &u8| rand.next() as u8) + .collect() +} + +// impl Named for CustomInput { +// fn name(&self) -> &Cow<'static, str> { +// &Cow::Borrowed("CustomInput") +// } +// } diff --git a/fuzzers/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby_fuzzer_custom_input/src/main.rs new file mode 100644 index 00000000000..f591b5141ed --- /dev/null +++ b/fuzzers/baby_fuzzer_custom_input/src/main.rs @@ -0,0 +1,143 @@ +mod input; + +#[cfg(windows)] +use std::ptr::write_volatile; +use std::{path::PathBuf, ptr::write}; + +use input::{CustomInput, CustomInputGenerator}; +use libafl::monitors::SimpleMonitor; +use libafl::mutators::{ + havoc_mutations_no_crossover, mapped_havoc_mutations, OptionMappingMutator, + ToFunctionMappingMutatorMapper, ToMutVecMappingMutatorMapper, ToOptionMappingMutatorMapper, +}; +use libafl::{ + corpus::{InMemoryCorpus, OnDiskCorpus}, + events::SimpleEventManager, + executors::{inprocess::InProcessExecutor, ExitKind}, + feedbacks::{CrashFeedback, MaxMapFeedback}, + fuzzer::{Fuzzer, StdFuzzer}, + mutators::scheduled::StdScheduledMutator, + observers::StdMapObserver, + schedulers::QueueScheduler, + stages::mutational::StdMutationalStage, + state::StdState, +}; +use libafl_bolts::tuples::{Map, Merge}; +use libafl_bolts::{current_nanos, rands::StdRand, tuples::tuple_list}; + +/// Coverage map with explicit assignments due to the lack of instrumentation +static mut SIGNALS: [u8; 16] = [0; 16]; +static mut SIGNALS_PTR: *mut u8 = unsafe { SIGNALS.as_mut_ptr() }; + +/// Assign a signal to the signals map +fn signals_set(idx: usize) { + unsafe { write(SIGNALS_PTR.add(idx), 1) }; +} + +#[allow(clippy::similar_names, clippy::manual_assert)] +pub fn main() { + // The closure that we want to fuzz + let mut harness = |input: &CustomInput| { + signals_set(0); + if input.boolean { + signals_set(1); + if input.byte_array == vec![b'a', b'b', b'c'] { + signals_set(2); + if input.optional_byte_array == Some(vec![b'a', b'b', b'c']) { + #[cfg(unix)] + panic!("Artificial bug triggered =)"); + + // panic!() raises a STATUS_STACK_BUFFER_OVERRUN exception which cannot be caught by the exception handler. + // Here we make it raise STATUS_ACCESS_VIOLATION instead. + // Extending the windows exception handler is a TODO. Maybe we can refer to what winafl code does. + // https://github.com/googleprojectzero/winafl/blob/ea5f6b85572980bb2cf636910f622f36906940aa/winafl.c#L728 + #[cfg(windows)] + unsafe { + write_volatile(0 as *mut u32, 0); + } + } + } + } + ExitKind::Ok + }; + + // Create an observation channel using the signals map + let observer = unsafe { StdMapObserver::from_mut_ptr("signals", SIGNALS_PTR, SIGNALS.len()) }; + + // Feedback to rate the interestingness of an input + let mut feedback = MaxMapFeedback::new(&observer); + + // A feedback to choose if an input is a solution or not + let mut objective = CrashFeedback::new(); + + // create a State from scratch + let mut state = StdState::new( + // RNG + StdRand::with_seed(current_nanos()), + // Corpus that will be evolved, we keep it in memory for performance + InMemoryCorpus::new(), + // Corpus in which we store solutions (crashes in this example), + // on disk so the user can get them after stopping the fuzzer + OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(), + // States of the feedbacks. + // The feedbacks can report the data that should persist in the State. + &mut feedback, + // Same for objective feedbacks + &mut objective, + ) + .unwrap(); + + // The Monitor trait define how the fuzzer stats are displayed to the user + let mon = SimpleMonitor::new(|s| println!("{s}")); + + // The event manager handle the various events generated during the fuzzing loop + // such as the notification of the addition of a new item to the corpus + let mut mgr = SimpleEventManager::new(mon); + + // A queue policy to get testcasess from the corpus + let scheduler = QueueScheduler::new(); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); + + // Create the executor for an in-process function with just one observer + let mut executor = InProcessExecutor::new( + &mut harness, + tuple_list!(observer), + &mut fuzzer, + &mut state, + &mut mgr, + ) + .expect("Failed to create the Executor"); + + // Generator of printable bytearrays of max size 32 + let mut generator = CustomInputGenerator::new(10); + + // Generate 8 initial inputs + state + .generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 8) + .expect("Failed to generate the initial corpus"); + + // Setup a mutational stage with a basic bytes mutator + let mutator = StdScheduledMutator::new( + mapped_havoc_mutations( + |e: &CustomInput| &e.byte_array, + |e: &mut CustomInput| &mut e.byte_array, + ) + .merge( + havoc_mutations_no_crossover() + .map(ToMutVecMappingMutatorMapper) + .map(ToOptionMappingMutatorMapper) + .map(ToFunctionMappingMutatorMapper::new( + |e: &mut CustomInput| &mut e.optional_byte_array, + )), + ), + ); + let mut stages = tuple_list!(StdMutationalStage::new(mutator)); + + fuzzer + .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) + .expect("Error in the fuzzing loop"); +} + +static mut ARRAY: Vec = Vec::new(); From 1f2507d1776a5028b8595392a55cd8c793e09f0a Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 21:31:58 +0000 Subject: [PATCH 04/32] making crossover mutators more flexible. --- fuzzers/baby_fuzzer_custom_input/src/input.rs | 87 ++++- fuzzers/baby_fuzzer_custom_input/src/main.rs | 52 ++- libafl/src/mutators/havoc_mutations.rs | 319 ++++++------------ libafl/src/mutators/mapping.rs | 33 +- libafl/src/mutators/mutations.rs | 98 +++--- 5 files changed, 269 insertions(+), 320 deletions(-) diff --git a/fuzzers/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby_fuzzer_custom_input/src/input.rs index 829fb286845..29872e39fd0 100644 --- a/fuzzers/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby_fuzzer_custom_input/src/input.rs @@ -1,9 +1,17 @@ -use libafl_bolts::rands::Rand; +use libafl_bolts::{rands::Rand, Named}; use serde::{Deserialize, Serialize}; -use std::hash::{DefaultHasher, Hash, Hasher}; +use std::{ + borrow::Cow, + hash::{DefaultHasher, Hash, Hasher}, +}; use libafl::{ - corpus::CorpusId, generators::Generator, inputs::Input, state::HasRand, Error, SerdeAny, + corpus::CorpusId, + generators::Generator, + inputs::Input, + prelude::{MutationResult, Mutator}, + state::HasRand, + Error, SerdeAny, }; #[derive(Serialize, Deserialize, Clone, Debug, Hash, SerdeAny)] @@ -22,6 +30,23 @@ impl Input for CustomInput { } } +impl CustomInput { + pub fn byte_array_mut(&mut self) -> &mut Vec { + &mut self.byte_array + } + + pub fn byte_array_optional(&self) -> Option<&Vec> { + Some(&self.byte_array) + } + + pub fn optional_byte_array_mut(&mut self) -> &mut Option> { + &mut self.optional_byte_array + } + pub fn optional_byte_array_optional(&self) -> Option<&Vec> { + self.optional_byte_array.as_ref() + } +} + pub struct CustomInputGenerator { pub max_len: usize, } @@ -54,14 +79,52 @@ where fn generate_bytes(length: usize, state: &mut S) -> Vec { let rand = state.rand_mut(); - Vec::with_capacity(rand.below(length)) - .iter() - .map(|_: &u8| rand.next() as u8) - .collect() + let len = rand.between(1, length); + let mut vec = Vec::new(); + vec.resize_with(len, || rand.next() as u8); + vec +} + +pub struct ToggleOptionalByteArrayMutator { + length: usize, } -// impl Named for CustomInput { -// fn name(&self) -> &Cow<'static, str> { -// &Cow::Borrowed("CustomInput") -// } -// } +impl ToggleOptionalByteArrayMutator { + pub fn new(length: usize) -> Self { + Self { length } + } +} + +impl Mutator for ToggleOptionalByteArrayMutator +where + S: HasRand, +{ + fn mutate(&mut self, state: &mut S, input: &mut CustomInput) -> Result { + input.optional_byte_array = match input.optional_byte_array { + None => Some(generate_bytes(self.length, state)), + Some(_) => None, + }; + Ok(MutationResult::Mutated) + } +} + +impl Named for ToggleOptionalByteArrayMutator { + fn name(&self) -> &Cow<'static, str> { + &Cow::Borrowed("ToggleOptionalByteArrayMutator") + } +} + +pub struct ToggleBooleanMutator; + +impl Mutator for ToggleBooleanMutator { + fn mutate(&mut self, _state: &mut S, input: &mut CustomInput) -> Result { + input.boolean = !input.boolean; + Ok(MutationResult::Mutated) + } +} + +impl Named for ToggleBooleanMutator { + fn name(&self) -> &Cow<'static, str> { + &Cow::Borrowed("ToggleBooleanMutator") + } +} diff --git a/fuzzers/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby_fuzzer_custom_input/src/main.rs index f591b5141ed..92b42cdd70a 100644 --- a/fuzzers/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby_fuzzer_custom_input/src/main.rs @@ -4,12 +4,11 @@ mod input; use std::ptr::write_volatile; use std::{path::PathBuf, ptr::write}; -use input::{CustomInput, CustomInputGenerator}; -use libafl::monitors::SimpleMonitor; -use libafl::mutators::{ - havoc_mutations_no_crossover, mapped_havoc_mutations, OptionMappingMutator, - ToFunctionMappingMutatorMapper, ToMutVecMappingMutatorMapper, ToOptionMappingMutatorMapper, +use input::{ + CustomInput, CustomInputGenerator, ToggleBooleanMutator, ToggleOptionalByteArrayMutator, }; +use libafl::monitors::SimpleMonitor; +use libafl::mutators::{mapped_havoc_mutations, optional_mapped_havoc_mutations}; use libafl::{ corpus::{InMemoryCorpus, OnDiskCorpus}, events::SimpleEventManager, @@ -22,7 +21,8 @@ use libafl::{ stages::mutational::StdMutationalStage, state::StdState, }; -use libafl_bolts::tuples::{Map, Merge}; + +use libafl_bolts::tuples::{Append, Merge}; use libafl_bolts::{current_nanos, rands::StdRand, tuples::tuple_list}; /// Coverage map with explicit assignments due to the lack of instrumentation @@ -31,6 +31,9 @@ static mut SIGNALS_PTR: *mut u8 = unsafe { SIGNALS.as_mut_ptr() }; /// Assign a signal to the signals map fn signals_set(idx: usize) { + if idx > 2 { + println!("Setting signal: {idx}"); + } unsafe { write(SIGNALS_PTR.add(idx), 1) }; } @@ -39,11 +42,11 @@ pub fn main() { // The closure that we want to fuzz let mut harness = |input: &CustomInput| { signals_set(0); - if input.boolean { + if input.byte_array == vec![b'a'] { signals_set(1); - if input.byte_array == vec![b'a', b'b', b'c'] { + if input.optional_byte_array == Some(vec![b'b']) { signals_set(2); - if input.optional_byte_array == Some(vec![b'a', b'b', b'c']) { + if input.boolean { #[cfg(unix)] panic!("Artificial bug triggered =)"); @@ -111,33 +114,28 @@ pub fn main() { .expect("Failed to create the Executor"); // Generator of printable bytearrays of max size 32 - let mut generator = CustomInputGenerator::new(10); + let mut generator = CustomInputGenerator::new(1); // Generate 8 initial inputs state .generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 8) .expect("Failed to generate the initial corpus"); - // Setup a mutational stage with a basic bytes mutator - let mutator = StdScheduledMutator::new( - mapped_havoc_mutations( - |e: &CustomInput| &e.byte_array, - |e: &mut CustomInput| &mut e.byte_array, - ) - .merge( - havoc_mutations_no_crossover() - .map(ToMutVecMappingMutatorMapper) - .map(ToOptionMappingMutatorMapper) - .map(ToFunctionMappingMutatorMapper::new( - |e: &mut CustomInput| &mut e.optional_byte_array, - )), - ), - ); + let mutations = mapped_havoc_mutations( + CustomInput::byte_array_mut, + &CustomInput::byte_array_optional, + ) + .merge(optional_mapped_havoc_mutations( + CustomInput::optional_byte_array_mut, + &CustomInput::optional_byte_array_optional, + )) + .append(ToggleOptionalByteArrayMutator::new(1)) + .append(ToggleBooleanMutator); + + let mutator = StdScheduledMutator::new(mutations); let mut stages = tuple_list!(StdMutationalStage::new(mutator)); fuzzer .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) .expect("Error in the fuzzing loop"); } - -static mut ARRAY: Vec = Vec::new(); diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index 5a83958f1d3..8b24fa466e4 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -2,8 +2,8 @@ use crate::mutators::{ mapping::{ - FunctionMappingMutator, MutVecMappingMutator, ToFunctionMappingMutatorMapper, - ToMutVecMappingMutatorMapper, + FunctionMappingMutator, MutVecMappingMutator, OptionMappingMutator, + ToFunctionMappingMutatorMapper, ToMutVecMappingMutatorMapper, }, mutations::{ BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator, ByteIncMutator, @@ -16,10 +16,11 @@ use crate::mutators::{ }, }; -use alloc::vec::Vec; use libafl_bolts::tuples::{Map, Merge}; use tuple_list::{tuple_list, tuple_list_type}; +use super::ToOptionMappingMutatorMapper; + /// Tuple type of the mutations that compose the Havoc mutator without crossover mutations pub type HavocMutationsNoCrossoverType = tuple_list_type!( BitFlipMutator, @@ -49,172 +50,14 @@ pub type HavocMutationsNoCrossoverType = tuple_list_type!( BytesSwapMutator, ); -/// Tuple type of the mutations that compose the Havoc mutator without crossover mutations for mapped input types -pub type MappedHavocMutationsNoCrossoverType = tuple_list_type!( - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, -); - -/// Tuple type of the mutations that compose the Havoc mutator without crossover mutations for mapped optional input types -// pub type OptionMappedHavocMutationsNoCrossoverType = tuple_list_type!( -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// FunctionMappingMutator< -// OptionMappingMutator>, -// I, -// Option<&mut Vec>, -// >, -// ); - /// Tuple type of the mutations that compose the Havoc mutator's crossover mutations pub type HavocCrossoverType = tuple_list_type!(CrossoverInsertMutator, CrossoverReplaceMutator); /// Tuple type of the mutations that compose the Havoc mutator's crossover mutations for mapped input types -pub type MappedHavocCrossoverType = tuple_list_type!( - MappedCrossoverInsertMutator, - MappedCrossoverReplaceMutator +pub type MappedHavocCrossoverType<'a, F> = tuple_list_type!( + MappedCrossoverInsertMutator<'a, F>, + MappedCrossoverReplaceMutator<'a, F> ); /// Tuple type of the mutations that compose the Havoc mutator @@ -249,34 +92,71 @@ pub type HavocMutationsType = tuple_list_type!( ); /// Tuple type of the mutations that compose the Havoc mutator for mapped input types -pub type MappedHavocMutationsType = tuple_list_type!( - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - FunctionMappingMutator, I, Vec>, - MappedCrossoverInsertMutator, - MappedCrossoverReplaceMutator, +pub type MappedHavocMutationsType<'a, F1, F2> = tuple_list_type!( + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, +); + +/// Tuple type of the mutations that compose the Havoc mutator for mapped input types +pub type OptionMappedHavocMutationsType<'a, F1, F2> = tuple_list_type!( + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator>, F1>, + FunctionMappingMutator< + OptionMappingMutator>>, + F1, + >, + FunctionMappingMutator< + OptionMappingMutator>>, + F1, + >, ); /// Get the mutations that compose the Havoc mutator (only applied to single inputs) @@ -311,16 +191,6 @@ pub fn havoc_mutations_no_crossover() -> HavocMutationsNoCrossoverType { ) } -/// Get the mutations that compose the Havoc mutator (only applied to single inputs) for mapped input types -#[must_use] -pub fn mapped_havoc_mutations_no_crossover( - mapper: for<'b> fn(&'b mut I) -> &'b mut Vec, -) -> MappedHavocMutationsNoCrossoverType { - havoc_mutations_no_crossover() - .map(ToMutVecMappingMutatorMapper) - .map(ToFunctionMappingMutatorMapper::new(mapper)) -} - /// Get the mutations that compose the Havoc mutator's crossover strategy #[must_use] pub fn havoc_crossover() -> HavocCrossoverType { @@ -330,15 +200,11 @@ pub fn havoc_crossover() -> HavocCrossoverType { ) } -/// Get the mutations that compose the Havoc mutator's crossover strategy for mapped input types -#[must_use] -pub fn mapped_havoc_crossover( - mapper: for<'b> fn(&'b I) -> &'b Vec, - mapper_mut: for<'b> fn(&'b mut I) -> &'b mut Vec, -) -> MappedHavocCrossoverType { +/// Get the mutations that compose the Havoc mutator's crossover strategy with custom corpus extraction logic +pub fn havoc_crossover_with_corpus_mapper(corpus_mapper: &F) -> MappedHavocCrossoverType<'_, F> { tuple_list!( - MappedCrossoverInsertMutator::new(mapper, mapper_mut), - MappedCrossoverReplaceMutator::new(mapper, mapper_mut), + MappedCrossoverInsertMutator::new(corpus_mapper), + MappedCrossoverReplaceMutator::new(corpus_mapper), ) } @@ -350,10 +216,31 @@ pub fn havoc_mutations() -> HavocMutationsType { /// Get the mutations that compose the Havoc mutator for mapped input types #[must_use] -pub fn mapped_havoc_mutations( - mapper: for<'b> fn(&'b I) -> &'b Vec, - mapper_mut: for<'b> fn(&'b mut I) -> &'b mut Vec, -) -> MappedHavocMutationsType { - mapped_havoc_mutations_no_crossover(mapper_mut) - .merge(mapped_havoc_crossover(mapper, mapper_mut)) +pub fn mapped_havoc_mutations( + current_input_mapper: F1, + input_from_corpus_mapper: &F2, +) -> MappedHavocMutationsType<'_, F1, F2> +where + F1: Clone, +{ + havoc_mutations_no_crossover() + .merge(havoc_crossover_with_corpus_mapper(input_from_corpus_mapper)) + .map(ToMutVecMappingMutatorMapper) + .map(ToFunctionMappingMutatorMapper::new(current_input_mapper)) +} + +/// Get the mutations that compose the Havoc mutator for mapped input types +#[must_use] +pub fn optional_mapped_havoc_mutations( + current_input_mapper: F1, + input_from_corpus_mapper: &F2, +) -> OptionMappedHavocMutationsType<'_, F1, F2> +where + F1: Clone, +{ + havoc_mutations_no_crossover() + .merge(havoc_crossover_with_corpus_mapper(input_from_corpus_mapper)) + .map(ToMutVecMappingMutatorMapper) + .map(ToOptionMappingMutatorMapper) + .map(ToFunctionMappingMutatorMapper::new(current_input_mapper)) } diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index 5120a27f179..f7f74ea2fa3 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -51,19 +51,20 @@ impl MappingFunctor for ToMutVecMappingMutatorMapper { } #[derive(Debug)] -pub struct FunctionMappingMutator { - mapper: fn(&mut IO) -> &mut II, +pub struct FunctionMappingMutator { + mapper: F, inner: M, } -impl FunctionMappingMutator { - fn new(mapper: fn(&mut IO) -> &mut II, inner: M) -> Self { +impl FunctionMappingMutator { + pub fn new(mapper: F, inner: M) -> Self { Self { mapper, inner } } } -impl Mutator for FunctionMappingMutator +impl Mutator for FunctionMappingMutator where + F: for<'a> FnMut(&'a mut IO) -> &'a mut II, M: Mutator, { fn mutate(&mut self, state: &mut S, input: &mut IO) -> Result { @@ -71,31 +72,31 @@ where } } -impl Named for FunctionMappingMutator -where - M: Named, -{ +impl Named for FunctionMappingMutator { fn name(&self) -> &Cow<'static, str> { &Cow::Borrowed("FunctionMappingMutator") } } #[derive(Debug)] -pub struct ToFunctionMappingMutatorMapper { - mapper: for<'a> fn(&'a mut IO) -> &'a mut II, +pub struct ToFunctionMappingMutatorMapper { + mapper: F, } -impl ToFunctionMappingMutatorMapper { - pub fn new(mapper: for<'a> fn(&'a mut IO) -> &'a mut II) -> Self { +impl ToFunctionMappingMutatorMapper { + pub fn new(mapper: F) -> Self { Self { mapper } } } -impl MappingFunctor for ToFunctionMappingMutatorMapper { - type Output = FunctionMappingMutator; +impl MappingFunctor for ToFunctionMappingMutatorMapper +where + F: Clone, +{ + type Output = FunctionMappingMutator; fn apply(&mut self, from: M) -> Self::Output { - FunctionMappingMutator::new(self.mapper, from) + FunctionMappingMutator::new(self.mapper.clone(), from) } } diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index aa38b976991..f785d8d3afd 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -10,7 +10,7 @@ use libafl_bolts::{rands::Rand, Named}; use crate::{ corpus::Corpus, - inputs::{HasMutatorBytes, MutVecInput, UsesInput}, + inputs::{HasMutatorBytes, UsesInput}, mutators::{MutationResult, Mutator}, random_corpus_id_with_disabled, state::{HasCorpus, HasMaxSize, HasRand}, @@ -1196,18 +1196,18 @@ impl CrossoverReplaceMutator { } /// Crossover insert mutation for inputs mapped to a bytes vector #[derive(Debug)] -pub struct MappedCrossoverInsertMutator { - input_from_corpus_mapper: for<'a> fn(&'a I) -> &Vec, - input_to_mutate_mapper: for<'a> fn(&'a mut I) -> &mut Vec, +pub struct MappedCrossoverInsertMutator<'a, F> { + input_from_corpus_mapper: &'a F, } -impl Mutator for MappedCrossoverInsertMutator +impl<'a, S, F, I> Mutator for MappedCrossoverInsertMutator<'a, F> where S: HasCorpus + HasMaxSize + HasRand + UsesInput, + I: HasMutatorBytes, + F: for<'b> Fn(&'b S::Input) -> Option<&'b Vec>, { - fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result { - let mapped_input: &mut MutVecInput = &mut (self.input_to_mutate_mapper)(input).into(); - let size = mapped_input.bytes().len(); + fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { + let size = input.bytes().len(); let max_size = state.max_size(); if size >= max_size { return Ok(MutationResult::Skipped); @@ -1224,7 +1224,7 @@ where let other_size = { let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); let other_input = other_testcase.load_input(state.corpus())?; - (self.input_from_corpus_mapper)(other_input).len() + (self.input_from_corpus_mapper)(other_input).map_or(0, Vec::len) }; if other_size < 2 { @@ -1236,53 +1236,62 @@ where let other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); // No need to load the input again, it'll still be cached. - let other = &mut other_testcase.input().as_ref().unwrap(); - let mapped_other = (self.input_from_corpus_mapper)(other); + let other_input = &mut other_testcase.input().as_ref().unwrap(); + let wrapped_mapped_other_input = (self.input_from_corpus_mapper)(other_input); + if wrapped_mapped_other_input.is_none() { + return Ok(MutationResult::Skipped); + } + let mapped_other_input = wrapped_mapped_other_input.unwrap(); Ok(CrossoverInsertMutator::crossover_insert( - mapped_input, + input, size, target, range, - mapped_other, + mapped_other_input, )) } } -impl Named for MappedCrossoverInsertMutator { +impl<'a, F> Named for MappedCrossoverInsertMutator<'a, F> { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("MappedCrossoverInsertMutator"); &NAME } } -impl MappedCrossoverInsertMutator { +impl<'a, F> MappedCrossoverInsertMutator<'a, F> { /// Creates a new [`MappedCrossoverInsertMutator`]. - pub fn new( - input_from_corpus_mapper: for<'a> fn(&'a I) -> &'a Vec, - input_to_mutate_mapper: for<'a> fn(&'a mut I) -> &'a mut Vec, - ) -> Self { + pub fn new(input_from_corpus_mapper: &'a F) -> Self { Self { input_from_corpus_mapper, - input_to_mutate_mapper, } } } /// Crossover replace mutation for inputs mapped to a bytes vector #[derive(Debug)] -pub struct MappedCrossoverReplaceMutator { - input_from_corpus_mapper: for<'a> fn(&'a I) -> &Vec, - input_to_mutate_mapper: for<'a> fn(&'a mut I) -> &mut Vec, +pub struct MappedCrossoverReplaceMutator<'a, F> { + input_from_corpus_mapper: &'a F, +} + +impl<'a, F> MappedCrossoverReplaceMutator<'a, F> { + /// Creates a new [`MappedCrossoverReplaceMutator`]. + pub fn new(input_from_corpus_mapper: &'a F) -> Self { + Self { + input_from_corpus_mapper, + } + } } -impl Mutator for MappedCrossoverReplaceMutator +impl<'a, S, I, F> Mutator for MappedCrossoverReplaceMutator<'a, F> where - S: HasCorpus + HasRand + HasMaxSize + UsesInput, + S: HasCorpus + HasMaxSize + HasRand + UsesInput, + I: HasMutatorBytes, + F: for<'b> Fn(&'b S::Input) -> Option<&'b Vec>, { - fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result { - let mapped_input: &mut MutVecInput = &mut (self.input_to_mutate_mapper)(input).into(); - let size = mapped_input.bytes().len(); + fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { + let size = input.bytes().len(); if size == 0 { return Ok(MutationResult::Skipped); } @@ -1296,9 +1305,9 @@ where } let other_size = { - let mut testcase = state.corpus().get_from_all(id)?.borrow_mut(); - let other_input = testcase.load_input(state.corpus())?; - (self.input_from_corpus_mapper)(other_input).len() + let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); + let other_input = other_testcase.load_input(state.corpus())?; + (self.input_from_corpus_mapper)(other_input).map_or(0, Vec::len) }; if other_size < 2 { @@ -1310,38 +1319,29 @@ where let other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); // No need to load the input again, it'll still be cached. - let other = &mut other_testcase.input().as_ref().unwrap(); - let mapped_other = (self.input_from_corpus_mapper)(other); + let other_input = &mut other_testcase.input().as_ref().unwrap(); + let wrapped_mapped_other_input = (self.input_from_corpus_mapper)(other_input); + if wrapped_mapped_other_input.is_none() { + return Ok(MutationResult::Skipped); + } + let mapped_other_input = wrapped_mapped_other_input.unwrap(); Ok(CrossoverReplaceMutator::crossover_replace( - mapped_input, + input, target, range, - mapped_other, + mapped_other_input, )) } } -impl Named for MappedCrossoverReplaceMutator { +impl<'a, F> Named for MappedCrossoverReplaceMutator<'a, F> { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("MappedCrossoverReplaceMutator"); &NAME } } -impl MappedCrossoverReplaceMutator { - /// Creates a new [`MappedCrossoverReplaceMutator`]. - pub fn new( - input_from_corpus_mapper: for<'a> fn(&'a I) -> &Vec, - input_to_mutate_mapper: for<'a> fn(&'a mut I) -> &mut Vec, - ) -> Self { - Self { - input_from_corpus_mapper, - input_to_mutate_mapper, - } - } -} - /// Returns the first and last diff position between the given vectors, stopping at the min len fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) { let mut first_diff: i64 = -1; From e4ab6324c42526bc0702e15724cb85ed0bb1a35e Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 21:44:48 +0000 Subject: [PATCH 05/32] moving example fuzzer --- fuzzers/{ => baby}/baby_fuzzer_custom_input/Cargo.toml | 0 fuzzers/{ => baby}/baby_fuzzer_custom_input/README.md | 0 fuzzers/{ => baby}/baby_fuzzer_custom_input/src/input.rs | 0 fuzzers/{ => baby}/baby_fuzzer_custom_input/src/main.rs | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename fuzzers/{ => baby}/baby_fuzzer_custom_input/Cargo.toml (100%) rename fuzzers/{ => baby}/baby_fuzzer_custom_input/README.md (100%) rename fuzzers/{ => baby}/baby_fuzzer_custom_input/src/input.rs (100%) rename fuzzers/{ => baby}/baby_fuzzer_custom_input/src/main.rs (100%) diff --git a/fuzzers/baby_fuzzer_custom_input/Cargo.toml b/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml similarity index 100% rename from fuzzers/baby_fuzzer_custom_input/Cargo.toml rename to fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml diff --git a/fuzzers/baby_fuzzer_custom_input/README.md b/fuzzers/baby/baby_fuzzer_custom_input/README.md similarity index 100% rename from fuzzers/baby_fuzzer_custom_input/README.md rename to fuzzers/baby/baby_fuzzer_custom_input/README.md diff --git a/fuzzers/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs similarity index 100% rename from fuzzers/baby_fuzzer_custom_input/src/input.rs rename to fuzzers/baby/baby_fuzzer_custom_input/src/input.rs diff --git a/fuzzers/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs similarity index 100% rename from fuzzers/baby_fuzzer_custom_input/src/main.rs rename to fuzzers/baby/baby_fuzzer_custom_input/src/main.rs From 1769ff1191b2208230000a500a3bf10cae3e2ca5 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 21:51:15 +0000 Subject: [PATCH 06/32] fixing dependency paths --- fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml b/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml index b9eec645570..c8c76fe60ff 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml +++ b/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml @@ -15,6 +15,6 @@ opt-level = 3 debug = true [dependencies] -libafl = { path = "../../libafl/" } -libafl_bolts = { path = "../../libafl_bolts/" } +libafl = { path = "../../../libafl/" } +libafl_bolts = { path = "../../../libafl_bolts/" } serde = "*" From 11801f59376a91d5c47d19b6676dac2cf4283940 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 21:51:23 +0000 Subject: [PATCH 07/32] formatting --- .../baby/baby_fuzzer_custom_input/src/input.rs | 4 ++-- fuzzers/baby/baby_fuzzer_custom_input/src/main.rs | 15 +++++++++------ libafl/src/mutators/havoc_mutations.rs | 9 ++++----- libafl/src/mutators/mapping.rs | 9 ++++----- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs index 29872e39fd0..b80a6699d62 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs @@ -1,5 +1,3 @@ -use libafl_bolts::{rands::Rand, Named}; -use serde::{Deserialize, Serialize}; use std::{ borrow::Cow, hash::{DefaultHasher, Hash, Hasher}, @@ -13,6 +11,8 @@ use libafl::{ state::HasRand, Error, SerdeAny, }; +use libafl_bolts::{rands::Rand, Named}; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Clone, Debug, Hash, SerdeAny)] pub struct CustomInput { diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index 92b42cdd70a..f5ae8fb6dd8 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -7,23 +7,26 @@ use std::{path::PathBuf, ptr::write}; use input::{ CustomInput, CustomInputGenerator, ToggleBooleanMutator, ToggleOptionalByteArrayMutator, }; -use libafl::monitors::SimpleMonitor; -use libafl::mutators::{mapped_havoc_mutations, optional_mapped_havoc_mutations}; use libafl::{ corpus::{InMemoryCorpus, OnDiskCorpus}, events::SimpleEventManager, executors::{inprocess::InProcessExecutor, ExitKind}, feedbacks::{CrashFeedback, MaxMapFeedback}, fuzzer::{Fuzzer, StdFuzzer}, - mutators::scheduled::StdScheduledMutator, + monitors::SimpleMonitor, + mutators::{ + mapped_havoc_mutations, optional_mapped_havoc_mutations, scheduled::StdScheduledMutator, + }, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, }; - -use libafl_bolts::tuples::{Append, Merge}; -use libafl_bolts::{current_nanos, rands::StdRand, tuples::tuple_list}; +use libafl_bolts::{ + current_nanos, + rands::StdRand, + tuples::{tuple_list, Append, Merge}, +}; /// Coverage map with explicit assignments due to the lack of instrumentation static mut SIGNALS: [u8; 16] = [0; 16]; diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index 8b24fa466e4..769cd7105db 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -1,5 +1,9 @@ //! [`Mutator`] collection equivalent to AFL++'s havoc mutations +use libafl_bolts::tuples::{Map, Merge}; +use tuple_list::{tuple_list, tuple_list_type}; + +use super::ToOptionMappingMutatorMapper; use crate::mutators::{ mapping::{ FunctionMappingMutator, MutVecMappingMutator, OptionMappingMutator, @@ -16,11 +20,6 @@ use crate::mutators::{ }, }; -use libafl_bolts::tuples::{Map, Merge}; -use tuple_list::{tuple_list, tuple_list_type}; - -use super::ToOptionMappingMutatorMapper; - /// Tuple type of the mutations that compose the Havoc mutator without crossover mutations pub type HavocMutationsNoCrossoverType = tuple_list_type!( BitFlipMutator, diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index f7f74ea2fa3..fd883df522a 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -1,15 +1,15 @@ //! Allowing mixing and matching between [`Mutator`] and [`crate::inputs::Input`] types. +use alloc::vec::Vec; use std::borrow::Cow; +use libafl_bolts::{tuples::MappingFunctor, Named}; + use crate::{ inputs::MutVecInput, mutators::{MutationResult, Mutator}, Error, }; -use alloc::vec::Vec; -use libafl_bolts::{tuples::MappingFunctor, Named}; - #[derive(Debug)] pub struct MutVecMappingMutator { inner: M, @@ -149,13 +149,12 @@ mod test { use libafl_bolts::tuples::Map; use tuple_list::tuple_list; + use super::{OptionMappingMutator, ToOptionMappingMutatorMapper}; use crate::{ inputs::MutVecInput, prelude::{ByteIncMutator, MutationResult, Mutator, NopState}, }; - use super::{OptionMappingMutator, ToOptionMappingMutatorMapper}; - #[test] fn test_option_mapping_mutator() { let inner = ByteIncMutator::new(); From 84d704e2cc0d2438e75d14b02a707962522edc19 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 22:04:30 +0000 Subject: [PATCH 08/32] fixing no std error --- libafl/src/mutators/mapping.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index fd883df522a..d6e9156f630 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -1,6 +1,5 @@ //! Allowing mixing and matching between [`Mutator`] and [`crate::inputs::Input`] types. -use alloc::vec::Vec; -use std::borrow::Cow; +use alloc::{borrow::Cow, vec::Vec}; use libafl_bolts::{tuples::MappingFunctor, Named}; @@ -145,14 +144,14 @@ impl MappingFunctor for ToOptionMappingMutatorMapper { #[cfg(test)] mod test { - use libafl_bolts::tuples::Map; use tuple_list::tuple_list; use super::{OptionMappingMutator, ToOptionMappingMutatorMapper}; use crate::{ inputs::MutVecInput, - prelude::{ByteIncMutator, MutationResult, Mutator, NopState}, + mutators::{ByteIncMutator, MutationResult, Mutator}, + state::NopState, }; #[test] From 5f6c6895c867229b2e52ae4a3d1ce009b0b8d6f1 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 22:11:01 +0000 Subject: [PATCH 09/32] fixing broken docs link --- libafl/src/mutators/havoc_mutations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index 769cd7105db..58fa7f184f4 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -1,4 +1,4 @@ -//! [`Mutator`] collection equivalent to AFL++'s havoc mutations +//! [`crate::mutators::Mutator`] collection equivalent to AFL++'s havoc mutations use libafl_bolts::tuples::{Map, Merge}; use tuple_list::{tuple_list, tuple_list_type}; From ac7dfb9a9bad25155acc0d5d6805b8e71dc71bd6 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 22:28:30 +0000 Subject: [PATCH 10/32] fixing import paths --- libafl/src/mutators/multi.rs | 14 ++++++++++---- libafl_sugar/src/forkserver.rs | 3 ++- libafl_sugar/src/inmemory.rs | 3 ++- libafl_sugar/src/qemu.rs | 3 ++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/libafl/src/mutators/multi.rs b/libafl/src/mutators/multi.rs index a4263951ba5..fa3405703f9 100644 --- a/libafl/src/mutators/multi.rs +++ b/libafl/src/mutators/multi.rs @@ -167,7 +167,13 @@ where } }; - return Ok(Self::crossover_insert(part, size, target, range, chosen)); + return Ok(Self::crossover_insert( + part, + size, + target, + range, + chosen.bytes(), + )); } return Ok(MutationResult::Skipped); @@ -207,7 +213,7 @@ where size, target, range, - &other.parts()[choice], + other.parts()[choice].bytes(), )) } else { // just add it! @@ -271,7 +277,7 @@ where } }; - return Ok(Self::crossover_replace(part, target, range, chosen)); + return Ok(Self::crossover_replace(part, target, range, chosen.bytes())); } return Ok(MutationResult::Skipped); @@ -310,7 +316,7 @@ where part, target, range, - &other.parts()[choice], + other.parts()[choice].bytes(), )) } else { // just add it! diff --git a/libafl_sugar/src/forkserver.rs b/libafl_sugar/src/forkserver.rs index 9ac55746706..7234b49c5e3 100644 --- a/libafl_sugar/src/forkserver.rs +++ b/libafl_sugar/src/forkserver.rs @@ -12,7 +12,8 @@ use libafl::{ generators::RandBytesGenerator, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, diff --git a/libafl_sugar/src/inmemory.rs b/libafl_sugar/src/inmemory.rs index cc05399f188..c6dc424a286 100644 --- a/libafl_sugar/src/inmemory.rs +++ b/libafl_sugar/src/inmemory.rs @@ -15,7 +15,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::{I2SRandReplace, Tokens}, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, diff --git a/libafl_sugar/src/qemu.rs b/libafl_sugar/src/qemu.rs index 4fd22bac333..fa6111d1b6f 100644 --- a/libafl_sugar/src/qemu.rs +++ b/libafl_sugar/src/qemu.rs @@ -17,7 +17,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, I2SRandReplace, }, From 4df0d6526c7bd3dd7c70011465031ee8614c71ba Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 22:35:51 +0000 Subject: [PATCH 11/32] fixing imports --- fuzzers/baby/baby_no_std/src/main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fuzzers/baby/baby_no_std/src/main.rs b/fuzzers/baby/baby_no_std/src/main.rs index 58b5acc28a5..6db18b9dae9 100644 --- a/fuzzers/baby/baby_no_std/src/main.rs +++ b/fuzzers/baby/baby_no_std/src/main.rs @@ -19,7 +19,10 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, + mutators::{ + havoc_mutations::havoc_mutations, + scheduled::{StdScheduledMutator}, + }, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, From dbbe477a3342ae68ff8cf397221a2a93a93b244f Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 22:41:41 +0000 Subject: [PATCH 12/32] more format fixing --- fuzzers/baby/baby_no_std/src/main.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fuzzers/baby/baby_no_std/src/main.rs b/fuzzers/baby/baby_no_std/src/main.rs index 6db18b9dae9..cd3a1674f13 100644 --- a/fuzzers/baby/baby_no_std/src/main.rs +++ b/fuzzers/baby/baby_no_std/src/main.rs @@ -19,10 +19,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::{ - havoc_mutations::havoc_mutations, - scheduled::{StdScheduledMutator}, - }, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, From 8a50e0ac9a98bada49c75ab7a0d950e3f2bd468e Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 22:41:55 +0000 Subject: [PATCH 13/32] adding new example fuzzer to CI --- .github/workflows/build_and_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index b984728fbd4..84155586fa1 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -241,6 +241,7 @@ jobs: - ./fuzzers/baby/baby_fuzzer_grimoire - ./fuzzers/baby/baby_fuzzer_gramatron - ./fuzzers/baby/baby_fuzzer + - ./fuzzers/baby/baby_fuzzer_custom_input - ./fuzzers/baby/baby_fuzzer_nautilus # - ./fuzzers/baby/backtrace_baby_fuzzers - ./fuzzers/baby/baby_fuzzer_unicode From 2c19717fa0c3003a2c75baff5710077bb963082f Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 23:30:38 +0000 Subject: [PATCH 14/32] fixing further imports --- fuzzers/baby/baby_fuzzer/src/main.rs | 2 +- fuzzers/baby/baby_fuzzer_multi/src/main.rs | 2 +- fuzzers/baby/baby_fuzzer_swap_differential/src/main.rs | 2 +- fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs | 3 +-- .../c_code_with_fork_executor/src/main.rs | 2 +- .../c_code_with_inprocess_executor/src/main.rs | 3 +-- .../baby/backtrace_baby_fuzzers/command_executor/src/main.rs | 2 +- .../backtrace_baby_fuzzers/forkserver_executor/src/main.rs | 3 +-- .../rust_code_with_fork_executor/src/main.rs | 3 +-- .../rust_code_with_inprocess_executor/src/main.rs | 3 +-- fuzzers/forkserver/forkserver_libafl_cc/src/main.rs | 2 +- fuzzers/forkserver/forkserver_simple/src/main.rs | 2 +- fuzzers/frida/frida_executable_libpng/src/fuzzer.rs | 3 ++- fuzzers/frida/frida_gdiplus/src/fuzzer.rs | 3 ++- fuzzers/frida/frida_libpng/src/fuzzer.rs | 3 ++- fuzzers/fuzzbench/fuzzbench/src/lib.rs | 4 ++-- fuzzers/fuzzbench/fuzzbench_ctx/src/lib.rs | 4 ++-- fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs | 4 ++-- fuzzers/fuzzbench/fuzzbench_forkserver/src/main.rs | 4 ++-- fuzzers/fuzzbench/fuzzbench_forkserver_cmplog/src/main.rs | 3 +-- fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs | 4 ++-- fuzzers/fuzzbench/fuzzbench_text/src/lib.rs | 2 +- fuzzers/libpng/libfuzzer_libpng/src/lib.rs | 3 ++- fuzzers/libpng/libfuzzer_libpng_accounting/src/lib.rs | 3 ++- fuzzers/libpng/libfuzzer_libpng_centralized/src/lib.rs | 3 ++- fuzzers/libpng/libfuzzer_libpng_cmin/src/lib.rs | 3 ++- fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs | 4 ++-- fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs | 4 ++-- fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs | 4 ++-- fuzzers/others/dynamic_analysis/src/lib.rs | 4 ++-- fuzzers/others/libafl-fuzz/src/fuzzer.rs | 4 +--- fuzzers/others/libafl_atheris/src/lib.rs | 4 ++-- fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs | 4 ++-- fuzzers/others/libfuzzer_windows_asan/src/lib.rs | 5 ++++- fuzzers/others/push_harness/src/main.rs | 3 +-- fuzzers/others/push_stage_harness/src/main.rs | 3 +-- fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs | 4 ++-- fuzzers/qemu/qemu_launcher/src/instance.rs | 4 ++-- fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs | 3 +-- fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs | 3 +-- fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs | 3 +-- fuzzers/stb/libfuzzer_stb_image/src/main.rs | 2 +- fuzzers/stb/libfuzzer_stb_image_concolic/fuzzer/src/main.rs | 2 +- 43 files changed, 66 insertions(+), 69 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer/src/main.rs b/fuzzers/baby/baby_fuzzer/src/main.rs index 2c22ae2f970..36f7ca94bd9 100644 --- a/fuzzers/baby/baby_fuzzer/src/main.rs +++ b/fuzzers/baby/baby_fuzzer/src/main.rs @@ -14,7 +14,7 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, diff --git a/fuzzers/baby/baby_fuzzer_multi/src/main.rs b/fuzzers/baby/baby_fuzzer_multi/src/main.rs index 6e7d9ae14df..dbcf35638af 100644 --- a/fuzzers/baby/baby_fuzzer_multi/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_multi/src/main.rs @@ -14,7 +14,7 @@ use libafl::{ feedbacks::{CrashFeedback, MaxMapFeedback, MinMapFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes, MultipartInput}, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, diff --git a/fuzzers/baby/baby_fuzzer_swap_differential/src/main.rs b/fuzzers/baby/baby_fuzzer_swap_differential/src/main.rs index dd8b47e6425..471d6fee317 100644 --- a/fuzzers/baby/baby_fuzzer_swap_differential/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_swap_differential/src/main.rs @@ -17,7 +17,7 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, diff --git a/fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs b/fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs index 7ab274bdcf4..717c71e3678 100644 --- a/fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs @@ -11,8 +11,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::StdMapObserver, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs index 78cb2c7a2e6..ca1d87f5d1b 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs @@ -10,7 +10,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{BacktraceObserver, ConstMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs index 3dbe6f0ad09..eaa13efd13e 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs @@ -10,8 +10,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::{BacktraceObserver, ConstMapObserver}, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{BacktraceObserver, ConstMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/command_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/command_executor/src/main.rs index f4cb4716582..65a3e282fee 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/command_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/command_executor/src/main.rs @@ -17,7 +17,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{get_asan_runtime_flags, AsanBacktraceObserver, StdMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs index 86fc4b41e97..b20633e051c 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs @@ -10,8 +10,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::BytesInput, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::{AsanBacktraceObserver, ConstMapObserver, HitcountsMapObserver}, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{AsanBacktraceObserver, ConstMapObserver, HitcountsMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs index 1b6e2507cc6..d500829e34d 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs @@ -12,8 +12,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::{BacktraceObserver, StdMapObserver}, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{BacktraceObserver, StdMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs index a58ef4ec6d3..0a496e4c7f5 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs @@ -12,8 +12,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::{BacktraceObserver, StdMapObserver}, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{BacktraceObserver, StdMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/forkserver/forkserver_libafl_cc/src/main.rs b/fuzzers/forkserver/forkserver_libafl_cc/src/main.rs index 5b131120ca2..4e4deb06809 100644 --- a/fuzzers/forkserver/forkserver_libafl_cc/src/main.rs +++ b/fuzzers/forkserver/forkserver_libafl_cc/src/main.rs @@ -11,7 +11,7 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::BytesInput, monitors::SimpleMonitor, - mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, + mutators::{havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::mutational::StdMutationalStage, diff --git a/fuzzers/forkserver/forkserver_simple/src/main.rs b/fuzzers/forkserver/forkserver_simple/src/main.rs index 84a34f5402f..c0261977388 100644 --- a/fuzzers/forkserver/forkserver_simple/src/main.rs +++ b/fuzzers/forkserver/forkserver_simple/src/main.rs @@ -11,7 +11,7 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::BytesInput, monitors::SimpleMonitor, - mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, + mutators::{havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::mutational::StdMutationalStage, diff --git a/fuzzers/frida/frida_executable_libpng/src/fuzzer.rs b/fuzzers/frida/frida_executable_libpng/src/fuzzer.rs index 0cb1d15ba33..7f55dbb62ba 100644 --- a/fuzzers/frida/frida_executable_libpng/src/fuzzer.rs +++ b/fuzzers/frida/frida_executable_libpng/src/fuzzer.rs @@ -13,7 +13,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::{I2SRandReplace, Tokens}, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, diff --git a/fuzzers/frida/frida_gdiplus/src/fuzzer.rs b/fuzzers/frida/frida_gdiplus/src/fuzzer.rs index 8f9fdbe8de0..1a8def4fc6a 100644 --- a/fuzzers/frida/frida_gdiplus/src/fuzzer.rs +++ b/fuzzers/frida/frida_gdiplus/src/fuzzer.rs @@ -30,7 +30,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::{I2SRandReplace, Tokens}, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, diff --git a/fuzzers/frida/frida_libpng/src/fuzzer.rs b/fuzzers/frida/frida_libpng/src/fuzzer.rs index 63c84537673..440f03c62f0 100644 --- a/fuzzers/frida/frida_libpng/src/fuzzer.rs +++ b/fuzzers/frida/frida_libpng/src/fuzzer.rs @@ -13,7 +13,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::{I2SRandReplace, Tokens}, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, diff --git a/fuzzers/fuzzbench/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/fuzzbench/src/lib.rs index 9b162a48e38..ae4d85d5504 100644 --- a/fuzzers/fuzzbench/fuzzbench/src/lib.rs +++ b/fuzzers/fuzzbench/fuzzbench/src/lib.rs @@ -25,8 +25,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, + havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, + StdScheduledMutator, Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{ diff --git a/fuzzers/fuzzbench/fuzzbench_ctx/src/lib.rs b/fuzzers/fuzzbench/fuzzbench_ctx/src/lib.rs index b407fd01af5..1a2af2121b1 100644 --- a/fuzzers/fuzzbench/fuzzbench_ctx/src/lib.rs +++ b/fuzzers/fuzzbench/fuzzbench_ctx/src/lib.rs @@ -28,8 +28,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, + havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, + StdScheduledMutator, Tokens, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{ diff --git a/fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs b/fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs index 3b44b674ecf..486148a746c 100644 --- a/fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs +++ b/fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs @@ -23,8 +23,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, + havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, + StdScheduledMutator, Tokens, }, observers::{CanTrack, ConstMapObserver, HitcountsMapObserver, TimeObserver}, schedulers::{ diff --git a/fuzzers/fuzzbench/fuzzbench_forkserver/src/main.rs b/fuzzers/fuzzbench/fuzzbench_forkserver/src/main.rs index ffa2b903f27..7e52a5e61a0 100644 --- a/fuzzers/fuzzbench/fuzzbench_forkserver/src/main.rs +++ b/fuzzers/fuzzbench/fuzzbench_forkserver/src/main.rs @@ -18,8 +18,8 @@ use libafl::{ inputs::BytesInput, monitors::SimpleMonitor, mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, + havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, + StdScheduledMutator, Tokens, }, observers::{ CanTrack, HitcountsMapObserver, StdCmpValuesObserver, StdMapObserver, TimeObserver, diff --git a/fuzzers/fuzzbench/fuzzbench_forkserver_cmplog/src/main.rs b/fuzzers/fuzzbench/fuzzbench_forkserver_cmplog/src/main.rs index 79e1568e1bd..7ce5805814e 100644 --- a/fuzzers/fuzzbench/fuzzbench_forkserver_cmplog/src/main.rs +++ b/fuzzers/fuzzbench/fuzzbench_forkserver_cmplog/src/main.rs @@ -18,8 +18,7 @@ use libafl::{ inputs::BytesInput, monitors::SimpleMonitor, mutators::{ - scheduled::havoc_mutations, token_mutations::AFLppRedQueen, tokens_mutations, - StdMOptMutator, Tokens, + havoc_mutations, token_mutations::AFLppRedQueen, tokens_mutations, StdMOptMutator, Tokens, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{ diff --git a/fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs b/fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs index 6c65a085928..418032b7bb9 100644 --- a/fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs +++ b/fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs @@ -22,8 +22,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, + havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, + StdScheduledMutator, Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{ diff --git a/fuzzers/fuzzbench/fuzzbench_text/src/lib.rs b/fuzzers/fuzzbench/fuzzbench_text/src/lib.rs index b8924015caf..bf77b644d39 100644 --- a/fuzzers/fuzzbench/fuzzbench_text/src/lib.rs +++ b/fuzzers/fuzzbench/fuzzbench_text/src/lib.rs @@ -30,7 +30,7 @@ use libafl::{ GrimoireExtensionMutator, GrimoireRandomDeleteMutator, GrimoireRecursiveReplacementMutator, GrimoireStringReplacementMutator, }, - scheduled::havoc_mutations, + havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, StdScheduledMutator, Tokens, }, diff --git a/fuzzers/libpng/libfuzzer_libpng/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng/src/lib.rs index f1fff436c67..274f28c2412 100644 --- a/fuzzers/libpng/libfuzzer_libpng/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng/src/lib.rs @@ -15,7 +15,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, diff --git a/fuzzers/libpng/libfuzzer_libpng_accounting/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_accounting/src/lib.rs index c52cfd68a8a..60a5f7c514f 100644 --- a/fuzzers/libpng/libfuzzer_libpng_accounting/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_accounting/src/lib.rs @@ -16,7 +16,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, diff --git a/fuzzers/libpng/libfuzzer_libpng_centralized/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_centralized/src/lib.rs index b1b5d681c45..ae7da19c3a4 100644 --- a/fuzzers/libpng/libfuzzer_libpng_centralized/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_centralized/src/lib.rs @@ -16,7 +16,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, diff --git a/fuzzers/libpng/libfuzzer_libpng_cmin/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_cmin/src/lib.rs index e024dcdbe86..f2c56979216 100644 --- a/fuzzers/libpng/libfuzzer_libpng_cmin/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_cmin/src/lib.rs @@ -18,7 +18,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, diff --git a/fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs index 870fc02e9aa..d8afc674db2 100644 --- a/fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs @@ -16,8 +16,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::{MultiMonitor, OnDiskTomlMonitor}, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, - token_mutations::Tokens, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, diff --git a/fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs index 9c4d7ebf94a..4d89772cedb 100644 --- a/fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs @@ -20,8 +20,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::{MultiMonitor, OnDiskTomlMonitor}, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, - token_mutations::Tokens, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, diff --git a/fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs index 60dab533fab..fccd7067951 100644 --- a/fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs @@ -15,8 +15,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, - token_mutations::Tokens, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{ diff --git a/fuzzers/others/dynamic_analysis/src/lib.rs b/fuzzers/others/dynamic_analysis/src/lib.rs index 472d8b4e360..088b2462717 100644 --- a/fuzzers/others/dynamic_analysis/src/lib.rs +++ b/fuzzers/others/dynamic_analysis/src/lib.rs @@ -24,8 +24,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, + havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, + StdScheduledMutator, Tokens, }, observers::{CanTrack, HitcountsMapObserver, ProfilingObserver, TimeObserver}, schedulers::{ diff --git a/fuzzers/others/libafl-fuzz/src/fuzzer.rs b/fuzzers/others/libafl-fuzz/src/fuzzer.rs index 7d69a21e267..557b53f6c8e 100644 --- a/fuzzers/others/libafl-fuzz/src/fuzzer.rs +++ b/fuzzers/others/libafl-fuzz/src/fuzzer.rs @@ -11,9 +11,7 @@ use libafl::{ feedbacks::{ConstFeedback, CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, fuzzer::StdFuzzer, inputs::BytesInput, - mutators::{ - scheduled::havoc_mutations, tokens_mutations, AFLppRedQueen, StdScheduledMutator, Tokens, - }, + mutators::{havoc_mutations, tokens_mutations, AFLppRedQueen, StdScheduledMutator, Tokens}, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{ powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, QueueScheduler, diff --git a/fuzzers/others/libafl_atheris/src/lib.rs b/fuzzers/others/libafl_atheris/src/lib.rs index d6e4ee2a1b2..5788fa13c05 100644 --- a/fuzzers/others/libafl_atheris/src/lib.rs +++ b/fuzzers/others/libafl_atheris/src/lib.rs @@ -22,8 +22,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, - token_mutations::{I2SRandReplace, Tokens}, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::{I2SRandReplace, Tokens}, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, diff --git a/fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs b/fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs index 99db317f11f..bdbb27bf7ca 100644 --- a/fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs +++ b/fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs @@ -16,8 +16,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, - token_mutations::Tokens, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::StdMapObserver, schedulers::RandScheduler, diff --git a/fuzzers/others/libfuzzer_windows_asan/src/lib.rs b/fuzzers/others/libfuzzer_windows_asan/src/lib.rs index 0d1401a8d58..0bb900cb0b3 100644 --- a/fuzzers/others/libfuzzer_windows_asan/src/lib.rs +++ b/fuzzers/others/libfuzzer_windows_asan/src/lib.rs @@ -10,7 +10,10 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, - mutators::scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + mutators::{ + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, + }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{ powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, diff --git a/fuzzers/others/push_harness/src/main.rs b/fuzzers/others/push_harness/src/main.rs index 981a81ec5be..0fcd76594b8 100644 --- a/fuzzers/others/push_harness/src/main.rs +++ b/fuzzers/others/push_harness/src/main.rs @@ -12,8 +12,7 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::StdMapObserver, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/others/push_stage_harness/src/main.rs b/fuzzers/others/push_stage_harness/src/main.rs index 27c78c26efb..7cf9455b7cd 100644 --- a/fuzzers/others/push_stage_harness/src/main.rs +++ b/fuzzers/others/push_stage_harness/src/main.rs @@ -15,8 +15,7 @@ use libafl::{ fuzzer::StdFuzzer, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::StdMapObserver, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::{QueueScheduler, Scheduler}, stages::push::{PushStageSharedState, StdMutationalPushStage}, state::{HasCorpus, StdState}, diff --git a/fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs b/fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs index ececbea5e66..f05f5ab7a47 100644 --- a/fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs +++ b/fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs @@ -19,8 +19,8 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, - token_mutations::Tokens, + havoc_mutations::havoc_mutations, + scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, diff --git a/fuzzers/qemu/qemu_launcher/src/instance.rs b/fuzzers/qemu/qemu_launcher/src/instance.rs index 12ba81c432e..a1e3f31094d 100644 --- a/fuzzers/qemu/qemu_launcher/src/instance.rs +++ b/fuzzers/qemu/qemu_launcher/src/instance.rs @@ -15,8 +15,8 @@ use libafl::{ inputs::BytesInput, monitors::Monitor, mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, + havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, + StdScheduledMutator, Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{ diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs index 74c09f950ce..d3f395b3142 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs @@ -12,8 +12,7 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::BytesInput, monitors::MultiMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::{CalibrationStage, StdMutationalStage}, state::{HasCorpus, StdState}, diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs index 441cc5e1e61..c753e1d558a 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs @@ -12,8 +12,7 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, StdState}, diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs index ca60a95c0f7..cf2a5eafb7a 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs @@ -11,8 +11,7 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::BytesInput, monitors::MultiMonitor, - mutators::scheduled::{havoc_mutations, StdScheduledMutator}, - observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, +mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::{CalibrationStage, StdMutationalStage}, state::{HasCorpus, StdState}, diff --git a/fuzzers/stb/libfuzzer_stb_image/src/main.rs b/fuzzers/stb/libfuzzer_stb_image/src/main.rs index c59fa70cf7f..964d2b26c51 100644 --- a/fuzzers/stb/libfuzzer_stb_image/src/main.rs +++ b/fuzzers/stb/libfuzzer_stb_image/src/main.rs @@ -16,7 +16,7 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator, token_mutations::I2SRandReplace, }, observers::{CanTrack, TimeObserver}, diff --git a/fuzzers/stb/libfuzzer_stb_image_concolic/fuzzer/src/main.rs b/fuzzers/stb/libfuzzer_stb_image_concolic/fuzzer/src/main.rs index cbe6e1d7fdd..611b4cb05e7 100644 --- a/fuzzers/stb/libfuzzer_stb_image_concolic/fuzzer/src/main.rs +++ b/fuzzers/stb/libfuzzer_stb_image_concolic/fuzzer/src/main.rs @@ -20,7 +20,7 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes, Input}, monitors::MultiMonitor, mutators::{ - scheduled::{havoc_mutations, StdScheduledMutator}, + havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator, token_mutations::I2SRandReplace, }, observers::{ From a6720414589b4e52c1f57619b0a375db08dc020f Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 23:34:13 +0000 Subject: [PATCH 15/32] fixing formatting --- .../rust_code_with_inprocess_executor/src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs index 0a496e4c7f5..ed7ffe4e5dc 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs @@ -12,7 +12,8 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{BacktraceObserver, StdMapObserver}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::{BacktraceObserver, StdMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, From 4d3b8a102db181257ae207991c4a15beccee7df6 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 23 Jul 2024 23:38:50 +0000 Subject: [PATCH 16/32] formatting fixes --- fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs | 3 ++- .../c_code_with_inprocess_executor/src/main.rs | 3 ++- .../backtrace_baby_fuzzers/forkserver_executor/src/main.rs | 3 ++- .../rust_code_with_fork_executor/src/main.rs | 3 ++- fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs | 3 ++- fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs | 3 ++- fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs | 3 ++- fuzzers/others/libafl_atheris/src/lib.rs | 3 ++- fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs | 3 ++- fuzzers/others/push_harness/src/main.rs | 3 ++- fuzzers/others/push_stage_harness/src/main.rs | 3 ++- fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs | 3 ++- fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs | 3 ++- fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs | 3 ++- fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs | 3 ++- 15 files changed, 30 insertions(+), 15 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs b/fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs index 717c71e3678..962f3e0d045 100644 --- a/fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_with_forkexecutor/src/main.rs @@ -11,7 +11,8 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs index eaa13efd13e..9dbdb61dc9d 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs @@ -10,7 +10,8 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{BacktraceObserver, ConstMapObserver}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::{BacktraceObserver, ConstMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs index b20633e051c..e0322e930ab 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs @@ -10,7 +10,8 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::BytesInput, monitors::SimpleMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{AsanBacktraceObserver, ConstMapObserver, HitcountsMapObserver}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::{AsanBacktraceObserver, ConstMapObserver, HitcountsMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs index d500829e34d..c88ca609529 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs @@ -12,7 +12,8 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{BacktraceObserver, StdMapObserver}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::{BacktraceObserver, StdMapObserver}, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs index d8afc674db2..6d626124e40 100644 --- a/fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_launcher/src/lib.rs @@ -17,7 +17,8 @@ use libafl::{ monitors::{MultiMonitor, OnDiskTomlMonitor}, mutators::{ havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, + scheduled::{tokens_mutations, StdScheduledMutator}, + token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, diff --git a/fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs index 4d89772cedb..79f9e22ade9 100644 --- a/fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_norestart/src/lib.rs @@ -21,7 +21,8 @@ use libafl::{ monitors::{MultiMonitor, OnDiskTomlMonitor}, mutators::{ havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, + scheduled::{tokens_mutations, StdScheduledMutator}, + token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, diff --git a/fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs b/fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs index fccd7067951..d8b109f73ba 100644 --- a/fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs +++ b/fuzzers/libpng/libfuzzer_libpng_tcp_manager/src/lib.rs @@ -16,7 +16,8 @@ use libafl::{ monitors::MultiMonitor, mutators::{ havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, + scheduled::{tokens_mutations, StdScheduledMutator}, + token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{ diff --git a/fuzzers/others/libafl_atheris/src/lib.rs b/fuzzers/others/libafl_atheris/src/lib.rs index 5788fa13c05..da8b1d03fd9 100644 --- a/fuzzers/others/libafl_atheris/src/lib.rs +++ b/fuzzers/others/libafl_atheris/src/lib.rs @@ -23,7 +23,8 @@ use libafl::{ monitors::MultiMonitor, mutators::{ havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::{I2SRandReplace, Tokens}, + scheduled::{tokens_mutations, StdScheduledMutator}, + token_mutations::{I2SRandReplace, Tokens}, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, diff --git a/fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs b/fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs index bdbb27bf7ca..aabdf32c9fb 100644 --- a/fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs +++ b/fuzzers/others/libfuzzer_libmozjpeg/src/lib.rs @@ -17,7 +17,8 @@ use libafl::{ monitors::SimpleMonitor, mutators::{ havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, + scheduled::{tokens_mutations, StdScheduledMutator}, + token_mutations::Tokens, }, observers::StdMapObserver, schedulers::RandScheduler, diff --git a/fuzzers/others/push_harness/src/main.rs b/fuzzers/others/push_harness/src/main.rs index 0fcd76594b8..2614bad70fe 100644 --- a/fuzzers/others/push_harness/src/main.rs +++ b/fuzzers/others/push_harness/src/main.rs @@ -12,7 +12,8 @@ use libafl::{ generators::RandPrintablesGenerator, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, diff --git a/fuzzers/others/push_stage_harness/src/main.rs b/fuzzers/others/push_stage_harness/src/main.rs index 7cf9455b7cd..4e90ac6b030 100644 --- a/fuzzers/others/push_stage_harness/src/main.rs +++ b/fuzzers/others/push_stage_harness/src/main.rs @@ -15,7 +15,8 @@ use libafl::{ fuzzer::StdFuzzer, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::StdMapObserver, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::StdMapObserver, schedulers::{QueueScheduler, Scheduler}, stages::push::{PushStageSharedState, StdMutationalPushStage}, state::{HasCorpus, StdState}, diff --git a/fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs b/fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs index f05f5ab7a47..f2d37be2ee8 100644 --- a/fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs +++ b/fuzzers/others/sqlite_centralized_multi_machine/src/lib.rs @@ -20,7 +20,8 @@ use libafl::{ monitors::MultiMonitor, mutators::{ havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, token_mutations::Tokens, + scheduled::{tokens_mutations, StdScheduledMutator}, + token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs index d3f395b3142..5fa38d43814 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs @@ -12,7 +12,8 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::BytesInput, monitors::MultiMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::{CalibrationStage, StdMutationalStage}, state::{HasCorpus, StdState}, diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs index c753e1d558a..c583d8b7209 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs @@ -12,7 +12,8 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, StdState}, diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs index cf2a5eafb7a..031750d6229 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs @@ -11,7 +11,8 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::BytesInput, monitors::MultiMonitor, -mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, + mutators::{havoc_mutations::havoc_mutations, scheduled::StdScheduledMutator}, + observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::{CalibrationStage, StdMutationalStage}, state::{HasCorpus, StdState}, From abc2458daab9d335aebf003760bfcb84c83d8793 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 7 Aug 2024 11:58:53 +0000 Subject: [PATCH 17/32] improving docs for the example fuzzer --- .../baby/baby_fuzzer_custom_input/src/input.rs | 17 +++++++++++++++++ .../baby/baby_fuzzer_custom_input/src/main.rs | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs index b80a6699d62..f5c0bde7daf 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs @@ -14,6 +14,12 @@ use libafl::{ use libafl_bolts::{rands::Rand, Named}; use serde::{Deserialize, Serialize}; +/// The custom [`Input`] type used in this example, consisting of a byte array part, a byte array that is not always present, and a boolean +/// +/// Imagine these could be used to model command line arguments for a bash command, where +/// - `byte_array` is binary data that is always needed like what is passed to stdin, +/// - `optional_byte_array` is binary data passed as a command line arg, and it is only passed if it is not `None` in the input, +/// - `boolean` models the presence or absence of a command line flag that does not require additional data #[derive(Serialize, Deserialize, Clone, Debug, Hash, SerdeAny)] pub struct CustomInput { pub byte_array: Vec, @@ -31,27 +37,34 @@ impl Input for CustomInput { } impl CustomInput { + /// Returns a mutable reference to the byte array pub fn byte_array_mut(&mut self) -> &mut Vec { &mut self.byte_array } + /// Returns an immutable reference to the byte array wrapped in [`Some`] pub fn byte_array_optional(&self) -> Option<&Vec> { Some(&self.byte_array) } + /// Returns a mutable reference to the optional byte array pub fn optional_byte_array_mut(&mut self) -> &mut Option> { &mut self.optional_byte_array } + + /// Returns an immutable reference to the optional byte array pub fn optional_byte_array_optional(&self) -> Option<&Vec> { self.optional_byte_array.as_ref() } } +/// A generator for [`CustomInput`] used in this example pub struct CustomInputGenerator { pub max_len: usize, } impl CustomInputGenerator { + /// Creates a new [`CustomInputGenerator`] pub fn new(max_len: usize) -> Self { Self { max_len } } @@ -77,6 +90,7 @@ where } } +/// Generate a [`Vec`] of a length between 1 (incl.) and `length` (incl.) filled with random bytes fn generate_bytes(length: usize, state: &mut S) -> Vec { let rand = state.rand_mut(); let len = rand.between(1, length); @@ -85,11 +99,13 @@ fn generate_bytes(length: usize, state: &mut S) -> Vec { vec } +/// [`Mutator`] that toggles the optional byte array of a [`CustomInput`], i.e. sets it to [`None`] if it is not, and to a random byte array if it is [`None`] pub struct ToggleOptionalByteArrayMutator { length: usize, } impl ToggleOptionalByteArrayMutator { + /// Creates a new [`ToggleOptionalByteArrayMutator`] pub fn new(length: usize) -> Self { Self { length } } @@ -114,6 +130,7 @@ impl Named for ToggleOptionalByteArrayMutator { } } +/// [`Mutator`] that toggles the boolean field in a [`CustomInput`] pub struct ToggleBooleanMutator; impl Mutator for ToggleBooleanMutator { diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index f5ae8fb6dd8..7fa06d241ea 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -43,6 +43,8 @@ fn signals_set(idx: usize) { #[allow(clippy::similar_names, clippy::manual_assert)] pub fn main() { // The closure that we want to fuzz + // The pseudo program under test uses all parts of the custom input + // We are manually setting bytes in a pseudo coverage map to guide the fuzzer let mut harness = |input: &CustomInput| { signals_set(0); if input.byte_array == vec![b'a'] { @@ -124,20 +126,29 @@ pub fn main() { .generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 8) .expect("Failed to generate the initial corpus"); + // Merging multiple lists of mutators that mutate a sub-part of the custom input + // This collection could be expanded with default or custom mutators as needed for the input + // First, mutators for the simple byte array let mutations = mapped_havoc_mutations( CustomInput::byte_array_mut, &CustomInput::byte_array_optional, ) + // Then, mutators for the optional byte array, these return MutationResult::Skipped if the part is not present .merge(optional_mapped_havoc_mutations( CustomInput::optional_byte_array_mut, &CustomInput::optional_byte_array_optional, )) + // A custom mutator that sets the optional byte array to None if present, and generates a random byte array of length 1 if it is not .append(ToggleOptionalByteArrayMutator::new(1)) + // Finally, a custom mutator that toggles the boolean part of the input .append(ToggleBooleanMutator); + // Scheduling layer for the mutations let mutator = StdScheduledMutator::new(mutations); + // Defining the mutator stage let mut stages = tuple_list!(StdMutationalStage::new(mutator)); + // Run the fuzzer fuzzer .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) .expect("Error in the fuzzing loop"); From 86e072bb4da158d2fbdbbcf00e8a14b00680ee1f Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 7 Aug 2024 13:14:55 +0000 Subject: [PATCH 18/32] adding documentation and tests to mapping mutators --- libafl/src/mutators/havoc_mutations.rs | 7 +- libafl/src/mutators/mapping.rs | 242 ++++++++++++++++++++----- 2 files changed, 195 insertions(+), 54 deletions(-) diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index 58fa7f184f4..244fe990073 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -3,11 +3,10 @@ use libafl_bolts::tuples::{Map, Merge}; use tuple_list::{tuple_list, tuple_list_type}; -use super::ToOptionMappingMutatorMapper; use crate::mutators::{ mapping::{ FunctionMappingMutator, MutVecMappingMutator, OptionMappingMutator, - ToFunctionMappingMutatorMapper, ToMutVecMappingMutatorMapper, + ToFunctionMappingMutatorMapper, ToMutVecMappingMutatorMapper, ToOptionMappingMutatorMapper, }, mutations::{ BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator, ByteIncMutator, @@ -121,7 +120,7 @@ pub type MappedHavocMutationsType<'a, F1, F2> = tuple_list_type!( FunctionMappingMutator>, F1>, ); -/// Tuple type of the mutations that compose the Havoc mutator for mapped input types +/// Tuple type of the mutations that compose the Havoc mutator for mapped input types, for optional byte array input parts pub type OptionMappedHavocMutationsType<'a, F1, F2> = tuple_list_type!( FunctionMappingMutator>, F1>, FunctionMappingMutator>, F1>, @@ -228,7 +227,7 @@ where .map(ToFunctionMappingMutatorMapper::new(current_input_mapper)) } -/// Get the mutations that compose the Havoc mutator for mapped input types +/// Get the mutations that compose the Havoc mutator for mapped input types, for optional byte array input parts #[must_use] pub fn optional_mapped_havoc_mutations( current_input_mapper: F1, diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index d6e9156f630..a22f2f3b1ea 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -9,12 +9,39 @@ use crate::{ Error, }; +/// Mapping [`Mutator`] that allows using [`Mutator`]s for [`Vec`] on (parts of) other input types that can be mapped to [`Vec`]. +/// +/// # Example +#[cfg_attr(feature = "std", doc = " ```")] +#[cfg_attr(not(feature = "std"), doc = " ```ignore")] +/// +/// use std::vec::Vec; +/// +/// use libafl::{ +/// mutators::{ +/// ByteIncMutator, MutationResult, MutVecMappingMutator, Mutator, +/// }, +/// state::NopState, +/// }; +/// +/// type CustomInput = Vec; +/// +/// let inner = ByteIncMutator::new(); +/// let mut outer = MutVecMappingMutator::new(inner); +/// +/// let mut input: CustomInput = vec![1]; +/// let mut state: NopState = NopState::new(); +/// let res = outer.mutate(&mut state, &mut input).unwrap(); +/// assert_eq!(res, MutationResult::Mutated); +/// assert_eq!(input, vec![2]); +/// ``` #[derive(Debug)] pub struct MutVecMappingMutator { inner: M, } impl MutVecMappingMutator { + /// Creates a new [`MutVecMappingMutator`] pub fn new(inner: M) -> Self { Self { inner } } @@ -38,6 +65,36 @@ where } } +/// Mapper to use when mapping a `tuple_list` of [`Mutator`]s defined for [`Vec`] for (parts of) a custom input type using a [`MutVecMappingMutator`]. +/// +/// # Example +#[cfg_attr(feature = "std", doc = " ```")] +#[cfg_attr(not(feature = "std"), doc = " ```ignore")] +/// +/// use std::vec::Vec; +/// +/// use libafl_bolts::tuples::Map; +/// use tuple_list::tuple_list; +/// +/// use libafl::{ +/// mutators::{ +/// ByteIncMutator, MutationResult, Mutator, ToMutVecMappingMutatorMapper +/// }, +/// state::NopState, +/// }; +/// +/// type CustomInput = Vec; +/// +/// let inner = tuple_list!(ByteIncMutator::new()); +/// let outer_list = inner.map(ToMutVecMappingMutatorMapper); +/// let mut outer = outer_list.0; +/// +/// let mut input: CustomInput = vec![1]; +/// let mut state: NopState = NopState::new(); +/// let res = outer.mutate(&mut state, &mut input).unwrap(); +/// assert_eq!(res, MutationResult::Mutated); +/// assert_eq!(input, vec![2]); +/// ``` #[derive(Debug)] pub struct ToMutVecMappingMutatorMapper; @@ -49,6 +106,37 @@ impl MappingFunctor for ToMutVecMappingMutatorMapper { } } +/// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type using a function. +/// +/// # Example +#[cfg_attr(feature = "std", doc = " ```")] +#[cfg_attr(not(feature = "std"), doc = " ```ignore")] +/// +/// use std::vec::Vec; +/// +/// use libafl::{ +/// mutators::{ +/// mapping::{FunctionMappingMutator, MutVecMappingMutator}, +/// ByteIncMutator, MutationResult, Mutator, +/// }, +/// state::NopState, +/// }; +/// +/// type CustomInput = (Vec,); +/// fn extract(input: &mut CustomInput) -> &mut Vec { +/// &mut input.0 +/// } +/// +/// let inner = MutVecMappingMutator::new(ByteIncMutator::new()); +/// let mut outer = FunctionMappingMutator::new(extract, inner); +/// +/// let mut input: CustomInput = (vec![1],); +/// +/// let mut state: NopState = NopState::new(); +/// let res = outer.mutate(&mut state, &mut input).unwrap(); +/// assert_eq!(res, MutationResult::Mutated); +/// assert_eq!(input, (vec![2],)); +/// ``` #[derive(Debug)] pub struct FunctionMappingMutator { mapper: F, @@ -56,6 +144,7 @@ pub struct FunctionMappingMutator { } impl FunctionMappingMutator { + /// Creates a new [`FunctionMappingMutator`] pub fn new(mapper: F, inner: M) -> Self { Self { mapper, inner } } @@ -77,12 +166,51 @@ impl Named for FunctionMappingMutator { } } +/// Mapper to use when mapping a `tuple_list` of [`Mutator`]s defined for a certain input type for (parts of) a custom input type using a [`FunctionMappingMutator`]. +/// +/// # Example +#[cfg_attr(feature = "std", doc = " ```")] +#[cfg_attr(not(feature = "std"), doc = " ```ignore")] +/// +/// use std::vec::Vec; +/// +/// use libafl_bolts::tuples::Map; +/// use tuple_list::tuple_list; +/// +/// use libafl::{ +/// inputs::MutVecInput, +/// mutators::{ +/// mapping::{ +/// ToFunctionMappingMutatorMapper, ToMutVecMappingMutatorMapper, +/// }, +/// ByteIncMutator, MutationResult, Mutator, +/// }, +/// state::NopState, +/// }; +/// +/// type CustomInput = (Vec,); +/// fn extract(input: &mut CustomInput) -> &mut Vec { +/// &mut input.0 +/// } +/// +/// let inner = tuple_list!(ByteIncMutator::new()).map(ToMutVecMappingMutatorMapper); +/// let outer_list = inner.map(ToFunctionMappingMutatorMapper::new(extract)); +/// let mut outer = outer_list.0; +/// +/// let mut input: CustomInput = (vec![1],); +/// +/// let mut state: NopState> = NopState::new(); +/// let res = outer.mutate(&mut state, &mut input).unwrap(); +/// assert_eq!(res, MutationResult::Mutated); +/// assert_eq!(input, (vec![2],)); +/// ``` #[derive(Debug)] pub struct ToFunctionMappingMutatorMapper { mapper: F, } impl ToFunctionMappingMutatorMapper { + /// Creates a new [`ToFunctionMappingMutatorMapper`] pub fn new(mapper: F) -> Self { Self { mapper } } @@ -99,12 +227,43 @@ where } } +/// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to an [`Option`] of said type. +/// +/// Returns [`MutationResult::Skipped`] if the mapper returns [`None`]. +/// +/// # Example +#[cfg_attr(feature = "std", doc = " ```")] +#[cfg_attr(not(feature = "std"), doc = " ```ignore")] +/// +/// use libafl::{ +/// inputs::MutVecInput, +/// mutators::{ +/// ByteIncMutator, MutationResult, Mutator, OptionMappingMutator +/// }, +/// state::NopState, +/// }; +/// let inner = ByteIncMutator::new(); +/// let mut outer = OptionMappingMutator::new(inner); +/// +/// let mut input_raw = vec![1]; +/// let input: MutVecInput = (&mut input_raw).into(); +/// let mut input_wrapped = Some(input); +/// let mut state: NopState> = NopState::new(); +/// let res = outer.mutate(&mut state, &mut input_wrapped).unwrap(); +/// assert_eq!(res, MutationResult::Mutated); +/// assert_eq!(input_raw, vec![2]); +/// +/// let mut empty_input: Option = None; +/// let res2 = outer.mutate(&mut state, &mut empty_input).unwrap(); +/// assert_eq!(res2, MutationResult::Skipped); +/// ``` #[derive(Debug)] pub struct OptionMappingMutator { inner: M, } impl OptionMappingMutator { + /// Creates a new [`OptionMappingMutator`] pub fn new(inner: M) -> Self { Self { inner } } @@ -131,6 +290,39 @@ where } } +/// Mapper to use when mapping a `tuple_list` of [`Mutator`]s defined for a certain input type for (parts of) a custom input type that can be mapped to an [`Option`] of said type using a [`OptionMappingMutator`]. +/// +/// # Example +#[cfg_attr(feature = "std", doc = " ```")] +#[cfg_attr(not(feature = "std"), doc = " ```ignore")] +/// +/// use libafl_bolts::tuples::Map; +/// use tuple_list::tuple_list; +/// +/// use libafl::{ +/// inputs::MutVecInput, +/// mutators::{ +/// ByteIncMutator, MutationResult, Mutator, ToOptionMappingMutatorMapper +/// }, +/// state::NopState, +/// }; +/// let inner = tuple_list!(ByteIncMutator::new()); +/// let outer_list = inner.map(ToOptionMappingMutatorMapper); +/// let mut outer = outer_list.0; +/// +/// let mut input_raw = vec![1]; +/// let input: MutVecInput = (&mut input_raw).into(); +/// let mut input_wrapped = Some(input); +/// let mut state: NopState> = NopState::new(); +/// let res = outer.mutate(&mut state, &mut input_wrapped).unwrap(); +/// assert_eq!(res, MutationResult::Mutated); +/// assert_eq!(input_raw, vec![2]); +/// +/// let mut empty_input: Option = None; +/// let res2 = outer.mutate(&mut state, &mut empty_input).unwrap(); +/// assert_eq!(res2, MutationResult::Skipped); + +/// ``` #[derive(Debug)] pub struct ToOptionMappingMutatorMapper; @@ -141,53 +333,3 @@ impl MappingFunctor for ToOptionMappingMutatorMapper { OptionMappingMutator::new(from) } } - -#[cfg(test)] -mod test { - use libafl_bolts::tuples::Map; - use tuple_list::tuple_list; - - use super::{OptionMappingMutator, ToOptionMappingMutatorMapper}; - use crate::{ - inputs::MutVecInput, - mutators::{ByteIncMutator, MutationResult, Mutator}, - state::NopState, - }; - - #[test] - fn test_option_mapping_mutator() { - let inner = ByteIncMutator::new(); - let mut outer = OptionMappingMutator::new(inner); - - let mut input_raw = vec![1]; - let input: MutVecInput = (&mut input_raw).into(); - let mut input_wrapped = Some(input); - let mut state: NopState> = NopState::new(); - let res = outer.mutate(&mut state, &mut input_wrapped).unwrap(); - assert_eq!(res, MutationResult::Mutated); - assert_eq!(input_raw, vec![2]); - - let mut empty_input: Option = None; - let res2 = outer.mutate(&mut state, &mut empty_input).unwrap(); - assert_eq!(res2, MutationResult::Skipped); - } - - #[test] - fn test_option_mapping_mutator_tuple_mapper() { - let inner = tuple_list!(ByteIncMutator::new()); - let outer_list = inner.map(ToOptionMappingMutatorMapper); - let mut outer = outer_list.0; - - let mut input_raw = vec![1]; - let input: MutVecInput = (&mut input_raw).into(); - let mut input_wrapped = Some(input); - let mut state: NopState> = NopState::new(); - let res = outer.mutate(&mut state, &mut input_wrapped).unwrap(); - assert_eq!(res, MutationResult::Mutated); - assert_eq!(input_raw, vec![2]); - - let mut empty_input: Option = None; - let res2 = outer.mutate(&mut state, &mut empty_input).unwrap(); - assert_eq!(res2, MutationResult::Skipped); - } -} From d8717285f9028ac9a44ad68adfd9c7e558e0da9c Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Thu, 5 Sep 2024 12:51:57 +0000 Subject: [PATCH 19/32] make extraction function for mapped crossover mutators more general --- fuzzers/baby/baby_fuzzer_custom_input/src/input.rs | 6 +++--- libafl/src/mutators/mutations.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs index f5c0bde7daf..dd60e4480d3 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs @@ -43,7 +43,7 @@ impl CustomInput { } /// Returns an immutable reference to the byte array wrapped in [`Some`] - pub fn byte_array_optional(&self) -> Option<&Vec> { + pub fn byte_array_optional(&self) -> Option<&[u8]> { Some(&self.byte_array) } @@ -53,8 +53,8 @@ impl CustomInput { } /// Returns an immutable reference to the optional byte array - pub fn optional_byte_array_optional(&self) -> Option<&Vec> { - self.optional_byte_array.as_ref() + pub fn optional_byte_array_optional(&self) -> Option<&[u8]> { + self.optional_byte_array.as_deref() } } diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index f785d8d3afd..b3e7f45d993 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -1204,7 +1204,7 @@ impl<'a, S, F, I> Mutator for MappedCrossoverInsertMutator<'a, F> where S: HasCorpus + HasMaxSize + HasRand + UsesInput, I: HasMutatorBytes, - F: for<'b> Fn(&'b S::Input) -> Option<&'b Vec>, + F: for<'b> Fn(&'b S::Input) -> Option<&'b [u8]>, { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { let size = input.bytes().len(); @@ -1224,7 +1224,7 @@ where let other_size = { let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); let other_input = other_testcase.load_input(state.corpus())?; - (self.input_from_corpus_mapper)(other_input).map_or(0, Vec::len) + (self.input_from_corpus_mapper)(other_input).map_or(0, <[u8]>::len) }; if other_size < 2 { @@ -1288,7 +1288,7 @@ impl<'a, S, I, F> Mutator for MappedCrossoverReplaceMutator<'a, F> where S: HasCorpus + HasMaxSize + HasRand + UsesInput, I: HasMutatorBytes, - F: for<'b> Fn(&'b S::Input) -> Option<&'b Vec>, + F: for<'b> Fn(&'b S::Input) -> Option<&'b [u8]>, { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { let size = input.bytes().len(); @@ -1307,7 +1307,7 @@ where let other_size = { let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); let other_input = other_testcase.load_input(state.corpus())?; - (self.input_from_corpus_mapper)(other_input).map_or(0, Vec::len) + (self.input_from_corpus_mapper)(other_input).map_or(0, <[u8]>::len) }; if other_size < 2 { From 5f1c5bc8cbbcc904b01a0b70dd3ed7b71f9047e9 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Sat, 7 Sep 2024 20:12:33 +0000 Subject: [PATCH 20/32] adding MutVecFunctionMappingMutator --- .../baby_fuzzer_custom_input/src/input.rs | 13 ++++- .../baby/baby_fuzzer_custom_input/src/main.rs | 15 +++++- libafl/src/mutators/mapping.rs | 53 ++++++++++++++++++- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs index dd60e4480d3..e1dcb4ac0fd 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs @@ -6,7 +6,7 @@ use std::{ use libafl::{ corpus::CorpusId, generators::Generator, - inputs::Input, + inputs::{Input, MutVecInput}, prelude::{MutationResult, Mutator}, state::HasRand, Error, SerdeAny, @@ -24,6 +24,7 @@ use serde::{Deserialize, Serialize}; pub struct CustomInput { pub byte_array: Vec, pub optional_byte_array: Option>, + pub byte_array_custom_mapper: Vec, pub boolean: bool, } @@ -56,6 +57,14 @@ impl CustomInput { pub fn optional_byte_array_optional(&self) -> Option<&[u8]> { self.optional_byte_array.as_deref() } + + pub fn byte_array_custom_mapper(&mut self) -> MutVecInput<'_> { + MutVecInput::from(&mut self.byte_array_custom_mapper) + } + + pub fn byte_array_custom_mapper_corpus_extractor(&self) -> Option<&[u8]> { + Some(&self.byte_array_custom_mapper) + } } /// A generator for [`CustomInput`] used in this example @@ -80,11 +89,13 @@ where .rand_mut() .coinflip(0.5) .then(|| generate_bytes(self.max_len, state)); + let byte_array_custom_mapper = generate_bytes(self.max_len, state); let boolean = state.rand_mut().coinflip(0.5); Ok(CustomInput { byte_array, optional_byte_array, + byte_array_custom_mapper, boolean, }) } diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index 7fa06d241ea..e12bfea975f 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -18,6 +18,10 @@ use libafl::{ mapped_havoc_mutations, optional_mapped_havoc_mutations, scheduled::StdScheduledMutator, }, observers::StdMapObserver, + prelude::{ + havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover, + ToMutVecFunctionMappingMutatorMapper, + }, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, @@ -25,7 +29,7 @@ use libafl::{ use libafl_bolts::{ current_nanos, rands::StdRand, - tuples::{tuple_list, Append, Merge}, + tuples::{tuple_list, Append, Map, Merge}, }; /// Coverage map with explicit assignments due to the lack of instrumentation @@ -126,6 +130,14 @@ pub fn main() { .generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 8) .expect("Failed to generate the initial corpus"); + let custom_mapped_mutators = havoc_mutations_no_crossover() + .merge(havoc_crossover_with_corpus_mapper( + &CustomInput::byte_array_custom_mapper_corpus_extractor, + )) + .map(ToMutVecFunctionMappingMutatorMapper::new( + CustomInput::byte_array_custom_mapper, + )); + // Merging multiple lists of mutators that mutate a sub-part of the custom input // This collection could be expanded with default or custom mutators as needed for the input // First, mutators for the simple byte array @@ -140,6 +152,7 @@ pub fn main() { )) // A custom mutator that sets the optional byte array to None if present, and generates a random byte array of length 1 if it is not .append(ToggleOptionalByteArrayMutator::new(1)) + .merge(custom_mapped_mutators) // Finally, a custom mutator that toggles the boolean part of the input .append(ToggleBooleanMutator); diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index a22f2f3b1ea..bdaacff1e2a 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -4,7 +4,7 @@ use alloc::{borrow::Cow, vec::Vec}; use libafl_bolts::{tuples::MappingFunctor, Named}; use crate::{ - inputs::MutVecInput, + inputs::{HasMutatorBytes, MutVecInput}, mutators::{MutationResult, Mutator}, Error, }; @@ -166,6 +166,35 @@ impl Named for FunctionMappingMutator { } } +#[derive(Debug)] +pub struct MutVecFunctionMappingMutator { + mapper: F, + inner: M, +} + +impl MutVecFunctionMappingMutator { + /// Creates a new [`OwnedFunctionMappingMutator`] + pub fn new(mapper: F, inner: M) -> Self { + Self { mapper, inner } + } +} + +impl Mutator for MutVecFunctionMappingMutator +where + F: for<'a> FnMut(&'a mut IO) -> MutVecInput<'a>, + M: for<'a> Mutator, S>, +{ + fn mutate(&mut self, state: &mut S, input: &mut IO) -> Result { + self.inner.mutate(state, &mut &mut (self.mapper)(input)) + } +} + +impl Named for MutVecFunctionMappingMutator { + fn name(&self) -> &Cow<'static, str> { + &Cow::Borrowed("OwnedFunctionMappingMutator") + } +} + /// Mapper to use when mapping a `tuple_list` of [`Mutator`]s defined for a certain input type for (parts of) a custom input type using a [`FunctionMappingMutator`]. /// /// # Example @@ -226,6 +255,28 @@ where FunctionMappingMutator::new(self.mapper.clone(), from) } } +#[derive(Debug)] +pub struct ToMutVecFunctionMappingMutatorMapper { + mapper: F, +} + +impl ToMutVecFunctionMappingMutatorMapper { + /// Creates a new [`ToOwnedFunctionMappingMutatorMapper`] + pub fn new(mapper: F) -> Self { + Self { mapper } + } +} + +impl MappingFunctor for ToMutVecFunctionMappingMutatorMapper +where + F: Clone, +{ + type Output = MutVecFunctionMappingMutator; + + fn apply(&mut self, from: M) -> Self::Output { + MutVecFunctionMappingMutator::new(self.mapper.clone(), from) + } +} /// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to an [`Option`] of said type. /// From 1171cc0c3fab9a112b10e39738b96220c826c2bb Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Mon, 9 Sep 2024 12:43:38 +0000 Subject: [PATCH 21/32] Introducing WrapsReference --- .../baby_fuzzer_custom_input/src/input.rs | 15 +++--- .../baby/baby_fuzzer_custom_input/src/main.rs | 21 ++++---- libafl/src/inputs/bytessub.rs | 6 +++ libafl/src/inputs/mod.rs | 10 ++++ libafl/src/mutators/mapping.rs | 50 ++++++++++++------- 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs index e1dcb4ac0fd..1772cd9cf61 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs @@ -24,7 +24,7 @@ use serde::{Deserialize, Serialize}; pub struct CustomInput { pub byte_array: Vec, pub optional_byte_array: Option>, - pub byte_array_custom_mapper: Vec, + pub byte_array_mutvec_mapper: Vec, pub boolean: bool, } @@ -58,12 +58,13 @@ impl CustomInput { self.optional_byte_array.as_deref() } - pub fn byte_array_custom_mapper(&mut self) -> MutVecInput<'_> { - MutVecInput::from(&mut self.byte_array_custom_mapper) + pub fn byte_array_mutvec_mapper(&mut self) -> MutVecInput<'_> { + MutVecInput::from(&mut self.byte_array_mutvec_mapper) } - pub fn byte_array_custom_mapper_corpus_extractor(&self) -> Option<&[u8]> { - Some(&self.byte_array_custom_mapper) + // TODO: Comment + pub fn byte_array_mutvec_mapper_corpus_extractor(&self) -> Option<&[u8]> { + Some(&self.byte_array_mutvec_mapper) } } @@ -89,13 +90,13 @@ where .rand_mut() .coinflip(0.5) .then(|| generate_bytes(self.max_len, state)); - let byte_array_custom_mapper = generate_bytes(self.max_len, state); + let byte_array_mutvec_mapper = generate_bytes(self.max_len, state); let boolean = state.rand_mut().coinflip(0.5); Ok(CustomInput { byte_array, optional_byte_array, - byte_array_custom_mapper, + byte_array_mutvec_mapper, boolean, }) } diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index e12bfea975f..4bc1958825e 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -13,15 +13,17 @@ use libafl::{ executors::{inprocess::InProcessExecutor, ExitKind}, feedbacks::{CrashFeedback, MaxMapFeedback}, fuzzer::{Fuzzer, StdFuzzer}, + inputs::MutVecInput, monitors::SimpleMonitor, mutators::{ - mapped_havoc_mutations, optional_mapped_havoc_mutations, scheduled::StdScheduledMutator, + havoc_mutations::{ + havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover, + mapped_havoc_mutations, optional_mapped_havoc_mutations, + }, + mapping::ToWrapsReferenceFunctionMappingMutatorMapper, + scheduled::StdScheduledMutator, }, observers::StdMapObserver, - prelude::{ - havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover, - ToMutVecFunctionMappingMutatorMapper, - }, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, @@ -132,11 +134,12 @@ pub fn main() { let custom_mapped_mutators = havoc_mutations_no_crossover() .merge(havoc_crossover_with_corpus_mapper( - &CustomInput::byte_array_custom_mapper_corpus_extractor, + &CustomInput::byte_array_mutvec_mapper_corpus_extractor, )) - .map(ToMutVecFunctionMappingMutatorMapper::new( - CustomInput::byte_array_custom_mapper, - )); + .map(ToWrapsReferenceFunctionMappingMutatorMapper::< + _, + MutVecInput<'_>, + >::new(CustomInput::byte_array_mutvec_mapper)); // Merging multiple lists of mutators that mutate a sub-part of the custom input // This collection could be expanded with default or custom mutators as needed for the input diff --git a/libafl/src/inputs/bytessub.rs b/libafl/src/inputs/bytessub.rs index aaf8f5a9a70..5fccf4c6ce9 100644 --- a/libafl/src/inputs/bytessub.rs +++ b/libafl/src/inputs/bytessub.rs @@ -13,6 +13,8 @@ use libafl_bolts::{ use crate::inputs::HasMutatorBytes; +use super::WrapsReference; + /// The [`BytesSubInput`] makes it possible to use [`crate::mutators::Mutator`]`s` that work on /// inputs implementing the [`HasMutatorBytes`] for a sub-range of this input. /// For example, we can do the following: @@ -201,6 +203,10 @@ where } } +impl<'a, I> WrapsReference for BytesSubInput<'a, I> { + type Type<'b> = BytesSubInput<'b, I> where Self: 'b; +} + #[cfg(test)] mod tests { diff --git a/libafl/src/inputs/mod.rs b/libafl/src/inputs/mod.rs index 75bba866bc5..a9f0a3d11e5 100644 --- a/libafl/src/inputs/mod.rs +++ b/libafl/src/inputs/mod.rs @@ -195,6 +195,12 @@ pub trait HasMutatorBytes: HasLen { } } +pub trait WrapsReference { + type Type<'a> + where + Self: 'a; +} + /// A wrapper type that allows us to use mutators for Mutators for `&mut `[`Vec`]. #[derive(Debug)] pub struct MutVecInput<'a>(&'a mut Vec); @@ -244,6 +250,10 @@ impl<'a> HasMutatorBytes for MutVecInput<'a> { } } +impl<'a> WrapsReference for MutVecInput<'a> { + type Type<'b> = MutVecInput<'b> where Self: 'b; +} + /// Defines the input type shared across traits of the type. /// Needed for consistency across HasCorpus/HasSolutions and friends. pub trait UsesInput { diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index bdaacff1e2a..dfb51ad46e5 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -1,10 +1,12 @@ //! Allowing mixing and matching between [`Mutator`] and [`crate::inputs::Input`] types. +use core::marker::PhantomData; + use alloc::{borrow::Cow, vec::Vec}; use libafl_bolts::{tuples::MappingFunctor, Named}; use crate::{ - inputs::{HasMutatorBytes, MutVecInput}, + inputs::{MutVecInput, WrapsReference}, mutators::{MutationResult, Mutator}, Error, }; @@ -167,31 +169,38 @@ impl Named for FunctionMappingMutator { } #[derive(Debug)] -pub struct MutVecFunctionMappingMutator { +pub struct WrapsReferenceFunctionMappingMutator { mapper: F, inner: M, + phantom: PhantomData, } -impl MutVecFunctionMappingMutator { - /// Creates a new [`OwnedFunctionMappingMutator`] +impl WrapsReferenceFunctionMappingMutator { + /// Creates a new [`WrapsReferenceFunctionMappingMutator`] pub fn new(mapper: F, inner: M) -> Self { - Self { mapper, inner } + Self { + mapper, + inner, + phantom: PhantomData, + } } } -impl Mutator for MutVecFunctionMappingMutator +impl Mutator for WrapsReferenceFunctionMappingMutator where - F: for<'a> FnMut(&'a mut IO) -> MutVecInput<'a>, - M: for<'a> Mutator, S>, + for<'a> M: Mutator, S>, + for<'a> II: WrapsReference + 'a, + F: for<'a> FnMut(&'a mut IO) -> II::Type<'a>, { fn mutate(&mut self, state: &mut S, input: &mut IO) -> Result { - self.inner.mutate(state, &mut &mut (self.mapper)(input)) + let mapped = &mut (self.mapper)(input); + self.inner.mutate(state, mapped) } } -impl Named for MutVecFunctionMappingMutator { +impl Named for WrapsReferenceFunctionMappingMutator { fn name(&self) -> &Cow<'static, str> { - &Cow::Borrowed("OwnedFunctionMappingMutator") + &Cow::Borrowed("WrapsReferenceFunctionMappingMutator") } } @@ -255,26 +264,31 @@ where FunctionMappingMutator::new(self.mapper.clone(), from) } } + #[derive(Debug)] -pub struct ToMutVecFunctionMappingMutatorMapper { +pub struct ToWrapsReferenceFunctionMappingMutatorMapper { mapper: F, + phantom: PhantomData, } -impl ToMutVecFunctionMappingMutatorMapper { - /// Creates a new [`ToOwnedFunctionMappingMutatorMapper`] +impl ToWrapsReferenceFunctionMappingMutatorMapper { + /// Creates a new [`ToWrapsReferenceFunctionMappingMutatorMapper`] pub fn new(mapper: F) -> Self { - Self { mapper } + Self { + mapper, + phantom: PhantomData, + } } } -impl MappingFunctor for ToMutVecFunctionMappingMutatorMapper +impl MappingFunctor for ToWrapsReferenceFunctionMappingMutatorMapper where F: Clone, { - type Output = MutVecFunctionMappingMutator; + type Output = WrapsReferenceFunctionMappingMutator; fn apply(&mut self, from: M) -> Self::Output { - MutVecFunctionMappingMutator::new(self.mapper.clone(), from) + WrapsReferenceFunctionMappingMutator::new(self.mapper.clone(), from) } } From 3a40f766a9ea33b8b0c685f1d75e4336160496a0 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Tue, 10 Sep 2024 20:04:56 +0000 Subject: [PATCH 22/32] code cleanup for mapping mutators --- .../baby/baby_fuzzer_custom_input/Cargo.toml | 4 + .../baby_fuzzer_custom_input/src/input.rs | 22 +-- .../baby/baby_fuzzer_custom_input/src/main.rs | 112 +++++++---- libafl/src/inputs/bytessub.rs | 4 +- libafl/src/inputs/mod.rs | 16 +- libafl/src/mutators/havoc_mutations.rs | 146 +++++++------- libafl/src/mutators/mapping.rs | 185 +++++------------- 7 files changed, 225 insertions(+), 264 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml b/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml index c8c76fe60ff..e27cbfe32ec 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml +++ b/fuzzers/baby/baby_fuzzer_custom_input/Cargo.toml @@ -4,6 +4,10 @@ version = "0.1.0" authors = ["Valentin Huber "] edition = "2021" +[features] +default = ["simple_interface"] +simple_interface = [] + [profile.dev] panic = "abort" diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs index 1772cd9cf61..01d5dcf1640 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs @@ -7,7 +7,7 @@ use libafl::{ corpus::CorpusId, generators::Generator, inputs::{Input, MutVecInput}, - prelude::{MutationResult, Mutator}, + mutators::{MutationResult, Mutator}, state::HasRand, Error, SerdeAny, }; @@ -24,7 +24,6 @@ use serde::{Deserialize, Serialize}; pub struct CustomInput { pub byte_array: Vec, pub optional_byte_array: Option>, - pub byte_array_mutvec_mapper: Vec, pub boolean: bool, } @@ -39,8 +38,8 @@ impl Input for CustomInput { impl CustomInput { /// Returns a mutable reference to the byte array - pub fn byte_array_mut(&mut self) -> &mut Vec { - &mut self.byte_array + pub fn byte_array_mut(&mut self) -> MutVecInput<'_> { + (&mut self.byte_array).into() } /// Returns an immutable reference to the byte array wrapped in [`Some`] @@ -49,23 +48,14 @@ impl CustomInput { } /// Returns a mutable reference to the optional byte array - pub fn optional_byte_array_mut(&mut self) -> &mut Option> { - &mut self.optional_byte_array + pub fn optional_byte_array_mut(&mut self) -> Option> { + self.optional_byte_array.as_mut().map(|e| e.into()) } /// Returns an immutable reference to the optional byte array pub fn optional_byte_array_optional(&self) -> Option<&[u8]> { self.optional_byte_array.as_deref() } - - pub fn byte_array_mutvec_mapper(&mut self) -> MutVecInput<'_> { - MutVecInput::from(&mut self.byte_array_mutvec_mapper) - } - - // TODO: Comment - pub fn byte_array_mutvec_mapper_corpus_extractor(&self) -> Option<&[u8]> { - Some(&self.byte_array_mutvec_mapper) - } } /// A generator for [`CustomInput`] used in this example @@ -90,13 +80,11 @@ where .rand_mut() .coinflip(0.5) .then(|| generate_bytes(self.max_len, state)); - let byte_array_mutvec_mapper = generate_bytes(self.max_len, state); let boolean = state.rand_mut().coinflip(0.5); Ok(CustomInput { byte_array, optional_byte_array, - byte_array_mutvec_mapper, boolean, }) } diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index 4bc1958825e..5ed0eda0aec 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -15,23 +15,28 @@ use libafl::{ fuzzer::{Fuzzer, StdFuzzer}, inputs::MutVecInput, monitors::SimpleMonitor, - mutators::{ - havoc_mutations::{ - havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover, - mapped_havoc_mutations, optional_mapped_havoc_mutations, - }, - mapping::ToWrapsReferenceFunctionMappingMutatorMapper, - scheduled::StdScheduledMutator, - }, + mutators::{mapping::MappedInputFunctionMappingMutator, scheduled::StdScheduledMutator}, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, state::StdState, }; + use libafl_bolts::{ current_nanos, rands::StdRand, - tuples::{tuple_list, Append, Map, Merge}, + tuples::{tuple_list, Append, Merge}, +}; + +#[cfg(feature = "simple_interface")] +use libafl::mutators::havoc_mutations::{mapped_havoc_mutations, optional_mapped_havoc_mutations}; +#[cfg(not(feature = "simple_interface"))] +use { + libafl::mutators::{ + havoc_mutations::{havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover}, + mapping::{ToMappedInputFunctionMappingMutatorMapper, ToOptionMappingMutatorMapper}, + }, + libafl_bolts::tuples::Map, }; /// Coverage map with explicit assignments due to the lack of instrumentation @@ -132,37 +137,78 @@ pub fn main() { .generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 8) .expect("Failed to generate the initial corpus"); - let custom_mapped_mutators = havoc_mutations_no_crossover() - .merge(havoc_crossover_with_corpus_mapper( - &CustomInput::byte_array_mutvec_mapper_corpus_extractor, - )) - .map(ToWrapsReferenceFunctionMappingMutatorMapper::< + #[cfg(feature = "simple_interface")] + let (mapped_mutators, optional_mapped_mutators) = { + // Creating mutators that will operate on input.byte_array + // For now, due to a limitation in lifetime management (see the MappedInput trait), + // the types have to be partially specified + let mapped_mutators: (MappedInputFunctionMappingMutator<_, _, MutVecInput<'_>>, _) = + mapped_havoc_mutations( + CustomInput::byte_array_mut, + &CustomInput::byte_array_optional, + ); + + // Creating mutators that will operate on input.optional_byte_array + // For now, due to a limitation in lifetime management (see the MappedInput trait), + // the types have to be partially specified + let optional_mapped_mutators: ( + MappedInputFunctionMappingMutator<_, _, Option>>, _, - MutVecInput<'_>, - >::new(CustomInput::byte_array_mutvec_mapper)); + ) = optional_mapped_havoc_mutations( + CustomInput::optional_byte_array_mut, + &CustomInput::optional_byte_array_optional, + ); + (mapped_mutators, optional_mapped_mutators) + }; + + #[cfg(not(feature = "simple_interface"))] + let (mapped_mutators, optional_mapped_mutators) = { + // Creating mutators that will operate on input.byte_array + // For now, due to a limitation in lifetime management (see the MappedInput trait), + // the types have to be partially specified + let mapped_mutators: (MappedInputFunctionMappingMutator<_, _, MutVecInput<'_>>, _) = + havoc_mutations_no_crossover() + .merge(havoc_crossover_with_corpus_mapper( + &CustomInput::byte_array_optional, + )) + .map(ToMappedInputFunctionMappingMutatorMapper::new( + CustomInput::byte_array_mut, + )); + + // Creating mutators that will operate on input.optional_byte_array + // For now, due to a limitation in lifetime management (see the MappedInput trait), + // the types have to be partially specified + let optional_mapped_mutators: ( + MappedInputFunctionMappingMutator<_, _, Option>>, + _, + ) = havoc_mutations_no_crossover() + .merge(havoc_crossover_with_corpus_mapper( + &CustomInput::optional_byte_array_optional, + )) + .map(ToOptionMappingMutatorMapper) + .map(ToMappedInputFunctionMappingMutatorMapper::new( + CustomInput::optional_byte_array_mut, + )); + + (mapped_mutators, optional_mapped_mutators) + }; // Merging multiple lists of mutators that mutate a sub-part of the custom input // This collection could be expanded with default or custom mutators as needed for the input - // First, mutators for the simple byte array - let mutations = mapped_havoc_mutations( - CustomInput::byte_array_mut, - &CustomInput::byte_array_optional, - ) - // Then, mutators for the optional byte array, these return MutationResult::Skipped if the part is not present - .merge(optional_mapped_havoc_mutations( - CustomInput::optional_byte_array_mut, - &CustomInput::optional_byte_array_optional, - )) - // A custom mutator that sets the optional byte array to None if present, and generates a random byte array of length 1 if it is not - .append(ToggleOptionalByteArrayMutator::new(1)) - .merge(custom_mapped_mutators) - // Finally, a custom mutator that toggles the boolean part of the input - .append(ToggleBooleanMutator); + let mutators = tuple_list!() + // First, mutators for the simple byte array + .merge(mapped_mutators) + // Then, mutators for the optional byte array, these return MutationResult::Skipped if the part is not present + .merge(optional_mapped_mutators) + // A custom mutator that sets the optional byte array to None if present, and generates a random byte array of length 1 if it is not + .append(ToggleOptionalByteArrayMutator::new(1)) + // Finally, a custom mutator that toggles the boolean part of the input + .append(ToggleBooleanMutator); // Scheduling layer for the mutations - let mutator = StdScheduledMutator::new(mutations); + let mutator_scheduler = StdScheduledMutator::new(mutators); // Defining the mutator stage - let mut stages = tuple_list!(StdMutationalStage::new(mutator)); + let mut stages = tuple_list!(StdMutationalStage::new(mutator_scheduler)); // Run the fuzzer fuzzer diff --git a/libafl/src/inputs/bytessub.rs b/libafl/src/inputs/bytessub.rs index 5fccf4c6ce9..9d3d8211407 100644 --- a/libafl/src/inputs/bytessub.rs +++ b/libafl/src/inputs/bytessub.rs @@ -13,7 +13,7 @@ use libafl_bolts::{ use crate::inputs::HasMutatorBytes; -use super::WrapsReference; +use super::MappedInput; /// The [`BytesSubInput`] makes it possible to use [`crate::mutators::Mutator`]`s` that work on /// inputs implementing the [`HasMutatorBytes`] for a sub-range of this input. @@ -203,7 +203,7 @@ where } } -impl<'a, I> WrapsReference for BytesSubInput<'a, I> { +impl<'a, I> MappedInput for BytesSubInput<'a, I> { type Type<'b> = BytesSubInput<'b, I> where Self: 'b; } diff --git a/libafl/src/inputs/mod.rs b/libafl/src/inputs/mod.rs index a9f0a3d11e5..85bc929b693 100644 --- a/libafl/src/inputs/mod.rs +++ b/libafl/src/inputs/mod.rs @@ -195,12 +195,24 @@ pub trait HasMutatorBytes: HasLen { } } -pub trait WrapsReference { +/// Mapping types to themselves, used to ensure lifetime consistency for mapped mutators. +/// +/// Specifically, this is for [`Input`] types that are owned wrappers around a reference. The lifetime of the associated type should be the same as the reference. +pub trait MappedInput { + /// The type for which this trait is implemented type Type<'a> where Self: 'a; } +impl MappedInput for Option +where + T: MappedInput, +{ + type Type<'a> = Option> + where T: 'a; +} + /// A wrapper type that allows us to use mutators for Mutators for `&mut `[`Vec`]. #[derive(Debug)] pub struct MutVecInput<'a>(&'a mut Vec); @@ -250,7 +262,7 @@ impl<'a> HasMutatorBytes for MutVecInput<'a> { } } -impl<'a> WrapsReference for MutVecInput<'a> { +impl<'a> MappedInput for MutVecInput<'a> { type Type<'b> = MutVecInput<'b> where Self: 'b; } diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index 244fe990073..f9740f385db 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -5,8 +5,8 @@ use tuple_list::{tuple_list, tuple_list_type}; use crate::mutators::{ mapping::{ - FunctionMappingMutator, MutVecMappingMutator, OptionMappingMutator, - ToFunctionMappingMutatorMapper, ToMutVecMappingMutatorMapper, ToOptionMappingMutatorMapper, + MappedInputFunctionMappingMutator, OptionMappingMutator, + ToMappedInputFunctionMappingMutatorMapper, ToOptionMappingMutatorMapper, }, mutations::{ BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator, ByteIncMutator, @@ -90,70 +90,72 @@ pub type HavocMutationsType = tuple_list_type!( ); /// Tuple type of the mutations that compose the Havoc mutator for mapped input types -pub type MappedHavocMutationsType<'a, F1, F2> = tuple_list_type!( - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, +pub type MappedHavocMutationsType<'a, F1, F2, II> = tuple_list_type!( + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, ); /// Tuple type of the mutations that compose the Havoc mutator for mapped input types, for optional byte array input parts -pub type OptionMappedHavocMutationsType<'a, F1, F2> = tuple_list_type!( - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator>, F1>, - FunctionMappingMutator< - OptionMappingMutator>>, +pub type OptionMappedHavocMutationsType<'a, F1, F2, II> = tuple_list_type!( + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator< + OptionMappingMutator>, F1, + II, >, - FunctionMappingMutator< - OptionMappingMutator>>, + MappedInputFunctionMappingMutator< + OptionMappingMutator>, F1, + II, >, ); @@ -213,32 +215,38 @@ pub fn havoc_mutations() -> HavocMutationsType { } /// Get the mutations that compose the Havoc mutator for mapped input types +/// +/// Check the example fuzzer for details on how to use this. #[must_use] -pub fn mapped_havoc_mutations( +pub fn mapped_havoc_mutations( current_input_mapper: F1, input_from_corpus_mapper: &F2, -) -> MappedHavocMutationsType<'_, F1, F2> +) -> MappedHavocMutationsType<'_, F1, F2, II> where F1: Clone, { havoc_mutations_no_crossover() .merge(havoc_crossover_with_corpus_mapper(input_from_corpus_mapper)) - .map(ToMutVecMappingMutatorMapper) - .map(ToFunctionMappingMutatorMapper::new(current_input_mapper)) + .map(ToMappedInputFunctionMappingMutatorMapper::new( + current_input_mapper, + )) } -/// Get the mutations that compose the Havoc mutator for mapped input types, for optional byte array input parts +/// Get the mutations that compose the Havoc mutator for mapped input types, for optional input parts +/// +/// Check the example fuzzer for details on how to use this. #[must_use] -pub fn optional_mapped_havoc_mutations( +pub fn optional_mapped_havoc_mutations( current_input_mapper: F1, input_from_corpus_mapper: &F2, -) -> OptionMappedHavocMutationsType<'_, F1, F2> +) -> OptionMappedHavocMutationsType<'_, F1, F2, II> where F1: Clone, { havoc_mutations_no_crossover() .merge(havoc_crossover_with_corpus_mapper(input_from_corpus_mapper)) - .map(ToMutVecMappingMutatorMapper) .map(ToOptionMappingMutatorMapper) - .map(ToFunctionMappingMutatorMapper::new(current_input_mapper)) + .map(ToMappedInputFunctionMappingMutatorMapper::new( + current_input_mapper, + )) } diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index dfb51ad46e5..dead45d9dac 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -1,113 +1,16 @@ //! Allowing mixing and matching between [`Mutator`] and [`crate::inputs::Input`] types. use core::marker::PhantomData; -use alloc::{borrow::Cow, vec::Vec}; +use alloc::borrow::Cow; use libafl_bolts::{tuples::MappingFunctor, Named}; use crate::{ - inputs::{MutVecInput, WrapsReference}, + inputs::MappedInput, mutators::{MutationResult, Mutator}, Error, }; -/// Mapping [`Mutator`] that allows using [`Mutator`]s for [`Vec`] on (parts of) other input types that can be mapped to [`Vec`]. -/// -/// # Example -#[cfg_attr(feature = "std", doc = " ```")] -#[cfg_attr(not(feature = "std"), doc = " ```ignore")] -/// -/// use std::vec::Vec; -/// -/// use libafl::{ -/// mutators::{ -/// ByteIncMutator, MutationResult, MutVecMappingMutator, Mutator, -/// }, -/// state::NopState, -/// }; -/// -/// type CustomInput = Vec; -/// -/// let inner = ByteIncMutator::new(); -/// let mut outer = MutVecMappingMutator::new(inner); -/// -/// let mut input: CustomInput = vec![1]; -/// let mut state: NopState = NopState::new(); -/// let res = outer.mutate(&mut state, &mut input).unwrap(); -/// assert_eq!(res, MutationResult::Mutated); -/// assert_eq!(input, vec![2]); -/// ``` -#[derive(Debug)] -pub struct MutVecMappingMutator { - inner: M, -} - -impl MutVecMappingMutator { - /// Creates a new [`MutVecMappingMutator`] - pub fn new(inner: M) -> Self { - Self { inner } - } -} - -impl Mutator, S> for MutVecMappingMutator -where - M: for<'a> Mutator, S>, -{ - fn mutate(&mut self, state: &mut S, input: &mut Vec) -> Result { - self.inner.mutate(state, &mut input.into()) - } -} - -impl Named for MutVecMappingMutator -where - M: Named, -{ - fn name(&self) -> &Cow<'static, str> { - &Cow::Borrowed("MutVecMappingMutator") - } -} - -/// Mapper to use when mapping a `tuple_list` of [`Mutator`]s defined for [`Vec`] for (parts of) a custom input type using a [`MutVecMappingMutator`]. -/// -/// # Example -#[cfg_attr(feature = "std", doc = " ```")] -#[cfg_attr(not(feature = "std"), doc = " ```ignore")] -/// -/// use std::vec::Vec; -/// -/// use libafl_bolts::tuples::Map; -/// use tuple_list::tuple_list; -/// -/// use libafl::{ -/// mutators::{ -/// ByteIncMutator, MutationResult, Mutator, ToMutVecMappingMutatorMapper -/// }, -/// state::NopState, -/// }; -/// -/// type CustomInput = Vec; -/// -/// let inner = tuple_list!(ByteIncMutator::new()); -/// let outer_list = inner.map(ToMutVecMappingMutatorMapper); -/// let mut outer = outer_list.0; -/// -/// let mut input: CustomInput = vec![1]; -/// let mut state: NopState = NopState::new(); -/// let res = outer.mutate(&mut state, &mut input).unwrap(); -/// assert_eq!(res, MutationResult::Mutated); -/// assert_eq!(input, vec![2]); -/// ``` -#[derive(Debug)] -pub struct ToMutVecMappingMutatorMapper; - -impl MappingFunctor for ToMutVecMappingMutatorMapper { - type Output = MutVecMappingMutator; - - fn apply(&mut self, from: M) -> Self::Output { - MutVecMappingMutator::new(from) - } -} - /// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type using a function. /// /// # Example @@ -168,42 +71,6 @@ impl Named for FunctionMappingMutator { } } -#[derive(Debug)] -pub struct WrapsReferenceFunctionMappingMutator { - mapper: F, - inner: M, - phantom: PhantomData, -} - -impl WrapsReferenceFunctionMappingMutator { - /// Creates a new [`WrapsReferenceFunctionMappingMutator`] - pub fn new(mapper: F, inner: M) -> Self { - Self { - mapper, - inner, - phantom: PhantomData, - } - } -} - -impl Mutator for WrapsReferenceFunctionMappingMutator -where - for<'a> M: Mutator, S>, - for<'a> II: WrapsReference + 'a, - F: for<'a> FnMut(&'a mut IO) -> II::Type<'a>, -{ - fn mutate(&mut self, state: &mut S, input: &mut IO) -> Result { - let mapped = &mut (self.mapper)(input); - self.inner.mutate(state, mapped) - } -} - -impl Named for WrapsReferenceFunctionMappingMutator { - fn name(&self) -> &Cow<'static, str> { - &Cow::Borrowed("WrapsReferenceFunctionMappingMutator") - } -} - /// Mapper to use when mapping a `tuple_list` of [`Mutator`]s defined for a certain input type for (parts of) a custom input type using a [`FunctionMappingMutator`]. /// /// # Example @@ -266,13 +133,49 @@ where } #[derive(Debug)] -pub struct ToWrapsReferenceFunctionMappingMutatorMapper { +pub struct MappedInputFunctionMappingMutator { + mapper: F, + inner: M, + phantom: PhantomData, +} + +impl MappedInputFunctionMappingMutator { + /// Creates a new [`MappedInputFunctionMappingMutator`] + pub fn new(mapper: F, inner: M) -> Self { + Self { + mapper, + inner, + phantom: PhantomData, + } + } +} + +impl Mutator for MappedInputFunctionMappingMutator +where + for<'a> M: Mutator, S>, + for<'a> II: MappedInput + 'a, + F: for<'a> FnMut(&'a mut IO) -> II::Type<'a>, +{ + fn mutate(&mut self, state: &mut S, input: &mut IO) -> Result { + let mapped = &mut (self.mapper)(input); + self.inner.mutate(state, mapped) + } +} + +impl Named for MappedInputFunctionMappingMutator { + fn name(&self) -> &Cow<'static, str> { + &Cow::Borrowed("MappedInputFunctionMappingMutator") + } +} + +#[derive(Debug)] +pub struct ToMappedInputFunctionMappingMutatorMapper { mapper: F, phantom: PhantomData, } -impl ToWrapsReferenceFunctionMappingMutatorMapper { - /// Creates a new [`ToWrapsReferenceFunctionMappingMutatorMapper`] +impl ToMappedInputFunctionMappingMutatorMapper { + /// Creates a new [`ToMappedInputFunctionMappingMutatorMapper`] pub fn new(mapper: F) -> Self { Self { mapper, @@ -281,14 +184,14 @@ impl ToWrapsReferenceFunctionMappingMutatorMapper { } } -impl MappingFunctor for ToWrapsReferenceFunctionMappingMutatorMapper +impl MappingFunctor for ToMappedInputFunctionMappingMutatorMapper where F: Clone, { - type Output = WrapsReferenceFunctionMappingMutator; + type Output = MappedInputFunctionMappingMutator; fn apply(&mut self, from: M) -> Self::Output { - WrapsReferenceFunctionMappingMutator::new(self.mapper.clone(), from) + MappedInputFunctionMappingMutator::new(self.mapper.clone(), from) } } From afc5259858614f999fcc9bf28ebdde4897f6dbdb Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 11 Sep 2024 09:45:17 +0000 Subject: [PATCH 23/32] adding tests and docs to mapping mutators --- libafl/src/mutators/mapping.rs | 132 +++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 32 deletions(-) diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index dead45d9dac..53a29ea9b71 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -11,29 +11,35 @@ use crate::{ Error, }; -/// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type using a function. +/// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type using a function returning a reference. /// /// # Example #[cfg_attr(feature = "std", doc = " ```")] #[cfg_attr(not(feature = "std"), doc = " ```ignore")] -/// /// use std::vec::Vec; /// /// use libafl::{ +/// inputs::MutVecInput, /// mutators::{ -/// mapping::{FunctionMappingMutator, MutVecMappingMutator}, -/// ByteIncMutator, MutationResult, Mutator, +/// ByteIncMutator, FunctionMappingMutator, MappedInputFunctionMappingMutator, +/// MutationResult, Mutator, /// }, /// state::NopState, /// }; /// /// type CustomInput = (Vec,); -/// fn extract(input: &mut CustomInput) -> &mut Vec { +/// fn extract_to_ref(input: &mut CustomInput) -> &mut Vec { /// &mut input.0 /// } /// -/// let inner = MutVecMappingMutator::new(ByteIncMutator::new()); -/// let mut outer = FunctionMappingMutator::new(extract, inner); +/// fn extract_from_ref(input: &mut Vec) -> MutVecInput<'_> { +/// input.into() +/// } +/// +/// // construct a mapper that works on &mut Vec +/// let inner: MappedInputFunctionMappingMutator<_, _, MutVecInput<'_>> = +/// MappedInputFunctionMappingMutator::new(extract_from_ref, ByteIncMutator::new()); +/// let mut outer = FunctionMappingMutator::new(extract_to_ref, inner); /// /// let mut input: CustomInput = (vec![1],); /// @@ -71,40 +77,43 @@ impl Named for FunctionMappingMutator { } } -/// Mapper to use when mapping a `tuple_list` of [`Mutator`]s defined for a certain input type for (parts of) a custom input type using a [`FunctionMappingMutator`]. +/// Mapper to use when mapping a [`tuple_list`] of [`Mutator`]s defined for a certain input type for (parts of) a custom input type using a [`FunctionMappingMutator`]. /// /// # Example #[cfg_attr(feature = "std", doc = " ```")] #[cfg_attr(not(feature = "std"), doc = " ```ignore")] -/// /// use std::vec::Vec; /// -/// use libafl_bolts::tuples::Map; -/// use tuple_list::tuple_list; -/// /// use libafl::{ /// inputs::MutVecInput, /// mutators::{ -/// mapping::{ -/// ToFunctionMappingMutatorMapper, ToMutVecMappingMutatorMapper, -/// }, -/// ByteIncMutator, MutationResult, Mutator, +/// ByteIncMutator, MappedInputFunctionMappingMutator, MutationResult, Mutator, +/// ToFunctionMappingMutatorMapper, /// }, /// state::NopState, /// }; /// +/// use libafl_bolts::tuples::{tuple_list, Map}; +/// /// type CustomInput = (Vec,); -/// fn extract(input: &mut CustomInput) -> &mut Vec { +/// fn extract_to_ref(input: &mut CustomInput) -> &mut Vec { /// &mut input.0 /// } /// -/// let inner = tuple_list!(ByteIncMutator::new()).map(ToMutVecMappingMutatorMapper); -/// let outer_list = inner.map(ToFunctionMappingMutatorMapper::new(extract)); +/// fn extract_from_ref(input: &mut Vec) -> MutVecInput<'_> { +/// input.into() +/// } +/// +/// // construct a mapper that works on &mut Vec +/// let inner: MappedInputFunctionMappingMutator<_, _, MutVecInput<'_>> = +/// MappedInputFunctionMappingMutator::new(extract_from_ref, ByteIncMutator::new()); +/// let inner_list = tuple_list!(inner); +/// let outer_list = inner_list.map(ToFunctionMappingMutatorMapper::new(extract_to_ref)); /// let mut outer = outer_list.0; /// /// let mut input: CustomInput = (vec![1],); /// -/// let mut state: NopState> = NopState::new(); +/// let mut state: NopState = NopState::new(); /// let res = outer.mutate(&mut state, &mut input).unwrap(); /// assert_eq!(res, MutationResult::Mutated); /// assert_eq!(input, (vec![2],)); @@ -132,6 +141,37 @@ where } } +/// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type using a function returning a wrapped reference (see [`MappedInput`]). +/// +/// # Example +#[cfg_attr(feature = "std", doc = " ```")] +#[cfg_attr(not(feature = "std"), doc = " ```ignore")] +/// use std::vec::Vec; +/// +/// use libafl::{ +/// inputs::MutVecInput, +/// mutators::{ +/// ByteIncMutator, MappedInputFunctionMappingMutator, MutationResult, Mutator, +/// }, +/// state::NopState, +/// }; +/// +/// type CustomInput = (Vec,); +/// fn extract(input: &mut CustomInput) -> MutVecInput<'_> { +/// (&mut input.0).into() +/// } +/// +/// let inner = ByteIncMutator::new(); +/// let mut outer: MappedInputFunctionMappingMutator<_, _, MutVecInput<'_>> = +/// MappedInputFunctionMappingMutator::new(extract, inner); +/// +/// let mut input: CustomInput = (vec![1],); +/// +/// let mut state: NopState = NopState::new(); +/// let res = outer.mutate(&mut state, &mut input).unwrap(); +/// assert_eq!(res, MutationResult::Mutated); +/// assert_eq!(input, (vec![2],)); +/// ``` #[derive(Debug)] pub struct MappedInputFunctionMappingMutator { mapper: F, @@ -168,6 +208,41 @@ impl Named for MappedInputFunctionMappingMutator { } } +/// Mapper to use when mapping a [`tuple_list`] of [`Mutator`]s defined for a certain input type for (parts of) a custom input type using a [`MappedInputFunctionMappingMutator`]. +/// +/// # Example +#[cfg_attr(feature = "std", doc = " ```")] +#[cfg_attr(not(feature = "std"), doc = " ```ignore")] +/// use std::vec::Vec; +/// +/// use libafl::{ +/// inputs::MutVecInput, +/// mutators::{ +/// ByteIncMutator, MappedInputFunctionMappingMutator, MutationResult, Mutator, +/// ToMappedInputFunctionMappingMutatorMapper, +/// }, +/// state::NopState, +/// }; +/// +/// use libafl_bolts::tuples::{tuple_list, Map}; +/// +/// type CustomInput = (Vec,); +/// fn extract(input: &mut CustomInput) -> MutVecInput<'_> { +/// (&mut input.0).into() +/// } +/// +/// let inner = tuple_list!(ByteIncMutator::new()); +/// let outer_list: (MappedInputFunctionMappingMutator<_, _, MutVecInput<'_>>, _) = +/// inner.map(ToMappedInputFunctionMappingMutatorMapper::new(extract)); +/// let mut outer = outer_list.0; +/// +/// let mut input: CustomInput = (vec![1],); +/// +/// let mut state: NopState = NopState::new(); +/// let res = outer.mutate(&mut state, &mut input).unwrap(); +/// assert_eq!(res, MutationResult::Mutated); +/// assert_eq!(input, (vec![2],)); +/// ``` #[derive(Debug)] pub struct ToMappedInputFunctionMappingMutatorMapper { mapper: F, @@ -202,14 +277,12 @@ where /// # Example #[cfg_attr(feature = "std", doc = " ```")] #[cfg_attr(not(feature = "std"), doc = " ```ignore")] -/// /// use libafl::{ /// inputs::MutVecInput, -/// mutators::{ -/// ByteIncMutator, MutationResult, Mutator, OptionMappingMutator -/// }, +/// mutators::{ByteIncMutator, MutationResult, Mutator, OptionMappingMutator}, /// state::NopState, /// }; +/// /// let inner = ByteIncMutator::new(); /// let mut outer = OptionMappingMutator::new(inner); /// @@ -263,17 +336,13 @@ where /// # Example #[cfg_attr(feature = "std", doc = " ```")] #[cfg_attr(not(feature = "std"), doc = " ```ignore")] -/// -/// use libafl_bolts::tuples::Map; -/// use tuple_list::tuple_list; -/// /// use libafl::{ /// inputs::MutVecInput, -/// mutators::{ -/// ByteIncMutator, MutationResult, Mutator, ToOptionMappingMutatorMapper -/// }, +/// mutators::{ByteIncMutator, MutationResult, Mutator, ToOptionMappingMutatorMapper}, /// state::NopState, /// }; +/// use libafl_bolts::tuples::{tuple_list, Map}; +/// /// let inner = tuple_list!(ByteIncMutator::new()); /// let outer_list = inner.map(ToOptionMappingMutatorMapper); /// let mut outer = outer_list.0; @@ -289,7 +358,6 @@ where /// let mut empty_input: Option = None; /// let res2 = outer.mutate(&mut state, &mut empty_input).unwrap(); /// assert_eq!(res2, MutationResult::Skipped); - /// ``` #[derive(Debug)] pub struct ToOptionMappingMutatorMapper; From fc1943f0f85ca9f7aee68ccef6c89d911f9e5d15 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 11 Sep 2024 11:51:40 +0000 Subject: [PATCH 24/32] reformatting comments --- libafl/src/mutators/mapping.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index 53a29ea9b71..e4e48958c9b 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -11,7 +11,9 @@ use crate::{ Error, }; -/// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type using a function returning a reference. +/// Mapping [`Mutator`] using a function returning a reference. +/// +/// Allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type. /// /// # Example #[cfg_attr(feature = "std", doc = " ```")] @@ -77,7 +79,9 @@ impl Named for FunctionMappingMutator { } } -/// Mapper to use when mapping a [`tuple_list`] of [`Mutator`]s defined for a certain input type for (parts of) a custom input type using a [`FunctionMappingMutator`]. +/// Mapper to use to map a [`tuple_list`] of [`Mutator`]s using [`ToFunctionMappingMutatorMapper`]s. +/// +/// See the explanation of [`ToFunctionMappingMutatorMapper`] for details. /// /// # Example #[cfg_attr(feature = "std", doc = " ```")] @@ -141,7 +145,9 @@ where } } -/// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type using a function returning a wrapped reference (see [`MappedInput`]). +/// Mapping [`Mutator`] using a function returning a wrapped reference (see [`MappedInput`]). +/// +/// Allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to this type. /// /// # Example #[cfg_attr(feature = "std", doc = " ```")] @@ -208,7 +214,9 @@ impl Named for MappedInputFunctionMappingMutator { } } -/// Mapper to use when mapping a [`tuple_list`] of [`Mutator`]s defined for a certain input type for (parts of) a custom input type using a [`MappedInputFunctionMappingMutator`]. +/// Mapper to use to map a [`tuple_list`] of [`Mutator`]s using [`MappedInputFunctionMappingMutator`]s. +/// +/// See the explanation of [`MappedInputFunctionMappingMutator`] for details. /// /// # Example #[cfg_attr(feature = "std", doc = " ```")] @@ -270,7 +278,9 @@ where } } -/// Mapping [`Mutator`] that allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to an [`Option`] of said type. +/// Mapping [`Mutator`] for dealing with input parts wrapped in [`Option`]. +/// +/// Allows using [`Mutator`]s for a certain type on (parts of) other input types that can be mapped to an [`Option`] of said type. /// /// Returns [`MutationResult::Skipped`] if the mapper returns [`None`]. /// @@ -331,7 +341,9 @@ where } } -/// Mapper to use when mapping a `tuple_list` of [`Mutator`]s defined for a certain input type for (parts of) a custom input type that can be mapped to an [`Option`] of said type using a [`OptionMappingMutator`]. +/// Mapper to use to map a [`tuple_list`] of [`Mutator`]s using [`OptionMappingMutator`]s. +/// +/// See the explanation of [`OptionMappingMutator`] for details. /// /// # Example #[cfg_attr(feature = "std", doc = " ```")] From 2d257b9c9e7b84601d0f9cf6107a4c3aaa56ad74 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 11 Sep 2024 12:09:47 +0000 Subject: [PATCH 25/32] fixing merging of mutators in example fuzzer --- fuzzers/baby/baby_fuzzer_custom_input/src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index 5ed0eda0aec..f464d687374 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -25,7 +25,7 @@ use libafl::{ use libafl_bolts::{ current_nanos, rands::StdRand, - tuples::{tuple_list, Append, Merge}, + tuples::{tuple_list, Merge, Prepend}, }; #[cfg(feature = "simple_interface")] @@ -201,9 +201,9 @@ pub fn main() { // Then, mutators for the optional byte array, these return MutationResult::Skipped if the part is not present .merge(optional_mapped_mutators) // A custom mutator that sets the optional byte array to None if present, and generates a random byte array of length 1 if it is not - .append(ToggleOptionalByteArrayMutator::new(1)) + .prepend(ToggleOptionalByteArrayMutator::new(1)) // Finally, a custom mutator that toggles the boolean part of the input - .append(ToggleBooleanMutator); + .prepend(ToggleBooleanMutator); // Scheduling layer for the mutations let mutator_scheduler = StdScheduledMutator::new(mutators); From 147e88ba5df3100bef82a23e5d675e295c334286 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 11 Sep 2024 12:16:41 +0000 Subject: [PATCH 26/32] formatting --- .../baby/baby_fuzzer_custom_input/src/main.rs | 24 +++++++++---------- libafl/src/inputs/bytessub.rs | 4 +--- libafl/src/mutators/mapping.rs | 3 +-- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index f464d687374..8d789be10e0 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -7,6 +7,18 @@ use std::{path::PathBuf, ptr::write}; use input::{ CustomInput, CustomInputGenerator, ToggleBooleanMutator, ToggleOptionalByteArrayMutator, }; +#[cfg(feature = "simple_interface")] +use libafl::mutators::havoc_mutations::{mapped_havoc_mutations, optional_mapped_havoc_mutations}; + +#[cfg(not(feature = "simple_interface"))] +use { + libafl::mutators::{ + havoc_mutations::{havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover}, + mapping::{ToMappedInputFunctionMappingMutatorMapper, ToOptionMappingMutatorMapper}, + }, + libafl_bolts::tuples::Map, +}; + use libafl::{ corpus::{InMemoryCorpus, OnDiskCorpus}, events::SimpleEventManager, @@ -21,24 +33,12 @@ use libafl::{ stages::mutational::StdMutationalStage, state::StdState, }; - use libafl_bolts::{ current_nanos, rands::StdRand, tuples::{tuple_list, Merge, Prepend}, }; -#[cfg(feature = "simple_interface")] -use libafl::mutators::havoc_mutations::{mapped_havoc_mutations, optional_mapped_havoc_mutations}; -#[cfg(not(feature = "simple_interface"))] -use { - libafl::mutators::{ - havoc_mutations::{havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover}, - mapping::{ToMappedInputFunctionMappingMutatorMapper, ToOptionMappingMutatorMapper}, - }, - libafl_bolts::tuples::Map, -}; - /// Coverage map with explicit assignments due to the lack of instrumentation static mut SIGNALS: [u8; 16] = [0; 16]; static mut SIGNALS_PTR: *mut u8 = unsafe { SIGNALS.as_mut_ptr() }; diff --git a/libafl/src/inputs/bytessub.rs b/libafl/src/inputs/bytessub.rs index e847c8a2f5f..53b6dea0e17 100644 --- a/libafl/src/inputs/bytessub.rs +++ b/libafl/src/inputs/bytessub.rs @@ -11,9 +11,7 @@ use libafl_bolts::{ HasLen, }; -use crate::inputs::HasMutatorBytes; - -use super::MappedInput; +use crate::inputs::{HasMutatorBytes, MappedInput}; /// The [`BytesSubInput`] makes it possible to use [`crate::mutators::Mutator`]`s` that work on /// inputs implementing the [`HasMutatorBytes`] for a sub-range of this input. diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index e4e48958c9b..5ad77d57a34 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -1,7 +1,6 @@ //! Allowing mixing and matching between [`Mutator`] and [`crate::inputs::Input`] types. -use core::marker::PhantomData; - use alloc::borrow::Cow; +use core::marker::PhantomData; use libafl_bolts::{tuples::MappingFunctor, Named}; From 4ea8b7248368a3f7d789cf4d8a8ff0767f8557a6 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 11 Sep 2024 12:21:05 +0000 Subject: [PATCH 27/32] formatting v2 --- .../baby/baby_fuzzer_custom_input/src/main.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index 8d789be10e0..0e6bba52b94 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -9,16 +9,6 @@ use input::{ }; #[cfg(feature = "simple_interface")] use libafl::mutators::havoc_mutations::{mapped_havoc_mutations, optional_mapped_havoc_mutations}; - -#[cfg(not(feature = "simple_interface"))] -use { - libafl::mutators::{ - havoc_mutations::{havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover}, - mapping::{ToMappedInputFunctionMappingMutatorMapper, ToOptionMappingMutatorMapper}, - }, - libafl_bolts::tuples::Map, -}; - use libafl::{ corpus::{InMemoryCorpus, OnDiskCorpus}, events::SimpleEventManager, @@ -38,6 +28,14 @@ use libafl_bolts::{ rands::StdRand, tuples::{tuple_list, Merge, Prepend}, }; +#[cfg(not(feature = "simple_interface"))] +use { + libafl::mutators::{ + havoc_mutations::{havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover}, + mapping::{ToMappedInputFunctionMappingMutatorMapper, ToOptionMappingMutatorMapper}, + }, + libafl_bolts::tuples::Map, +}; /// Coverage map with explicit assignments due to the lack of instrumentation static mut SIGNALS: [u8; 16] = [0; 16]; From b6e2af101d9a62c3f8a79af32246ea03dec0284a Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 11 Sep 2024 14:30:59 +0000 Subject: [PATCH 28/32] cleanup according to PR comments --- .../baby_fuzzer_custom_input/src/input.rs | 38 +++++++++---------- libafl/src/mutators/havoc_mutations.rs | 6 +-- libafl/src/mutators/mutations.rs | 24 +++++------- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs index 01d5dcf1640..2b2ddd465d0 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs @@ -6,8 +6,9 @@ use std::{ use libafl::{ corpus::CorpusId, generators::Generator, - inputs::{Input, MutVecInput}, + inputs::{BytesInput, HasTargetBytes, Input, MutVecInput}, mutators::{MutationResult, Mutator}, + prelude::RandBytesGenerator, state::HasRand, Error, SerdeAny, }; @@ -75,11 +76,13 @@ where S: HasRand, { fn generate(&mut self, state: &mut S) -> Result { - let byte_array = generate_bytes(self.max_len, state); + let mut generator = RandBytesGenerator::new(self.max_len); + + let byte_array = generator.generate(state).unwrap().target_bytes().into(); let optional_byte_array = state .rand_mut() .coinflip(0.5) - .then(|| generate_bytes(self.max_len, state)); + .then(|| generator.generate(state).unwrap().target_bytes().into()); let boolean = state.rand_mut().coinflip(0.5); Ok(CustomInput { @@ -90,41 +93,38 @@ where } } -/// Generate a [`Vec`] of a length between 1 (incl.) and `length` (incl.) filled with random bytes -fn generate_bytes(length: usize, state: &mut S) -> Vec { - let rand = state.rand_mut(); - let len = rand.between(1, length); - let mut vec = Vec::new(); - vec.resize_with(len, || rand.next() as u8); - vec -} - /// [`Mutator`] that toggles the optional byte array of a [`CustomInput`], i.e. sets it to [`None`] if it is not, and to a random byte array if it is [`None`] -pub struct ToggleOptionalByteArrayMutator { - length: usize, +pub struct ToggleOptionalByteArrayMutator { + generator: G, } -impl ToggleOptionalByteArrayMutator { +impl ToggleOptionalByteArrayMutator> +where + S: HasRand, +{ /// Creates a new [`ToggleOptionalByteArrayMutator`] pub fn new(length: usize) -> Self { - Self { length } + Self { + generator: RandBytesGenerator::new(length), + } } } -impl Mutator for ToggleOptionalByteArrayMutator +impl Mutator for ToggleOptionalByteArrayMutator where S: HasRand, + G: Generator, { fn mutate(&mut self, state: &mut S, input: &mut CustomInput) -> Result { input.optional_byte_array = match input.optional_byte_array { - None => Some(generate_bytes(self.length, state)), + None => Some(self.generator.generate(state)?.target_bytes().into()), Some(_) => None, }; Ok(MutationResult::Mutated) } } -impl Named for ToggleOptionalByteArrayMutator { +impl Named for ToggleOptionalByteArrayMutator { fn name(&self) -> &Cow<'static, str> { &Cow::Borrowed("ToggleOptionalByteArrayMutator") } diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index f9740f385db..d9cad66f426 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -201,10 +201,10 @@ pub fn havoc_crossover() -> HavocCrossoverType { } /// Get the mutations that compose the Havoc mutator's crossover strategy with custom corpus extraction logic -pub fn havoc_crossover_with_corpus_mapper(corpus_mapper: &F) -> MappedHavocCrossoverType<'_, F> { +pub fn havoc_crossover_with_corpus_mapper(input_mapper: &F) -> MappedHavocCrossoverType<'_, F> { tuple_list!( - MappedCrossoverInsertMutator::new(corpus_mapper), - MappedCrossoverReplaceMutator::new(corpus_mapper), + MappedCrossoverInsertMutator::new(input_mapper), + MappedCrossoverReplaceMutator::new(input_mapper), ) } diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index b3e7f45d993..2ec40d359bc 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -1197,7 +1197,7 @@ impl CrossoverReplaceMutator { /// Crossover insert mutation for inputs mapped to a bytes vector #[derive(Debug)] pub struct MappedCrossoverInsertMutator<'a, F> { - input_from_corpus_mapper: &'a F, + input_mapper: &'a F, } impl<'a, S, F, I> Mutator for MappedCrossoverInsertMutator<'a, F> @@ -1224,7 +1224,7 @@ where let other_size = { let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); let other_input = other_testcase.load_input(state.corpus())?; - (self.input_from_corpus_mapper)(other_input).map_or(0, <[u8]>::len) + (self.input_mapper)(other_input).map_or(0, <[u8]>::len) }; if other_size < 2 { @@ -1237,7 +1237,7 @@ where let other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); // No need to load the input again, it'll still be cached. let other_input = &mut other_testcase.input().as_ref().unwrap(); - let wrapped_mapped_other_input = (self.input_from_corpus_mapper)(other_input); + let wrapped_mapped_other_input = (self.input_mapper)(other_input); if wrapped_mapped_other_input.is_none() { return Ok(MutationResult::Skipped); } @@ -1262,25 +1262,21 @@ impl<'a, F> Named for MappedCrossoverInsertMutator<'a, F> { impl<'a, F> MappedCrossoverInsertMutator<'a, F> { /// Creates a new [`MappedCrossoverInsertMutator`]. - pub fn new(input_from_corpus_mapper: &'a F) -> Self { - Self { - input_from_corpus_mapper, - } + pub fn new(input_mapper: &'a F) -> Self { + Self { input_mapper } } } /// Crossover replace mutation for inputs mapped to a bytes vector #[derive(Debug)] pub struct MappedCrossoverReplaceMutator<'a, F> { - input_from_corpus_mapper: &'a F, + input_mapper: &'a F, } impl<'a, F> MappedCrossoverReplaceMutator<'a, F> { /// Creates a new [`MappedCrossoverReplaceMutator`]. - pub fn new(input_from_corpus_mapper: &'a F) -> Self { - Self { - input_from_corpus_mapper, - } + pub fn new(input_mapper: &'a F) -> Self { + Self { input_mapper } } } @@ -1307,7 +1303,7 @@ where let other_size = { let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); let other_input = other_testcase.load_input(state.corpus())?; - (self.input_from_corpus_mapper)(other_input).map_or(0, <[u8]>::len) + (self.input_mapper)(other_input).map_or(0, <[u8]>::len) }; if other_size < 2 { @@ -1320,7 +1316,7 @@ where let other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); // No need to load the input again, it'll still be cached. let other_input = &mut other_testcase.input().as_ref().unwrap(); - let wrapped_mapped_other_input = (self.input_from_corpus_mapper)(other_input); + let wrapped_mapped_other_input = (self.input_mapper)(other_input); if wrapped_mapped_other_input.is_none() { return Ok(MutationResult::Skipped); } From 61f3822bc33f5c0f8f2431a7c4ecca3a4908c651 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 18 Sep 2024 13:05:02 +0000 Subject: [PATCH 29/32] adding type constraint to MappedInput helper functions to remove the need to specify types --- .../baby/baby_fuzzer_custom_input/src/main.rs | 51 ++++++++----------- libafl/src/mutators/havoc_mutations.rs | 8 +-- libafl/src/mutators/mapping.rs | 7 ++- 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index 0e6bba52b94..29d83152882 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -15,9 +15,8 @@ use libafl::{ executors::{inprocess::InProcessExecutor, ExitKind}, feedbacks::{CrashFeedback, MaxMapFeedback}, fuzzer::{Fuzzer, StdFuzzer}, - inputs::MutVecInput, monitors::SimpleMonitor, - mutators::{mapping::MappedInputFunctionMappingMutator, scheduled::StdScheduledMutator}, + mutators::scheduled::StdScheduledMutator, observers::StdMapObserver, schedulers::QueueScheduler, stages::mutational::StdMutationalStage, @@ -30,9 +29,12 @@ use libafl_bolts::{ }; #[cfg(not(feature = "simple_interface"))] use { - libafl::mutators::{ - havoc_mutations::{havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover}, - mapping::{ToMappedInputFunctionMappingMutatorMapper, ToOptionMappingMutatorMapper}, + libafl::{ + inputs::MutVecInput, + mutators::{ + havoc_mutations::{havoc_crossover_with_corpus_mapper, havoc_mutations_no_crossover}, + mapping::{ToMappedInputFunctionMappingMutatorMapper, ToOptionMappingMutatorMapper}, + }, }, libafl_bolts::tuples::Map, }; @@ -138,21 +140,13 @@ pub fn main() { #[cfg(feature = "simple_interface")] let (mapped_mutators, optional_mapped_mutators) = { // Creating mutators that will operate on input.byte_array - // For now, due to a limitation in lifetime management (see the MappedInput trait), - // the types have to be partially specified - let mapped_mutators: (MappedInputFunctionMappingMutator<_, _, MutVecInput<'_>>, _) = - mapped_havoc_mutations( - CustomInput::byte_array_mut, - &CustomInput::byte_array_optional, - ); + let mapped_mutators = mapped_havoc_mutations( + CustomInput::byte_array_mut, + &CustomInput::byte_array_optional, + ); // Creating mutators that will operate on input.optional_byte_array - // For now, due to a limitation in lifetime management (see the MappedInput trait), - // the types have to be partially specified - let optional_mapped_mutators: ( - MappedInputFunctionMappingMutator<_, _, Option>>, - _, - ) = optional_mapped_havoc_mutations( + let optional_mapped_mutators = optional_mapped_havoc_mutations( CustomInput::optional_byte_array_mut, &CustomInput::optional_byte_array_optional, ); @@ -164,22 +158,19 @@ pub fn main() { // Creating mutators that will operate on input.byte_array // For now, due to a limitation in lifetime management (see the MappedInput trait), // the types have to be partially specified - let mapped_mutators: (MappedInputFunctionMappingMutator<_, _, MutVecInput<'_>>, _) = - havoc_mutations_no_crossover() - .merge(havoc_crossover_with_corpus_mapper( - &CustomInput::byte_array_optional, - )) - .map(ToMappedInputFunctionMappingMutatorMapper::new( - CustomInput::byte_array_mut, - )); + let mapped_mutators = havoc_mutations_no_crossover() + .merge(havoc_crossover_with_corpus_mapper( + &CustomInput::byte_array_optional, + )) + .map(ToMappedInputFunctionMappingMutatorMapper::< + _, + MutVecInput<'_>, + >::new(CustomInput::byte_array_mut)); // Creating mutators that will operate on input.optional_byte_array // For now, due to a limitation in lifetime management (see the MappedInput trait), // the types have to be partially specified - let optional_mapped_mutators: ( - MappedInputFunctionMappingMutator<_, _, Option>>, - _, - ) = havoc_mutations_no_crossover() + let optional_mapped_mutators = havoc_mutations_no_crossover() .merge(havoc_crossover_with_corpus_mapper( &CustomInput::optional_byte_array_optional, )) diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index d9cad66f426..d08c3d761b1 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -218,12 +218,12 @@ pub fn havoc_mutations() -> HavocMutationsType { /// /// Check the example fuzzer for details on how to use this. #[must_use] -pub fn mapped_havoc_mutations( +pub fn mapped_havoc_mutations( current_input_mapper: F1, input_from_corpus_mapper: &F2, ) -> MappedHavocMutationsType<'_, F1, F2, II> where - F1: Clone, + F1: Clone + FnMut(IO) -> II, { havoc_mutations_no_crossover() .merge(havoc_crossover_with_corpus_mapper(input_from_corpus_mapper)) @@ -236,12 +236,12 @@ where /// /// Check the example fuzzer for details on how to use this. #[must_use] -pub fn optional_mapped_havoc_mutations( +pub fn optional_mapped_havoc_mutations( current_input_mapper: F1, input_from_corpus_mapper: &F2, ) -> OptionMappedHavocMutationsType<'_, F1, F2, II> where - F1: Clone, + F1: Clone + FnMut(IO) -> II, { havoc_mutations_no_crossover() .merge(havoc_crossover_with_corpus_mapper(input_from_corpus_mapper)) diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index 5ad77d57a34..fd6c7e79c5a 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -199,7 +199,7 @@ impl Mutator for MappedInputFunctionMappingMutator M: Mutator, S>, for<'a> II: MappedInput + 'a, - F: for<'a> FnMut(&'a mut IO) -> II::Type<'a>, + for<'a> F: FnMut(&'a mut IO) -> II::Type<'a>, { fn mutate(&mut self, state: &mut S, input: &mut IO) -> Result { let mapped = &mut (self.mapper)(input); @@ -258,7 +258,10 @@ pub struct ToMappedInputFunctionMappingMutatorMapper { impl ToMappedInputFunctionMappingMutatorMapper { /// Creates a new [`ToMappedInputFunctionMappingMutatorMapper`] - pub fn new(mapper: F) -> Self { + pub fn new(mapper: F) -> Self + where + F: FnMut(IO) -> II, + { Self { mapper, phantom: PhantomData, From 4411d6b1f4bc99bf5251df9884192f1e831a900f Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 18 Sep 2024 19:48:44 +0000 Subject: [PATCH 30/32] matching functions passed to mapped_havoc_mutations --- .../baby_fuzzer_custom_input/src/input.rs | 6 +- .../baby/baby_fuzzer_custom_input/src/main.rs | 4 +- libafl/src/mutators/havoc_mutations.rs | 62 +++++++---- libafl/src/mutators/mutations.rs | 100 +++++++++++++----- 4 files changed, 121 insertions(+), 51 deletions(-) diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs index 2b2ddd465d0..d6ffe0f4774 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/input.rs @@ -44,8 +44,8 @@ impl CustomInput { } /// Returns an immutable reference to the byte array wrapped in [`Some`] - pub fn byte_array_optional(&self) -> Option<&[u8]> { - Some(&self.byte_array) + pub fn byte_array_optional<'a>(&'a self) -> &'a [u8] { + &self.byte_array } /// Returns a mutable reference to the optional byte array @@ -54,7 +54,7 @@ impl CustomInput { } /// Returns an immutable reference to the optional byte array - pub fn optional_byte_array_optional(&self) -> Option<&[u8]> { + pub fn optional_byte_array_optional<'a>(&'a self) -> Option<&'a [u8]> { self.optional_byte_array.as_deref() } } diff --git a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs index 29d83152882..7e3c83dceab 100644 --- a/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs +++ b/fuzzers/baby/baby_fuzzer_custom_input/src/main.rs @@ -142,13 +142,13 @@ pub fn main() { // Creating mutators that will operate on input.byte_array let mapped_mutators = mapped_havoc_mutations( CustomInput::byte_array_mut, - &CustomInput::byte_array_optional, + CustomInput::byte_array_optional, ); // Creating mutators that will operate on input.optional_byte_array let optional_mapped_mutators = optional_mapped_havoc_mutations( CustomInput::optional_byte_array_mut, - &CustomInput::optional_byte_array_optional, + CustomInput::optional_byte_array_optional, ); (mapped_mutators, optional_mapped_mutators) }; diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index d08c3d761b1..999794c9c90 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -53,9 +53,9 @@ pub type HavocCrossoverType = tuple_list_type!(CrossoverInsertMutator, CrossoverReplaceMutator); /// Tuple type of the mutations that compose the Havoc mutator's crossover mutations for mapped input types -pub type MappedHavocCrossoverType<'a, F> = tuple_list_type!( - MappedCrossoverInsertMutator<'a, F>, - MappedCrossoverReplaceMutator<'a, F> +pub type MappedHavocCrossoverType = tuple_list_type!( + MappedCrossoverInsertMutator, + MappedCrossoverReplaceMutator, ); /// Tuple type of the mutations that compose the Havoc mutator @@ -90,7 +90,7 @@ pub type HavocMutationsType = tuple_list_type!( ); /// Tuple type of the mutations that compose the Havoc mutator for mapped input types -pub type MappedHavocMutationsType<'a, F1, F2, II> = tuple_list_type!( +pub type MappedHavocMutationsType = tuple_list_type!( MappedInputFunctionMappingMutator, MappedInputFunctionMappingMutator, MappedInputFunctionMappingMutator, @@ -116,12 +116,12 @@ pub type MappedHavocMutationsType<'a, F1, F2, II> = tuple_list_type!( MappedInputFunctionMappingMutator, MappedInputFunctionMappingMutator, MappedInputFunctionMappingMutator, - MappedInputFunctionMappingMutator, F1, II>, - MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, + MappedInputFunctionMappingMutator, F1, II>, ); /// Tuple type of the mutations that compose the Havoc mutator for mapped input types, for optional byte array input parts -pub type OptionMappedHavocMutationsType<'a, F1, F2, II> = tuple_list_type!( +pub type OptionMappedHavocMutationsType = tuple_list_type!( MappedInputFunctionMappingMutator, F1, II>, MappedInputFunctionMappingMutator, F1, II>, MappedInputFunctionMappingMutator, F1, II>, @@ -148,12 +148,12 @@ pub type OptionMappedHavocMutationsType<'a, F1, F2, II> = tuple_list_type!( MappedInputFunctionMappingMutator, F1, II>, MappedInputFunctionMappingMutator, F1, II>, MappedInputFunctionMappingMutator< - OptionMappingMutator>, + OptionMappingMutator>, F1, II, >, MappedInputFunctionMappingMutator< - OptionMappingMutator>, + OptionMappingMutator>, F1, II, >, @@ -201,10 +201,26 @@ pub fn havoc_crossover() -> HavocCrossoverType { } /// Get the mutations that compose the Havoc mutator's crossover strategy with custom corpus extraction logic -pub fn havoc_crossover_with_corpus_mapper(input_mapper: &F) -> MappedHavocCrossoverType<'_, F> { +pub fn havoc_crossover_with_corpus_mapper(input_mapper: F) -> MappedHavocCrossoverType +where + F: Clone, +{ tuple_list!( - MappedCrossoverInsertMutator::new(input_mapper), - MappedCrossoverReplaceMutator::new(input_mapper), + MappedCrossoverInsertMutator::new(input_mapper.clone()), + MappedCrossoverReplaceMutator::new(input_mapper.clone()), + ) +} + +/// Get the mutations that compose the Havoc mutator's crossover strategy with custom corpus extraction logic +pub fn havoc_crossover_with_corpus_mapper_optional( + input_mapper: F, +) -> MappedHavocCrossoverType +where + F: Clone, +{ + tuple_list!( + MappedCrossoverInsertMutator::new(input_mapper.clone()), + MappedCrossoverReplaceMutator::new(input_mapper.clone()), ) } @@ -218,12 +234,13 @@ pub fn havoc_mutations() -> HavocMutationsType { /// /// Check the example fuzzer for details on how to use this. #[must_use] -pub fn mapped_havoc_mutations( +pub fn mapped_havoc_mutations( current_input_mapper: F1, - input_from_corpus_mapper: &F2, -) -> MappedHavocMutationsType<'_, F1, F2, II> + input_from_corpus_mapper: F2, +) -> MappedHavocMutationsType where - F1: Clone + FnMut(IO) -> II, + F1: Clone + FnMut(IO1) -> II, + F2: Clone + Fn(IO2) -> O, { havoc_mutations_no_crossover() .merge(havoc_crossover_with_corpus_mapper(input_from_corpus_mapper)) @@ -236,15 +253,18 @@ where /// /// Check the example fuzzer for details on how to use this. #[must_use] -pub fn optional_mapped_havoc_mutations( +pub fn optional_mapped_havoc_mutations( current_input_mapper: F1, - input_from_corpus_mapper: &F2, -) -> OptionMappedHavocMutationsType<'_, F1, F2, II> + input_from_corpus_mapper: F2, +) -> OptionMappedHavocMutationsType where - F1: Clone + FnMut(IO) -> II, + F1: Clone + FnMut(IO1) -> II, + F2: Clone + Fn(IO2) -> O, { havoc_mutations_no_crossover() - .merge(havoc_crossover_with_corpus_mapper(input_from_corpus_mapper)) + .merge(havoc_crossover_with_corpus_mapper_optional( + input_from_corpus_mapper, + )) .map(ToOptionMappingMutatorMapper) .map(ToMappedInputFunctionMappingMutatorMapper::new( current_input_mapper, diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index 2ec40d359bc..dd266f4dc78 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -1194,17 +1194,66 @@ impl CrossoverReplaceMutator { } } } + +trait IntoOptionBytes { + type Type<'b> + where + Self: 'b; + + fn into_option_bytes<'a>(self) -> Option<&'a [u8]> + where + Self: 'a, + Self::Type<'a>:; +} + +impl<'a> IntoOptionBytes for &'a [u8] { + type Type<'b> = &'b [u8] where Self: 'b; + + fn into_option_bytes<'b>(self) -> Option<&'b [u8]> + where + Self: 'b, + Self::Type<'b>:, + { + Some(self) + } +} + +impl<'a> IntoOptionBytes for Option<&'a [u8]> { + type Type<'b> = Option<&'b [u8]> where Self: 'b; + + fn into_option_bytes<'b>(self) -> Option<&'b [u8]> + where + Self: 'b, + Self::Type<'b>:, + { + self + } +} + /// Crossover insert mutation for inputs mapped to a bytes vector #[derive(Debug)] -pub struct MappedCrossoverInsertMutator<'a, F> { - input_mapper: &'a F, +pub struct MappedCrossoverInsertMutator { + input_mapper: F, + phantom: PhantomData, } -impl<'a, S, F, I> Mutator for MappedCrossoverInsertMutator<'a, F> +impl MappedCrossoverInsertMutator { + /// Creates a new [`MappedCrossoverInsertMutator`] + pub fn new(input_mapper: F) -> Self { + Self { + input_mapper, + phantom: PhantomData, + } + } +} + +impl Mutator for MappedCrossoverInsertMutator where S: HasCorpus + HasMaxSize + HasRand + UsesInput, I: HasMutatorBytes, - F: for<'b> Fn(&'b S::Input) -> Option<&'b [u8]>, + O: IntoOptionBytes, + for<'a> O::Type<'a>: IntoOptionBytes, + for<'a> F: Fn(&'a S::Input) -> ::Type<'a>, { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { let size = input.bytes().len(); @@ -1224,7 +1273,8 @@ where let other_size = { let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); let other_input = other_testcase.load_input(state.corpus())?; - (self.input_mapper)(other_input).map_or(0, <[u8]>::len) + let input_mapped = (self.input_mapper)(other_input).into_option_bytes(); + input_mapped.map_or(0, <[u8]>::len) }; if other_size < 2 { @@ -1237,7 +1287,7 @@ where let other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); // No need to load the input again, it'll still be cached. let other_input = &mut other_testcase.input().as_ref().unwrap(); - let wrapped_mapped_other_input = (self.input_mapper)(other_input); + let wrapped_mapped_other_input = (self.input_mapper)(other_input).into_option_bytes(); if wrapped_mapped_other_input.is_none() { return Ok(MutationResult::Skipped); } @@ -1253,38 +1303,37 @@ where } } -impl<'a, F> Named for MappedCrossoverInsertMutator<'a, F> { +impl Named for MappedCrossoverInsertMutator { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("MappedCrossoverInsertMutator"); &NAME } } -impl<'a, F> MappedCrossoverInsertMutator<'a, F> { - /// Creates a new [`MappedCrossoverInsertMutator`]. - pub fn new(input_mapper: &'a F) -> Self { - Self { input_mapper } - } -} - /// Crossover replace mutation for inputs mapped to a bytes vector #[derive(Debug)] -pub struct MappedCrossoverReplaceMutator<'a, F> { - input_mapper: &'a F, +pub struct MappedCrossoverReplaceMutator { + input_mapper: F, + phantom: PhantomData, } -impl<'a, F> MappedCrossoverReplaceMutator<'a, F> { - /// Creates a new [`MappedCrossoverReplaceMutator`]. - pub fn new(input_mapper: &'a F) -> Self { - Self { input_mapper } +impl MappedCrossoverReplaceMutator { + /// Creates a new [`MappedCrossoverReplaceMutator`] + pub fn new(input_mapper: F) -> Self { + Self { + input_mapper, + phantom: PhantomData, + } } } -impl<'a, S, I, F> Mutator for MappedCrossoverReplaceMutator<'a, F> +impl Mutator for MappedCrossoverReplaceMutator where S: HasCorpus + HasMaxSize + HasRand + UsesInput, I: HasMutatorBytes, - F: for<'b> Fn(&'b S::Input) -> Option<&'b [u8]>, + O: IntoOptionBytes, + for<'a> O::Type<'a>: IntoOptionBytes, + for<'a> F: Fn(&'a S::Input) -> ::Type<'a>, { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { let size = input.bytes().len(); @@ -1303,7 +1352,8 @@ where let other_size = { let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); let other_input = other_testcase.load_input(state.corpus())?; - (self.input_mapper)(other_input).map_or(0, <[u8]>::len) + let input_mapped = (self.input_mapper)(other_input).into_option_bytes(); + input_mapped.map_or(0, <[u8]>::len) }; if other_size < 2 { @@ -1316,7 +1366,7 @@ where let other_testcase = state.corpus().get_from_all(id)?.borrow_mut(); // No need to load the input again, it'll still be cached. let other_input = &mut other_testcase.input().as_ref().unwrap(); - let wrapped_mapped_other_input = (self.input_mapper)(other_input); + let wrapped_mapped_other_input = (self.input_mapper)(other_input).into_option_bytes(); if wrapped_mapped_other_input.is_none() { return Ok(MutationResult::Skipped); } @@ -1331,7 +1381,7 @@ where } } -impl<'a, F> Named for MappedCrossoverReplaceMutator<'a, F> { +impl Named for MappedCrossoverReplaceMutator { fn name(&self) -> &Cow<'static, str> { static NAME: Cow<'static, str> = Cow::Borrowed("MappedCrossoverReplaceMutator"); &NAME From 745945e6813ea6e3e71d8f3aa513b9dc200f2f70 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 18 Sep 2024 19:52:03 +0000 Subject: [PATCH 31/32] removing unnecessary constraints --- libafl/src/mutators/mutations.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index dd266f4dc78..93e9d09920b 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -1196,35 +1196,30 @@ impl CrossoverReplaceMutator { } trait IntoOptionBytes { - type Type<'b> - where - Self: 'b; + type Type<'b>; fn into_option_bytes<'a>(self) -> Option<&'a [u8]> where - Self: 'a, - Self::Type<'a>:; + Self: 'a; } impl<'a> IntoOptionBytes for &'a [u8] { - type Type<'b> = &'b [u8] where Self: 'b; + type Type<'b> = &'b [u8]; fn into_option_bytes<'b>(self) -> Option<&'b [u8]> where Self: 'b, - Self::Type<'b>:, { Some(self) } } impl<'a> IntoOptionBytes for Option<&'a [u8]> { - type Type<'b> = Option<&'b [u8]> where Self: 'b; + type Type<'b> = Option<&'b [u8]>; fn into_option_bytes<'b>(self) -> Option<&'b [u8]> where Self: 'b, - Self::Type<'b>:, { self } @@ -1251,7 +1246,7 @@ impl Mutator for MappedCrossoverInsertMutator where S: HasCorpus + HasMaxSize + HasRand + UsesInput, I: HasMutatorBytes, - O: IntoOptionBytes, + for<'a> O: IntoOptionBytes, for<'a> O::Type<'a>: IntoOptionBytes, for<'a> F: Fn(&'a S::Input) -> ::Type<'a>, { From 41de711692963dd8e5cf6b86882aa20379143115 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Wed, 18 Sep 2024 20:00:18 +0000 Subject: [PATCH 32/32] mapping mutators now contain the name of their inner mutator --- libafl/src/mutators/mapping.rs | 47 +++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index fd6c7e79c5a..27dc7990d58 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -53,12 +53,21 @@ use crate::{ pub struct FunctionMappingMutator { mapper: F, inner: M, + name: Cow<'static, str>, } impl FunctionMappingMutator { /// Creates a new [`FunctionMappingMutator`] - pub fn new(mapper: F, inner: M) -> Self { - Self { mapper, inner } + pub fn new(mapper: F, inner: M) -> Self + where + M: Named, + { + let name = Cow::Owned(format!("FunctionMappingMutator<{}>", inner.name())); + Self { + mapper, + inner, + name, + } } } @@ -74,7 +83,7 @@ where impl Named for FunctionMappingMutator { fn name(&self) -> &Cow<'static, str> { - &Cow::Borrowed("FunctionMappingMutator") + &self.name } } @@ -136,6 +145,7 @@ impl ToFunctionMappingMutatorMapper { impl MappingFunctor for ToFunctionMappingMutatorMapper where F: Clone, + M: Named, { type Output = FunctionMappingMutator; @@ -181,15 +191,25 @@ where pub struct MappedInputFunctionMappingMutator { mapper: F, inner: M, + name: Cow<'static, str>, phantom: PhantomData, } impl MappedInputFunctionMappingMutator { /// Creates a new [`MappedInputFunctionMappingMutator`] - pub fn new(mapper: F, inner: M) -> Self { + pub fn new(mapper: F, inner: M) -> Self + where + M: Named, + { + let name = Cow::Owned(format!( + "MappedInputFunctionMappingMutator<{}>", + inner.name() + )); + Self { mapper, inner, + name, phantom: PhantomData, } } @@ -209,7 +229,7 @@ where impl Named for MappedInputFunctionMappingMutator { fn name(&self) -> &Cow<'static, str> { - &Cow::Borrowed("MappedInputFunctionMappingMutator") + &self.name } } @@ -272,6 +292,7 @@ impl ToMappedInputFunctionMappingMutatorMapper { impl MappingFunctor for ToMappedInputFunctionMappingMutatorMapper where F: Clone, + M: Named, { type Output = MappedInputFunctionMappingMutator; @@ -313,12 +334,17 @@ where #[derive(Debug)] pub struct OptionMappingMutator { inner: M, + name: Cow<'static, str>, } impl OptionMappingMutator { /// Creates a new [`OptionMappingMutator`] - pub fn new(inner: M) -> Self { - Self { inner } + pub fn new(inner: M) -> Self + where + M: Named, + { + let name = Cow::Owned(format!("OptionMappingMutator<{}>", inner.name())); + Self { inner, name } } } @@ -339,7 +365,7 @@ where M: Named, { fn name(&self) -> &Cow<'static, str> { - &Cow::Borrowed("OptionMappingMutator") + &self.name } } @@ -376,7 +402,10 @@ where #[derive(Debug)] pub struct ToOptionMappingMutatorMapper; -impl MappingFunctor for ToOptionMappingMutatorMapper { +impl MappingFunctor for ToOptionMappingMutatorMapper +where + M: Named, +{ type Output = OptionMappingMutator; fn apply(&mut self, from: M) -> Self::Output {