Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Named Mutators and MultiMutator API change #1387

Merged
merged 8 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"libafl",
"libafl_derive",
Expand Down
6 changes: 3 additions & 3 deletions fuzzers/fuzzbench_forkserver_cmplog/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
},
Expand Down Expand Up @@ -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 _,
Expand Down
59 changes: 50 additions & 9 deletions libafl/src/mutators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub enum MutationResult {

/// A mutator takes input, and mutates it.
/// Simple as that.
pub trait Mutator<I, S> {
pub trait Mutator<I, S>: Named {
/// Mutate a given input
fn mutate(
&mut self,
Expand All @@ -90,6 +90,7 @@ pub trait Mutator<I, S> {
) -> Result<MutationResult, Error>;

/// Post-process given the outcome of the execution
#[inline]
fn post_exec(
&mut self,
_state: &mut S,
Expand All @@ -102,18 +103,20 @@ pub trait Mutator<I, S> {

/// A mutator that takes input, and returns a vector of mutated inputs.
/// Simple as that.
pub trait MultipleMutator<I, S> {
/// Mutate a given input
fn mutate(
pub trait MultiMutator<I, S>: 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(
&mut self,
state: &mut S,
input: &I,
vec: &mut Vec<I>,
stage_idx: i32,
) -> Result<MutationResult, Error>;
max_count: Option<usize>,
domenukk marked this conversation as resolved.
Show resolved Hide resolved
) -> Result<Vec<I>, Error>;

/// Post-process given the outcome of the execution
fn post_exec(
#[inline]
fn multi_post_exec(
&mut self,
_state: &mut S,
_stage_idx: i32,
Expand Down Expand Up @@ -158,9 +161,13 @@ pub trait MutatorsTuple<I, S>: HasConstLen {
stage_idx: i32,
corpus_idx: Option<CorpusId>,
) -> Result<(), Error>;

/// Gets all names of the wrapped [`Mutator`]`s`.
fn names(&self) -> Vec<&str>;
}

impl<I, S> MutatorsTuple<I, S> for () {
#[inline]
fn mutate_all(
&mut self,
_state: &mut S,
Expand All @@ -170,6 +177,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
Ok(MutationResult::Skipped)
}

#[inline]
fn post_exec_all(
&mut self,
_state: &mut S,
Expand All @@ -179,6 +187,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
Ok(())
}

#[inline]
fn get_and_mutate(
&mut self,
_index: MutationId,
Expand All @@ -189,6 +198,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
Ok(MutationResult::Skipped)
}

#[inline]
fn get_and_post_exec(
&mut self,
_index: usize,
Expand All @@ -198,11 +208,16 @@ impl<I, S> MutatorsTuple<I, S> for () {
) -> Result<(), Error> {
Ok(())
}

#[inline]
fn names(&self) -> Vec<&str> {
Vec::new()
}
}

impl<Head, Tail, I, S> MutatorsTuple<I, S> for (Head, Tail)
where
Head: Mutator<I, S> + Named,
Head: Mutator<I, S>,
Tail: MutatorsTuple<I, S>,
{
fn mutate_all(
Expand Down Expand Up @@ -258,16 +273,25 @@ 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
#[cfg(feature = "python")]
#[allow(missing_docs)]
pub mod pybind {
use pyo3::prelude::*;
use core::ffi::CStr;

use pyo3::{prelude::*, AsPyPointer};

use super::{MutationResult, Mutator};
use crate::{
bolts::tuples::Named,
corpus::CorpusId,
inputs::{BytesInput, HasBytesVec},
mutators::scheduled::pybind::PythonStdHavocMutator,
Expand All @@ -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 {
fn mutate(
&mut self,
Expand Down Expand Up @@ -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 {
fn mutate(
&mut self,
Expand Down
22 changes: 20 additions & 2 deletions libafl/src/mutators/mopt_mutator.rs
Original file line number Diff line number Diff line change
@@ -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>
use alloc::{string::ToString, vec::Vec};
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::{
fmt::{self, Debug},
marker::PhantomData,
Expand All @@ -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},
Expand Down Expand Up @@ -365,6 +371,7 @@ where
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
name: String,
mode: MOptMode,
finds_before: usize,
mutations: MT,
Expand Down Expand Up @@ -539,6 +546,7 @@ where
state.add_metadata::<MOpt>(MOpt::new(mutations.len(), swarm_num, rand_seed)?);
}
Ok(Self {
name: format!("StdMOptMutator[{}]", mutations.names().join(",")),
mode: MOptMode::Pilotfuzzing,
finds_before: 0,
mutations,
Expand Down Expand Up @@ -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>
where
MT: MutatorsTuple<I, S>,
Expand Down
31 changes: 29 additions & 2 deletions libafl/src/mutators/scheduled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -106,6 +106,7 @@ where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
name: String,
mutations: MT,
max_stack_pow: u64,
phantom: PhantomData<(I, S)>,
Expand All @@ -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>
where
MT: MutatorsTuple<I, S>,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -279,6 +292,7 @@ where
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{
name: String,
scheduled: SM,
mutation_log: Vec<MutationId>,
phantom: PhantomData<(I, MT, S)>,
Expand All @@ -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>
where
MT: MutatorsTuple<I, S> + NamedTuple,
Expand Down Expand Up @@ -403,9 +428,11 @@ where
S: HasRand + HasCorpus,
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 {
Self {
name: format!("LoggerScheduledMutator[{}]", scheduled.name()),
scheduled,
mutation_log: vec![],
phantom: PhantomData,
Expand Down
Loading