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:
parent
90e9f3c786
commit
006dcac00c
@ -1,4 +1,5 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"libafl",
|
"libafl",
|
||||||
"libafl_derive",
|
"libafl_derive",
|
||||||
|
@ -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 _,
|
||||||
|
@ -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,
|
||||||
|
@ -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>,
|
||||||
|
@ -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,
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user