From c9be69398031646808705983ac616c0c2ac983fa Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 31 Jul 2023 13:09:06 +0000 Subject: [PATCH 1/7] Mutators need names (alternative to #1379) --- libafl/src/mutators/mod.rs | 19 +++++++++++++--- libafl/src/mutators/mopt_mutator.rs | 22 ++++++++++++++++-- libafl/src/mutators/scheduled.rs | 31 ++++++++++++++++++++++++-- libafl/src/mutators/token_mutations.rs | 4 ++-- libafl/src/mutators/tuneable.rs | 16 +++++++++++-- libafl/src/stages/mutational.rs | 10 ++++----- 6 files changed, 86 insertions(+), 16 deletions(-) diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index 070ac3e574..efbd236d6d 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -80,7 +80,7 @@ pub enum MutationResult { /// A mutator takes input, and mutates it. /// Simple as that. -pub trait Mutator { +pub trait Mutator: Named { /// Mutate a given input fn mutate( &mut self, @@ -102,7 +102,7 @@ pub trait Mutator { /// A mutator that takes input, and returns a vector of mutated inputs. /// Simple as that. -pub trait MultipleMutator { +pub trait MultiMutator: Named { /// Mutate a given input fn mutate( &mut self, @@ -158,6 +158,9 @@ pub trait MutatorsTuple: HasConstLen { stage_idx: i32, corpus_idx: Option, ) -> Result<(), Error>; + + /// Gets all names of the wrapped [`Mutator`]`s`. + fn names(&self) -> Vec<&str>; } impl MutatorsTuple for () { @@ -198,11 +201,15 @@ impl MutatorsTuple for () { ) -> Result<(), Error> { Ok(()) } + + fn names(&self) -> Vec<&str> { + Vec::new() + } } impl MutatorsTuple for (Head, Tail) where - Head: Mutator + Named, + Head: Mutator, Tail: MutatorsTuple, { fn mutate_all( @@ -258,6 +265,12 @@ where .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 diff --git a/libafl/src/mutators/mopt_mutator.rs b/libafl/src/mutators/mopt_mutator.rs index d4e01290b5..d08c9350c2 100644 --- a/libafl/src/mutators/mopt_mutator.rs +++ b/libafl/src/mutators/mopt_mutator.rs @@ -1,5 +1,8 @@ //! The `MOpt` mutator scheduler, see and -use alloc::{string::ToString, vec::Vec}; +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; use core::{ fmt::{self, Debug}, marker::PhantomData, @@ -9,7 +12,10 @@ use serde::{Deserialize, Serialize}; use super::MutationId; use crate::{ - bolts::rands::{Rand, StdRand}, + bolts::{ + rands::{Rand, StdRand}, + tuples::Named, + }, corpus::{Corpus, CorpusId}, mutators::{ComposedByMutations, MutationResult, Mutator, MutatorsTuple, ScheduledMutator}, state::{HasCorpus, HasMetadata, HasRand, HasSolutions}, @@ -365,6 +371,7 @@ where MT: MutatorsTuple, S: HasRand + HasMetadata + HasCorpus + HasSolutions, { + name: String, mode: MOptMode, finds_before: usize, mutations: MT, @@ -539,6 +546,7 @@ where state.add_metadata::(MOpt::new(mutations.len(), swarm_num, rand_seed)?); } Ok(Self { + name: format!("StdMOptMutator[{}]", mutations.names().join(",")), mode: MOptMode::Pilotfuzzing, finds_before: 0, mutations, @@ -632,6 +640,16 @@ where } } +impl Named for StdMOptMutator +where + MT: MutatorsTuple, + S: HasRand + HasMetadata + HasCorpus + HasSolutions, +{ + fn name(&self) -> &str { + &self.name + } +} + impl ScheduledMutator for StdMOptMutator where MT: MutatorsTuple, diff --git a/libafl/src/mutators/scheduled.rs b/libafl/src/mutators/scheduled.rs index 894f53de04..a2a739187c 100644 --- a/libafl/src/mutators/scheduled.rs +++ b/libafl/src/mutators/scheduled.rs @@ -13,7 +13,7 @@ pub use crate::mutators::{mutations::*, token_mutations::*}; use crate::{ bolts::{ rands::Rand, - tuples::{tuple_list, tuple_list_type, NamedTuple}, + tuples::{tuple_list, tuple_list_type, Named, NamedTuple}, AsMutSlice, AsSlice, }, corpus::{Corpus, CorpusId}, @@ -106,6 +106,7 @@ where MT: MutatorsTuple, S: HasRand, { + name: String, mutations: MT, max_stack_pow: u64, phantom: PhantomData<(I, S)>, @@ -126,6 +127,16 @@ where } } +impl Named for StdScheduledMutator +where + MT: MutatorsTuple, + S: HasRand, +{ + fn name(&self) -> &str { + &self.name + } +} + impl Mutator for StdScheduledMutator where MT: MutatorsTuple, @@ -185,6 +196,7 @@ where /// Create a new [`StdScheduledMutator`] instance specifying mutations pub fn new(mutations: MT) -> Self { StdScheduledMutator { + name: format!("StdScheduledMutator[{}]", mutations.names().join(", ")), mutations, max_stack_pow: 7, phantom: PhantomData, @@ -194,6 +206,7 @@ where /// 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 { StdScheduledMutator { + name: format!("StdScheduledMutator[{}]", mutations.names().join(", ")), mutations, max_stack_pow, phantom: PhantomData, @@ -279,6 +292,7 @@ where S: HasRand + HasCorpus, SM: ScheduledMutator, { + name: String, scheduled: SM, mutation_log: Vec, phantom: PhantomData<(I, MT, S)>, @@ -300,6 +314,17 @@ where } } +impl Named for LoggerScheduledMutator +where + MT: MutatorsTuple + NamedTuple, + S: HasRand + HasCorpus, + SM: ScheduledMutator, +{ + fn name(&self) -> &str { + &self.name + } +} + impl Mutator for LoggerScheduledMutator where MT: MutatorsTuple + NamedTuple, @@ -403,9 +428,11 @@ where S: HasRand + HasCorpus, SM: ScheduledMutator, { - /// 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 { Self { + name: format!("LoggerScheduledMutator[{}]", scheduled.name()), scheduled, mutation_log: vec![], phantom: PhantomData, diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 321a9d7cda..b1fa3b6309 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -25,7 +25,7 @@ use crate::{ bolts::{rands::Rand, AsSlice}, inputs::{HasBytesVec, UsesInput}, 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}, stages::TaintMetadata, @@ -1090,7 +1090,7 @@ impl AFLppRedQueen { } } -impl MultipleMutator for AFLppRedQueen +impl MultiMutator for AFLppRedQueen where S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus, I: HasBytesVec + From>, diff --git a/libafl/src/mutators/tuneable.rs b/libafl/src/mutators/tuneable.rs index 2e122d7ec0..67dbac46a1 100644 --- a/libafl/src/mutators/tuneable.rs +++ b/libafl/src/mutators/tuneable.rs @@ -2,7 +2,7 @@ //! Instead of a random mutator for a random amount of iterations, we can run //! a specific mutator for a specified amount of iterations -use alloc::vec::Vec; +use alloc::{string::String, vec::Vec}; use core::{ fmt::{self, Debug}, marker::PhantomData, @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; pub use crate::mutators::{mutations::*, token_mutations::*}; use crate::{ - bolts::{calculate_cumulative_sum_in_place, rands::Rand}, + bolts::{calculate_cumulative_sum_in_place, rands::Rand, tuples::Named}, impl_serdeany, mutators::{ ComposedByMutations, MutationId, MutationResult, Mutator, MutatorsTuple, ScheduledMutator, @@ -80,6 +80,7 @@ where MT: MutatorsTuple, S: HasRand, { + name: String, mutations: MT, max_stack_pow: u64, phantom: PhantomData<(I, S)>, @@ -134,6 +135,16 @@ where } } +impl Named for TuneableScheduledMutator +where + MT: MutatorsTuple, + S: HasRand, +{ + fn name(&self) -> &str { + &self.name + } +} + impl ScheduledMutator for TuneableScheduledMutator where MT: MutatorsTuple, @@ -215,6 +226,7 @@ where state.add_metadata(TuneableScheduledMutatorMetadata::default()); } TuneableScheduledMutator { + name: format!("TuneableMutator[{}]", mutations.names().join(", ")), mutations, max_stack_pow: 7, phantom: PhantomData, diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 2f85925bff..2b2a1477f0 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -11,7 +11,7 @@ use crate::{ fuzzer::Evaluator, inputs::Input, mark_feature_time, - mutators::{MultipleMutator, MutationResult, Mutator}, + mutators::{MultiMutator, MutationResult, Mutator}, stages::Stage, start_timer, state::{HasClientPerfMonitor, HasCorpus, HasRand, UsesState}, @@ -270,7 +270,7 @@ impl UsesState for MultipleMutationalStage where E: UsesState, EM: UsesState, - M: MultipleMutator, + M: MultiMutator, Z: Evaluator, Z::State: HasClientPerfMonitor + HasCorpus + HasRand, { @@ -281,7 +281,7 @@ impl Stage for MultipleMutationalStage where E: UsesState, EM: UsesState, - M: MultipleMutator, + M: MultiMutator, Z: Evaluator, Z::State: HasClientPerfMonitor + HasCorpus + HasRand, I: MutatedTransform + Clone, @@ -323,7 +323,7 @@ impl MultipleMutationalStage where E: UsesState, EM: UsesState, - M: MultipleMutator, + M: MultiMutator, Z: Evaluator, Z::State: HasClientPerfMonitor + HasCorpus + HasRand, { @@ -337,7 +337,7 @@ impl MultipleMutationalStage where E: UsesState, EM: UsesState, - M: MultipleMutator, + M: MultiMutator, Z: Evaluator, Z::State: HasClientPerfMonitor + HasCorpus + HasRand, { From 4a643399c2509cb463f123664510fcf798f77092 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 31 Jul 2023 13:47:54 +0000 Subject: [PATCH 2/7] Signature of MultiMutator shouldn't be the same as the normal mutator --- .../fuzzbench_forkserver_cmplog/src/main.rs | 6 +- libafl/src/mutators/mod.rs | 21 ++--- libafl/src/mutators/token_mutations.rs | 94 ++++++++++++------- libafl/src/stages/mutational.rs | 13 ++- 4 files changed, 74 insertions(+), 60 deletions(-) diff --git a/fuzzers/fuzzbench_forkserver_cmplog/src/main.rs b/fuzzers/fuzzbench_forkserver_cmplog/src/main.rs index 249c3d448f..bb7ed78e0a 100644 --- a/fuzzers/fuzzbench_forkserver_cmplog/src/main.rs +++ b/fuzzers/fuzzbench_forkserver_cmplog/src/main.rs @@ -26,7 +26,7 @@ use libafl::{ monitors::SimpleMonitor, mutators::{ scheduled::havoc_mutations, token_mutations::AFLppRedQueen, tokens_mutations, - MutationResult, StdMOptMutator, Tokens, + StdMOptMutator, Tokens, }, observers::{ AFLppCmpMap, AFLppForkserverCmpObserver, HitcountsMapObserver, StdMapObserver, TimeObserver, @@ -35,7 +35,7 @@ use libafl::{ powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, }, stages::{ - calibrate::CalibrationStage, mutational::MultipleMutationalStage, + calibrate::CalibrationStage, mutational::MultiMutationalStage, power::StdPowerMutationalStage, tracing::AFLppCmplogTracingStage, ColorizationStage, IfStage, }, @@ -368,7 +368,7 @@ fn fuzz( let tracing = AFLppCmplogTracingStage::with_cmplog_observer_name(cmplog_executor, "cmplog"); // 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 _, _executor: &mut _, diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index efbd236d6d..fb8e630dbd 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -102,25 +102,16 @@ pub trait Mutator: Named { /// A mutator that takes input, and returns a vector of mutated inputs. /// Simple as that. -pub trait MultiMutator: Named { - /// Mutate a given input - fn mutate( +pub trait MultiMutator: Mutator { + /// Mutate a given input up to [`max_count`] times, + /// or as many times as appropriate, if no [`max_count`] is given + fn multi_mutate( &mut self, state: &mut S, input: &I, - vec: &mut Vec, stage_idx: i32, - ) -> Result; - - /// Post-process given the outcome of the execution - fn post_exec( - &mut self, - _state: &mut S, - _stage_idx: i32, - _corpus_idx: Option, - ) -> Result<(), Error> { - Ok(()) - } + max_count: Option, + ) -> Result, Error>; } /// A `Tuple` of `Mutators` that can execute multiple `Mutators` in a row. diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index b1fa3b6309..37bc9e1755 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -1090,6 +1090,27 @@ impl AFLppRedQueen { } } +impl Mutator for AFLppRedQueen +where + S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus, + I: HasBytesVec + From>, +{ + fn mutate( + &mut self, + state: &mut S, + input: &mut I, + stage_idx: i32, + ) -> Result { + let mut result = self.multi_mutate(state, input, stage_idx, Some(1))?; + if let Some(first_input) = result.pop() { + *input = first_input; + Ok(MutationResult::Mutated) + } else { + Ok(MutationResult::Skipped) + } + } +} + impl MultiMutator for AFLppRedQueen where S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus, @@ -1097,30 +1118,30 @@ where { #[allow(clippy::needless_range_loop)] #[allow(clippy::too_many_lines)] - fn mutate( + fn multi_mutate( &mut self, state: &mut S, input: &I, - ret: &mut Vec, stage_idx: i32, - ) -> Result { + max_count: Option, + ) -> Result, Error> { // TODO // handle 128-bits logs let size = input.bytes().len(); if size == 0 { - return Ok(MutationResult::Skipped); + return Ok(vec![]); } let (cmp_len, cmp_meta, taint_meta) = { let cmp_meta = state.metadata_map().get::(); let taint_meta = state.metadata_map().get::(); if cmp_meta.is_none() || taint_meta.is_none() { - return Ok(MutationResult::Skipped); + return Ok(vec![]); } let cmp_len = cmp_meta.unwrap().headers().len(); if cmp_len == 0 { - return Ok(MutationResult::Skipped); + return Ok(vec![]); } (cmp_len, cmp_meta.unwrap(), taint_meta.unwrap()) }; @@ -1135,7 +1156,7 @@ where let orig_bytes = input.bytes(); 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(); // println!("orig: {:#?} new: {:#?}", orig_cmpvals, new_cmpvals); @@ -1172,6 +1193,13 @@ where } 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) { Some(t) => { if cmp_buf_idx < t.start { @@ -1213,7 +1241,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // Swapped @@ -1229,7 +1257,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); } @@ -1247,7 +1275,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // Swapped @@ -1263,7 +1291,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); } */ @@ -1301,7 +1329,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // Swapped @@ -1318,7 +1346,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); } @@ -1336,7 +1364,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // Swapped @@ -1352,7 +1380,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); } @@ -1390,7 +1418,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // swapped @@ -1407,7 +1435,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); } @@ -1425,7 +1453,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // Swapped @@ -1442,7 +1470,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); } @@ -1483,7 +1511,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // Swapped @@ -1500,7 +1528,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); } @@ -1518,7 +1546,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // Swapped @@ -1535,7 +1563,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); } @@ -1574,7 +1602,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); // Compare v1 against v0 @@ -1589,7 +1617,7 @@ where taint_len, input_len, hshape, - &mut vec, + &mut ret, ); let is_ascii_or_utf8 = self.text_type.is_ascii_or_utf8(); @@ -1663,17 +1691,13 @@ where } } - let mut mutated = false; - for item in vec { - ret.push(I::from(item)); - mutated = true; - } + let ret_count = max_count.unwrap_or_else(|| ret.len()); - if mutated { - Ok(MutationResult::Mutated) - } else { - Ok(MutationResult::Skipped) - } + Ok(ret + .into_iter() + .take(ret_count) + .map(|item| I::from(item)) + .collect()) } } diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 2b2a1477f0..6102fa226e 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -260,13 +260,13 @@ where /// The default mutational stage #[derive(Clone, Debug)] -pub struct MultipleMutationalStage { +pub struct MultiMutationalStage { mutator: M, #[allow(clippy::type_complexity)] phantom: PhantomData<(E, EM, I, Z)>, } -impl UsesState for MultipleMutationalStage +impl UsesState for MultiMutationalStage where E: UsesState, EM: UsesState, @@ -277,7 +277,7 @@ where type State = Z::State; } -impl Stage for MultipleMutationalStage +impl Stage for MultiMutationalStage where E: UsesState, EM: UsesState, @@ -303,8 +303,7 @@ where }; drop(testcase); - let mut generated = vec![]; - let _ = self.mutator.mutate(state, &input, &mut generated, 0)?; + let generated = self.mutator.multi_mutate(state, &input, 0, None)?; // println!("Generated {}", generated.len()); for (i, new_input) in generated.into_iter().enumerate() { // Time is measured directly the `evaluate_input` function @@ -319,7 +318,7 @@ where } } -impl MultipleMutationalStage +impl MultiMutationalStage where E: UsesState, EM: UsesState, @@ -333,7 +332,7 @@ where } } -impl MultipleMutationalStage +impl MultiMutationalStage where E: UsesState, EM: UsesState, From 70524354d41a099e8a9ce771f910f598ca12aa41 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 1 Aug 2023 10:53:58 +0200 Subject: [PATCH 3/7] Named for python, remove mutator for multi_mutator --- libafl/src/mutators/mod.rs | 39 +++++++++++++++++++++++++- libafl/src/mutators/token_mutations.rs | 21 -------------- libafl/src/stages/mutational.rs | 2 +- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index fb8e630dbd..cdfa892bb6 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -90,6 +90,7 @@ pub trait Mutator: Named { ) -> Result; /// Post-process given the outcome of the execution + #[inline] fn post_exec( &mut self, _state: &mut S, @@ -102,7 +103,7 @@ pub trait Mutator: Named { /// A mutator that takes input, and returns a vector of mutated inputs. /// Simple as that. -pub trait MultiMutator: Mutator { +pub trait MultiMutator: Named { /// Mutate a given input up to [`max_count`] times, /// or as many times as appropriate, if no [`max_count`] is given fn multi_mutate( @@ -112,6 +113,17 @@ pub trait MultiMutator: Mutator { stage_idx: i32, max_count: Option, ) -> Result, Error>; + + /// Post-process given the outcome of the execution + #[inline] + fn multi_post_exec( + &mut self, + _state: &mut S, + _stage_idx: i32, + _corpus_idx: Option, + ) -> Result<(), Error> { + Ok(()) + } } /// A `Tuple` of `Mutators` that can execute multiple `Mutators` in a row. @@ -155,6 +167,7 @@ pub trait MutatorsTuple: HasConstLen { } impl MutatorsTuple for () { + #[inline] fn mutate_all( &mut self, _state: &mut S, @@ -164,6 +177,7 @@ impl MutatorsTuple for () { Ok(MutationResult::Skipped) } + #[inline] fn post_exec_all( &mut self, _state: &mut S, @@ -173,6 +187,7 @@ impl MutatorsTuple for () { Ok(()) } + #[inline] fn get_and_mutate( &mut self, _index: MutationId, @@ -183,6 +198,7 @@ impl MutatorsTuple for () { Ok(MutationResult::Skipped) } + #[inline] fn get_and_post_exec( &mut self, _index: usize, @@ -193,6 +209,7 @@ impl MutatorsTuple for () { Ok(()) } + #[inline] fn names(&self) -> Vec<&str> { Vec::new() } @@ -268,10 +285,13 @@ where #[cfg(feature = "python")] #[allow(missing_docs)] pub mod pybind { + use core::ffi::CStr; use pyo3::prelude::*; + use pyo3::AsPyPointer; use super::{MutationResult, Mutator}; use crate::{ + bolts::tuples::Named, corpus::CorpusId, inputs::{BytesInput, HasBytesVec}, mutators::scheduled::pybind::PythonStdHavocMutator, @@ -291,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 for PyObjectMutator { fn mutate( &mut self, @@ -390,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 for PythonMutator { fn mutate( &mut self, diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 37bc9e1755..a96f2b4272 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -1090,27 +1090,6 @@ impl AFLppRedQueen { } } -impl Mutator for AFLppRedQueen -where - S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus, - I: HasBytesVec + From>, -{ - fn mutate( - &mut self, - state: &mut S, - input: &mut I, - stage_idx: i32, - ) -> Result { - let mut result = self.multi_mutate(state, input, stage_idx, Some(1))?; - if let Some(first_input) = result.pop() { - *input = first_input; - Ok(MutationResult::Mutated) - } else { - Ok(MutationResult::Skipped) - } - } -} - impl MultiMutator for AFLppRedQueen where S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus, diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 6102fa226e..fe28e99a39 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -309,7 +309,7 @@ where // Time is measured directly the `evaluate_input` function let (untransformed, post) = new_input.try_transform_into(state)?; 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)?; } // println!("Found {}", found); From 413b5bb34aac5e15c76615fef31253db676b8555 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 1 Aug 2023 11:19:39 +0200 Subject: [PATCH 4/7] fmt --- libafl/src/mutators/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index cdfa892bb6..475ab0e67b 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -286,8 +286,8 @@ where #[allow(missing_docs)] pub mod pybind { use core::ffi::CStr; - use pyo3::prelude::*; - use pyo3::AsPyPointer; + + use pyo3::{prelude::*, AsPyPointer}; use super::{MutationResult, Mutator}; use crate::{ From 17b27157cde30d6f621f30a1811c5d8c332dc29e Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 1 Aug 2023 11:24:47 +0200 Subject: [PATCH 5/7] clippy edition warning --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index ef58e3fa83..a56246ffdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "libafl", "libafl_derive", From a8391df4ad1c686a7eb384dbb568fda38985a02c Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 1 Aug 2023 12:25:45 +0200 Subject: [PATCH 6/7] clippy --- libafl/src/mutators/token_mutations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index a96f2b4272..1cd8e8ea62 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -1670,7 +1670,7 @@ where } } - let ret_count = max_count.unwrap_or_else(|| ret.len()); + let ret_count = max_count.unwrap_or(ret.len()); Ok(ret .into_iter() From c2cdebc519553fbc38f4f181949fd0f800f5f311 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 1 Aug 2023 13:23:15 +0200 Subject: [PATCH 7/7] mac_count doc fix, return cleanup --- libafl/src/mutators/mod.rs | 4 ++-- libafl/src/mutators/token_mutations.rs | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index 475ab0e67b..70dd76eeb2 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -104,8 +104,8 @@ pub trait Mutator: Named { /// A mutator that takes input, and returns a vector of mutated inputs. /// Simple as that. pub trait MultiMutator: Named { - /// Mutate a given input up to [`max_count`] times, - /// or as many times as appropriate, if no [`max_count`] is given + /// Mutate a given input up to `max_count` times, + /// or as many times as appropriate, if no `max_count` is given fn multi_mutate( &mut self, state: &mut S, diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 1cd8e8ea62..ce4c34ed18 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -1670,13 +1670,11 @@ where } } - let ret_count = max_count.unwrap_or(ret.len()); - - Ok(ret - .into_iter() - .take(ret_count) - .map(|item| I::from(item)) - .collect()) + if let Some(max_count) = max_count { + Ok(ret.into_iter().take(max_count).map(I::from).collect()) + } else { + Ok(ret.into_iter().map(I::from).collect()) + } } }