Named Mutators and MultiMutator API change (#1387)

* Mutators need names (alternative to #1379)

* Signature of MultiMutator shouldn't be the same as the normal mutator

* Named for python, remove mutator for multi_mutator

* fmt

* clippy edition warning

* clippy

* mac_count doc fix, return cleanup
This commit is contained in:
Dominik Maier 2023-08-01 16:58:40 +02:00 committed by GitHub
parent 90e9f3c786
commit 006dcac00c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 166 additions and 67 deletions

View File

@ -1,4 +1,5 @@
[workspace] [workspace]
resolver = "2"
members = [ members = [
"libafl", "libafl",
"libafl_derive", "libafl_derive",

View File

@ -26,7 +26,7 @@ use libafl::{
monitors::SimpleMonitor, monitors::SimpleMonitor,
mutators::{ mutators::{
scheduled::havoc_mutations, token_mutations::AFLppRedQueen, tokens_mutations, scheduled::havoc_mutations, token_mutations::AFLppRedQueen, tokens_mutations,
MutationResult, StdMOptMutator, Tokens, StdMOptMutator, Tokens,
}, },
observers::{ observers::{
AFLppCmpMap, AFLppForkserverCmpObserver, HitcountsMapObserver, StdMapObserver, TimeObserver, AFLppCmpMap, AFLppForkserverCmpObserver, HitcountsMapObserver, StdMapObserver, TimeObserver,
@ -35,7 +35,7 @@ use libafl::{
powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler,
}, },
stages::{ stages::{
calibrate::CalibrationStage, mutational::MultipleMutationalStage, calibrate::CalibrationStage, mutational::MultiMutationalStage,
power::StdPowerMutationalStage, tracing::AFLppCmplogTracingStage, ColorizationStage, power::StdPowerMutationalStage, tracing::AFLppCmplogTracingStage, ColorizationStage,
IfStage, IfStage,
}, },
@ -368,7 +368,7 @@ fn fuzz(
let tracing = AFLppCmplogTracingStage::with_cmplog_observer_name(cmplog_executor, "cmplog"); let tracing = AFLppCmplogTracingStage::with_cmplog_observer_name(cmplog_executor, "cmplog");
// Setup a randomic Input2State stage // Setup a randomic Input2State stage
let rq = MultipleMutationalStage::new(AFLppRedQueen::with_cmplog_options(true, true)); let rq = MultiMutationalStage::new(AFLppRedQueen::with_cmplog_options(true, true));
let cb = |_fuzzer: &mut _, let cb = |_fuzzer: &mut _,
_executor: &mut _, _executor: &mut _,

View File

@ -80,7 +80,7 @@ pub enum MutationResult {
/// A mutator takes input, and mutates it. /// A mutator takes input, and mutates it.
/// Simple as that. /// Simple as that.
pub trait Mutator<I, S> { pub trait Mutator<I, S>: Named {
/// Mutate a given input /// Mutate a given input
fn mutate( fn mutate(
&mut self, &mut self,
@ -90,6 +90,7 @@ pub trait Mutator<I, S> {
) -> Result<MutationResult, Error>; ) -> Result<MutationResult, Error>;
/// Post-process given the outcome of the execution /// Post-process given the outcome of the execution
#[inline]
fn post_exec( fn post_exec(
&mut self, &mut self,
_state: &mut S, _state: &mut S,
@ -102,18 +103,20 @@ pub trait Mutator<I, S> {
/// A mutator that takes input, and returns a vector of mutated inputs. /// A mutator that takes input, and returns a vector of mutated inputs.
/// Simple as that. /// Simple as that.
pub trait MultipleMutator<I, S> { pub trait MultiMutator<I, S>: Named {
/// Mutate a given input /// Mutate a given input up to `max_count` times,
fn mutate( /// or as many times as appropriate, if no `max_count` is given
fn multi_mutate(
&mut self, &mut self,
state: &mut S, state: &mut S,
input: &I, input: &I,
vec: &mut Vec<I>,
stage_idx: i32, stage_idx: i32,
) -> Result<MutationResult, Error>; max_count: Option<usize>,
) -> Result<Vec<I>, Error>;
/// Post-process given the outcome of the execution /// Post-process given the outcome of the execution
fn post_exec( #[inline]
fn multi_post_exec(
&mut self, &mut self,
_state: &mut S, _state: &mut S,
_stage_idx: i32, _stage_idx: i32,
@ -158,9 +161,13 @@ pub trait MutatorsTuple<I, S>: HasConstLen {
stage_idx: i32, stage_idx: i32,
corpus_idx: Option<CorpusId>, corpus_idx: Option<CorpusId>,
) -> Result<(), Error>; ) -> Result<(), Error>;
/// Gets all names of the wrapped [`Mutator`]`s`.
fn names(&self) -> Vec<&str>;
} }
impl<I, S> MutatorsTuple<I, S> for () { impl<I, S> MutatorsTuple<I, S> for () {
#[inline]
fn mutate_all( fn mutate_all(
&mut self, &mut self,
_state: &mut S, _state: &mut S,
@ -170,6 +177,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
Ok(MutationResult::Skipped) Ok(MutationResult::Skipped)
} }
#[inline]
fn post_exec_all( fn post_exec_all(
&mut self, &mut self,
_state: &mut S, _state: &mut S,
@ -179,6 +187,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
Ok(()) Ok(())
} }
#[inline]
fn get_and_mutate( fn get_and_mutate(
&mut self, &mut self,
_index: MutationId, _index: MutationId,
@ -189,6 +198,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
Ok(MutationResult::Skipped) Ok(MutationResult::Skipped)
} }
#[inline]
fn get_and_post_exec( fn get_and_post_exec(
&mut self, &mut self,
_index: usize, _index: usize,
@ -198,11 +208,16 @@ impl<I, S> MutatorsTuple<I, S> for () {
) -> Result<(), Error> { ) -> Result<(), Error> {
Ok(()) Ok(())
} }
#[inline]
fn names(&self) -> Vec<&str> {
Vec::new()
}
} }
impl<Head, Tail, I, S> MutatorsTuple<I, S> for (Head, Tail) impl<Head, Tail, I, S> MutatorsTuple<I, S> for (Head, Tail)
where where
Head: Mutator<I, S> + Named, Head: Mutator<I, S>,
Tail: MutatorsTuple<I, S>, Tail: MutatorsTuple<I, S>,
{ {
fn mutate_all( fn mutate_all(
@ -258,16 +273,25 @@ where
.get_and_post_exec(index - 1, state, stage_idx, corpus_idx) .get_and_post_exec(index - 1, state, stage_idx, corpus_idx)
} }
} }
fn names(&self) -> Vec<&str> {
let mut ret = self.1.names();
ret.insert(0, self.0.name());
ret
}
} }
/// `Mutator` Python bindings /// `Mutator` Python bindings
#[cfg(feature = "python")] #[cfg(feature = "python")]
#[allow(missing_docs)] #[allow(missing_docs)]
pub mod pybind { pub mod pybind {
use pyo3::prelude::*; use core::ffi::CStr;
use pyo3::{prelude::*, AsPyPointer};
use super::{MutationResult, Mutator}; use super::{MutationResult, Mutator};
use crate::{ use crate::{
bolts::tuples::Named,
corpus::CorpusId, corpus::CorpusId,
inputs::{BytesInput, HasBytesVec}, inputs::{BytesInput, HasBytesVec},
mutators::scheduled::pybind::PythonStdHavocMutator, mutators::scheduled::pybind::PythonStdHavocMutator,
@ -287,6 +311,14 @@ pub mod pybind {
} }
} }
impl Named for PyObjectMutator {
fn name(&self) -> &str {
unsafe { CStr::from_ptr((*(*self.inner.as_ptr()).ob_type).tp_name) }
.to_str()
.unwrap()
}
}
impl Mutator<BytesInput, PythonStdState> for PyObjectMutator { impl Mutator<BytesInput, PythonStdState> for PyObjectMutator {
fn mutate( fn mutate(
&mut self, &mut self,
@ -386,6 +418,15 @@ pub mod pybind {
} }
} }
impl Named for PythonMutator {
fn name(&self) -> &str {
match &self.wrapper {
PythonMutatorWrapper::Python(pyo) => pyo.name(),
PythonMutatorWrapper::StdHavoc(_) => "StdHavocPythonMutator",
}
}
}
impl Mutator<BytesInput, PythonStdState> for PythonMutator { impl Mutator<BytesInput, PythonStdState> for PythonMutator {
fn mutate( fn mutate(
&mut self, &mut self,

View File

@ -1,5 +1,8 @@
//! The `MOpt` mutator scheduler, see <https://github.com/puppet-meteor/MOpt-AFL> and <https://www.usenix.org/conference/usenixsecurity19/presentation/lyu> //! The `MOpt` mutator scheduler, see <https://github.com/puppet-meteor/MOpt-AFL> and <https://www.usenix.org/conference/usenixsecurity19/presentation/lyu>
use alloc::{string::ToString, vec::Vec}; use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::{ use core::{
fmt::{self, Debug}, fmt::{self, Debug},
marker::PhantomData, marker::PhantomData,
@ -9,7 +12,10 @@ use serde::{Deserialize, Serialize};
use super::MutationId; use super::MutationId;
use crate::{ use crate::{
bolts::rands::{Rand, StdRand}, bolts::{
rands::{Rand, StdRand},
tuples::Named,
},
corpus::{Corpus, CorpusId}, corpus::{Corpus, CorpusId},
mutators::{ComposedByMutations, MutationResult, Mutator, MutatorsTuple, ScheduledMutator}, mutators::{ComposedByMutations, MutationResult, Mutator, MutatorsTuple, ScheduledMutator},
state::{HasCorpus, HasMetadata, HasRand, HasSolutions}, state::{HasCorpus, HasMetadata, HasRand, HasSolutions},
@ -365,6 +371,7 @@ where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions, S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{ {
name: String,
mode: MOptMode, mode: MOptMode,
finds_before: usize, finds_before: usize,
mutations: MT, mutations: MT,
@ -539,6 +546,7 @@ where
state.add_metadata::<MOpt>(MOpt::new(mutations.len(), swarm_num, rand_seed)?); state.add_metadata::<MOpt>(MOpt::new(mutations.len(), swarm_num, rand_seed)?);
} }
Ok(Self { Ok(Self {
name: format!("StdMOptMutator[{}]", mutations.names().join(",")),
mode: MOptMode::Pilotfuzzing, mode: MOptMode::Pilotfuzzing,
finds_before: 0, finds_before: 0,
mutations, mutations,
@ -632,6 +640,16 @@ where
} }
} }
impl<I, MT, S> Named for StdMOptMutator<I, MT, S>
where
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
fn name(&self) -> &str {
&self.name
}
}
impl<I, MT, S> ScheduledMutator<I, MT, S> for StdMOptMutator<I, MT, S> impl<I, MT, S> ScheduledMutator<I, MT, S> for StdMOptMutator<I, MT, S>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,

View File

@ -13,7 +13,7 @@ pub use crate::mutators::{mutations::*, token_mutations::*};
use crate::{ use crate::{
bolts::{ bolts::{
rands::Rand, rands::Rand,
tuples::{tuple_list, tuple_list_type, NamedTuple}, tuples::{tuple_list, tuple_list_type, Named, NamedTuple},
AsMutSlice, AsSlice, AsMutSlice, AsSlice,
}, },
corpus::{Corpus, CorpusId}, corpus::{Corpus, CorpusId},
@ -106,6 +106,7 @@ where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand, S: HasRand,
{ {
name: String,
mutations: MT, mutations: MT,
max_stack_pow: u64, max_stack_pow: u64,
phantom: PhantomData<(I, S)>, phantom: PhantomData<(I, S)>,
@ -126,6 +127,16 @@ where
} }
} }
impl<I, MT, S> Named for StdScheduledMutator<I, MT, S>
where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
fn name(&self) -> &str {
&self.name
}
}
impl<I, MT, S> Mutator<I, S> for StdScheduledMutator<I, MT, S> impl<I, MT, S> Mutator<I, S> for StdScheduledMutator<I, MT, S>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
@ -185,6 +196,7 @@ where
/// Create a new [`StdScheduledMutator`] instance specifying mutations /// Create a new [`StdScheduledMutator`] instance specifying mutations
pub fn new(mutations: MT) -> Self { pub fn new(mutations: MT) -> Self {
StdScheduledMutator { StdScheduledMutator {
name: format!("StdScheduledMutator[{}]", mutations.names().join(", ")),
mutations, mutations,
max_stack_pow: 7, max_stack_pow: 7,
phantom: PhantomData, phantom: PhantomData,
@ -194,6 +206,7 @@ where
/// Create a new [`StdScheduledMutator`] instance specifying mutations and the maximun number of iterations /// Create a new [`StdScheduledMutator`] instance specifying mutations and the maximun number of iterations
pub fn with_max_stack_pow(mutations: MT, max_stack_pow: u64) -> Self { pub fn with_max_stack_pow(mutations: MT, max_stack_pow: u64) -> Self {
StdScheduledMutator { StdScheduledMutator {
name: format!("StdScheduledMutator[{}]", mutations.names().join(", ")),
mutations, mutations,
max_stack_pow, max_stack_pow,
phantom: PhantomData, phantom: PhantomData,
@ -279,6 +292,7 @@ where
S: HasRand + HasCorpus, S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>, SM: ScheduledMutator<I, MT, S>,
{ {
name: String,
scheduled: SM, scheduled: SM,
mutation_log: Vec<MutationId>, mutation_log: Vec<MutationId>,
phantom: PhantomData<(I, MT, S)>, phantom: PhantomData<(I, MT, S)>,
@ -300,6 +314,17 @@ where
} }
} }
impl<I, MT, S, SM> Named for LoggerScheduledMutator<I, MT, S, SM>
where
MT: MutatorsTuple<I, S> + NamedTuple,
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{
fn name(&self) -> &str {
&self.name
}
}
impl<I, MT, S, SM> Mutator<I, S> for LoggerScheduledMutator<I, MT, S, SM> impl<I, MT, S, SM> Mutator<I, S> for LoggerScheduledMutator<I, MT, S, SM>
where where
MT: MutatorsTuple<I, S> + NamedTuple, MT: MutatorsTuple<I, S> + NamedTuple,
@ -403,9 +428,11 @@ where
S: HasRand + HasCorpus, S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>, SM: ScheduledMutator<I, MT, S>,
{ {
/// Create a new [`StdScheduledMutator`] instance without mutations and corpus /// Create a new [`LoggerScheduledMutator`] instance without mutations and corpus
/// This mutator logs all mutators.
pub fn new(scheduled: SM) -> Self { pub fn new(scheduled: SM) -> Self {
Self { Self {
name: format!("LoggerScheduledMutator[{}]", scheduled.name()),
scheduled, scheduled,
mutation_log: vec![], mutation_log: vec![],
phantom: PhantomData, phantom: PhantomData,

View File

@ -25,7 +25,7 @@ use crate::{
bolts::{rands::Rand, AsSlice}, bolts::{rands::Rand, AsSlice},
inputs::{HasBytesVec, UsesInput}, inputs::{HasBytesVec, UsesInput},
mutators::{ mutators::{
buffer_self_copy, mutations::buffer_copy, MultipleMutator, MutationResult, Mutator, Named, buffer_self_copy, mutations::buffer_copy, MultiMutator, MutationResult, Mutator, Named,
}, },
observers::cmp::{AFLppCmpValuesMetadata, CmpValues, CmpValuesMetadata}, observers::cmp::{AFLppCmpValuesMetadata, CmpValues, CmpValuesMetadata},
stages::TaintMetadata, stages::TaintMetadata,
@ -1090,37 +1090,37 @@ impl AFLppRedQueen {
} }
} }
impl<I, S> MultipleMutator<I, S> for AFLppRedQueen impl<I, S> MultiMutator<I, S> for AFLppRedQueen
where where
S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus, S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus,
I: HasBytesVec + From<Vec<u8>>, I: HasBytesVec + From<Vec<u8>>,
{ {
#[allow(clippy::needless_range_loop)] #[allow(clippy::needless_range_loop)]
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn mutate( fn multi_mutate(
&mut self, &mut self,
state: &mut S, state: &mut S,
input: &I, input: &I,
ret: &mut Vec<I>,
stage_idx: i32, stage_idx: i32,
) -> Result<MutationResult, Error> { max_count: Option<usize>,
) -> Result<Vec<I>, Error> {
// TODO // TODO
// handle 128-bits logs // handle 128-bits logs
let size = input.bytes().len(); let size = input.bytes().len();
if size == 0 { if size == 0 {
return Ok(MutationResult::Skipped); return Ok(vec![]);
} }
let (cmp_len, cmp_meta, taint_meta) = { let (cmp_len, cmp_meta, taint_meta) = {
let cmp_meta = state.metadata_map().get::<AFLppCmpValuesMetadata>(); let cmp_meta = state.metadata_map().get::<AFLppCmpValuesMetadata>();
let taint_meta = state.metadata_map().get::<TaintMetadata>(); let taint_meta = state.metadata_map().get::<TaintMetadata>();
if cmp_meta.is_none() || taint_meta.is_none() { if cmp_meta.is_none() || taint_meta.is_none() {
return Ok(MutationResult::Skipped); return Ok(vec![]);
} }
let cmp_len = cmp_meta.unwrap().headers().len(); let cmp_len = cmp_meta.unwrap().headers().len();
if cmp_len == 0 { if cmp_len == 0 {
return Ok(MutationResult::Skipped); return Ok(vec![]);
} }
(cmp_len, cmp_meta.unwrap(), taint_meta.unwrap()) (cmp_len, cmp_meta.unwrap(), taint_meta.unwrap())
}; };
@ -1135,7 +1135,7 @@ where
let orig_bytes = input.bytes(); let orig_bytes = input.bytes();
let taint = taint_meta.ranges(); let taint = taint_meta.ranges();
let mut vec = vec![]; let mut ret = max_count.map_or_else(Vec::new, Vec::with_capacity);
let mut gathered_tokens = Tokens::new(); let mut gathered_tokens = Tokens::new();
// println!("orig: {:#?} new: {:#?}", orig_cmpvals, new_cmpvals); // println!("orig: {:#?} new: {:#?}", orig_cmpvals, new_cmpvals);
@ -1172,6 +1172,13 @@ where
} }
for cmp_buf_idx in 0..input_len { for cmp_buf_idx in 0..input_len {
if let Some(max_count) = max_count {
if ret.len() >= max_count {
// TODO: does this bias towards earlier mutations?
break;
}
}
let taint_len = match taint.get(taint_idx) { let taint_len = match taint.get(taint_idx) {
Some(t) => { Some(t) => {
if cmp_buf_idx < t.start { if cmp_buf_idx < t.start {
@ -1213,7 +1220,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// Swapped // Swapped
@ -1229,7 +1236,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
} }
@ -1247,7 +1254,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// Swapped // Swapped
@ -1263,7 +1270,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
} }
*/ */
@ -1301,7 +1308,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// Swapped // Swapped
@ -1318,7 +1325,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
} }
@ -1336,7 +1343,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// Swapped // Swapped
@ -1352,7 +1359,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
} }
@ -1390,7 +1397,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// swapped // swapped
@ -1407,7 +1414,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
} }
@ -1425,7 +1432,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// Swapped // Swapped
@ -1442,7 +1449,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
} }
@ -1483,7 +1490,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// Swapped // Swapped
@ -1500,7 +1507,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
} }
@ -1518,7 +1525,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// Swapped // Swapped
@ -1535,7 +1542,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
} }
@ -1574,7 +1581,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
// Compare v1 against v0 // Compare v1 against v0
@ -1589,7 +1596,7 @@ where
taint_len, taint_len,
input_len, input_len,
hshape, hshape,
&mut vec, &mut ret,
); );
let is_ascii_or_utf8 = self.text_type.is_ascii_or_utf8(); let is_ascii_or_utf8 = self.text_type.is_ascii_or_utf8();
@ -1663,16 +1670,10 @@ where
} }
} }
let mut mutated = false; if let Some(max_count) = max_count {
for item in vec { Ok(ret.into_iter().take(max_count).map(I::from).collect())
ret.push(I::from(item));
mutated = true;
}
if mutated {
Ok(MutationResult::Mutated)
} else { } else {
Ok(MutationResult::Skipped) Ok(ret.into_iter().map(I::from).collect())
} }
} }
} }

View File

@ -2,7 +2,7 @@
//! Instead of a random mutator for a random amount of iterations, we can run //! Instead of a random mutator for a random amount of iterations, we can run
//! a specific mutator for a specified amount of iterations //! a specific mutator for a specified amount of iterations
use alloc::vec::Vec; use alloc::{string::String, vec::Vec};
use core::{ use core::{
fmt::{self, Debug}, fmt::{self, Debug},
marker::PhantomData, marker::PhantomData,
@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
pub use crate::mutators::{mutations::*, token_mutations::*}; pub use crate::mutators::{mutations::*, token_mutations::*};
use crate::{ use crate::{
bolts::{calculate_cumulative_sum_in_place, rands::Rand}, bolts::{calculate_cumulative_sum_in_place, rands::Rand, tuples::Named},
impl_serdeany, impl_serdeany,
mutators::{ mutators::{
ComposedByMutations, MutationId, MutationResult, Mutator, MutatorsTuple, ScheduledMutator, ComposedByMutations, MutationId, MutationResult, Mutator, MutatorsTuple, ScheduledMutator,
@ -80,6 +80,7 @@ where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand, S: HasRand,
{ {
name: String,
mutations: MT, mutations: MT,
max_stack_pow: u64, max_stack_pow: u64,
phantom: PhantomData<(I, S)>, phantom: PhantomData<(I, S)>,
@ -134,6 +135,16 @@ where
} }
} }
impl<I, MT, S> Named for TuneableScheduledMutator<I, MT, S>
where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
fn name(&self) -> &str {
&self.name
}
}
impl<I, MT, S> ScheduledMutator<I, MT, S> for TuneableScheduledMutator<I, MT, S> impl<I, MT, S> ScheduledMutator<I, MT, S> for TuneableScheduledMutator<I, MT, S>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
@ -215,6 +226,7 @@ where
state.add_metadata(TuneableScheduledMutatorMetadata::default()); state.add_metadata(TuneableScheduledMutatorMetadata::default());
} }
TuneableScheduledMutator { TuneableScheduledMutator {
name: format!("TuneableMutator[{}]", mutations.names().join(", ")),
mutations, mutations,
max_stack_pow: 7, max_stack_pow: 7,
phantom: PhantomData, phantom: PhantomData,

View File

@ -11,7 +11,7 @@ use crate::{
fuzzer::Evaluator, fuzzer::Evaluator,
inputs::Input, inputs::Input,
mark_feature_time, mark_feature_time,
mutators::{MultipleMutator, MutationResult, Mutator}, mutators::{MultiMutator, MutationResult, Mutator},
stages::Stage, stages::Stage,
start_timer, start_timer,
state::{HasClientPerfMonitor, HasCorpus, HasRand, UsesState}, state::{HasClientPerfMonitor, HasCorpus, HasRand, UsesState},
@ -260,28 +260,28 @@ where
/// The default mutational stage /// The default mutational stage
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct MultipleMutationalStage<E, EM, I, M, Z> { pub struct MultiMutationalStage<E, EM, I, M, Z> {
mutator: M, mutator: M,
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
phantom: PhantomData<(E, EM, I, Z)>, phantom: PhantomData<(E, EM, I, Z)>,
} }
impl<E, EM, I, M, Z> UsesState for MultipleMutationalStage<E, EM, I, M, Z> impl<E, EM, I, M, Z> UsesState for MultiMutationalStage<E, EM, I, M, Z>
where where
E: UsesState<State = Z::State>, E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>, EM: UsesState<State = Z::State>,
M: MultipleMutator<I, Z::State>, M: MultiMutator<I, Z::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand, Z::State: HasClientPerfMonitor + HasCorpus + HasRand,
{ {
type State = Z::State; type State = Z::State;
} }
impl<E, EM, I, M, Z> Stage<E, EM, Z> for MultipleMutationalStage<E, EM, I, M, Z> impl<E, EM, I, M, Z> Stage<E, EM, Z> for MultiMutationalStage<E, EM, I, M, Z>
where where
E: UsesState<State = Z::State>, E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>, EM: UsesState<State = Z::State>,
M: MultipleMutator<I, Z::State>, M: MultiMutator<I, Z::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand, Z::State: HasClientPerfMonitor + HasCorpus + HasRand,
I: MutatedTransform<Self::Input, Self::State> + Clone, I: MutatedTransform<Self::Input, Self::State> + Clone,
@ -303,14 +303,13 @@ where
}; };
drop(testcase); drop(testcase);
let mut generated = vec![]; let generated = self.mutator.multi_mutate(state, &input, 0, None)?;
let _ = self.mutator.mutate(state, &input, &mut generated, 0)?;
// println!("Generated {}", generated.len()); // println!("Generated {}", generated.len());
for (i, new_input) in generated.into_iter().enumerate() { for (i, new_input) in generated.into_iter().enumerate() {
// Time is measured directly the `evaluate_input` function // Time is measured directly the `evaluate_input` function
let (untransformed, post) = new_input.try_transform_into(state)?; let (untransformed, post) = new_input.try_transform_into(state)?;
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, untransformed)?; let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, untransformed)?;
self.mutator.post_exec(state, i as i32, corpus_idx)?; self.mutator.multi_post_exec(state, i as i32, corpus_idx)?;
post.post_exec(state, i as i32, corpus_idx)?; post.post_exec(state, i as i32, corpus_idx)?;
} }
// println!("Found {}", found); // println!("Found {}", found);
@ -319,11 +318,11 @@ where
} }
} }
impl<E, EM, M, Z> MultipleMutationalStage<E, EM, Z::Input, M, Z> impl<E, EM, M, Z> MultiMutationalStage<E, EM, Z::Input, M, Z>
where where
E: UsesState<State = Z::State>, E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>, EM: UsesState<State = Z::State>,
M: MultipleMutator<Z::Input, Z::State>, M: MultiMutator<Z::Input, Z::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand, Z::State: HasClientPerfMonitor + HasCorpus + HasRand,
{ {
@ -333,11 +332,11 @@ where
} }
} }
impl<E, EM, I, M, Z> MultipleMutationalStage<E, EM, I, M, Z> impl<E, EM, I, M, Z> MultiMutationalStage<E, EM, I, M, Z>
where where
E: UsesState<State = Z::State>, E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>, EM: UsesState<State = Z::State>,
M: MultipleMutator<I, Z::State>, M: MultiMutator<I, Z::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand, Z::State: HasClientPerfMonitor + HasCorpus + HasRand,
{ {