#![allow(clippy::use_self)] #![allow(clippy::cast_possible_truncation)] use std::any::Any;
use std::cmp::min;
use std::fmt;
use std::marker::PhantomData;
use std::sync::atomic::Ordering;
use super::Mutator;
use crate::corpora::Corpus;
use crate::error::FeroxFuzzError;
use crate::input::Data;
use crate::metadata::AsAny;
use crate::state::SharedState;
use crate::std_ext::ops::Len;
use crate::std_ext::tuple::Named;
use crate::{atomic_load, AsBytes};
use libafl::bolts::rands::Rand;
use libafl::inputs::HasBytesVec;
use libafl::mutators::mutations::{buffer_copy, buffer_self_copy};
use libafl::state::{HasMaxSize, HasRand};
#[cfg(feature = "serde")]
use serde::{
de::{self, Deserialize, Deserializer, MapAccess, Visitor},
ser::{Serialize, Serializer},
};
use tracing::{debug, error, instrument};
pub use libafl::mutators::mutations::{
BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator, ByteIncMutator,
ByteInterestingMutator, ByteNegMutator, ByteRandMutator, BytesCopyMutator, BytesDeleteMutator,
BytesExpandMutator, BytesInsertCopyMutator, BytesInsertMutator, BytesRandInsertMutator,
BytesRandSetMutator, BytesSetMutator, BytesSwapMutator, DwordAddMutator,
DwordInterestingMutator, QwordAddMutator, WordAddMutator, WordInterestingMutator,
};
#[derive(Debug)]
#[non_exhaustive]
pub enum LibAflMutator {
BitFlipMutator(BitFlipMutator),
ByteAddMutator(ByteAddMutator),
ByteDecMutator(ByteDecMutator),
ByteFlipMutator(ByteFlipMutator),
ByteIncMutator(ByteIncMutator),
ByteInterestingMutator(ByteInterestingMutator),
ByteNegMutator(ByteNegMutator),
ByteRandMutator(ByteRandMutator),
BytesCopyMutator(BytesCopyMutator),
BytesDeleteMutator(BytesDeleteMutator),
BytesExpandMutator(BytesExpandMutator),
BytesInsertCopyMutator(BytesInsertCopyMutator),
BytesInsertMutator(BytesInsertMutator),
BytesRandInsertMutator(BytesRandInsertMutator),
BytesRandSetMutator(BytesRandSetMutator),
BytesSetMutator(BytesSetMutator),
BytesSwapMutator(BytesSwapMutator),
CrossoverInsertMutator(CrossoverInsertMutator),
CrossoverReplaceMutator(CrossoverReplaceMutator),
DwordAddMutator(DwordAddMutator),
DwordInterestingMutator(DwordInterestingMutator),
QwordAddMutator(QwordAddMutator),
WordAddMutator(WordAddMutator),
WordInterestingMutator(WordInterestingMutator),
}
#[allow(clippy::too_many_lines)] impl Mutator for LibAflMutator {
fn mutate(&mut self, input: &mut Data, state: &mut SharedState) -> Result<(), FeroxFuzzError> {
if !input.is_fuzzable() {
return Ok(());
}
match self {
LibAflMutator::BitFlipMutator(mutator) => {
<BitFlipMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::ByteAddMutator(mutator) => {
<ByteAddMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::ByteDecMutator(mutator) => {
<ByteDecMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::ByteFlipMutator(mutator) => {
<ByteFlipMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::ByteIncMutator(mutator) => {
<ByteIncMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::ByteInterestingMutator(mutator) => {
<ByteInterestingMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::ByteNegMutator(mutator) => {
<ByteNegMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::ByteRandMutator(mutator) => {
<ByteRandMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesCopyMutator(mutator) => {
<BytesCopyMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesDeleteMutator(mutator) => {
<BytesDeleteMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesExpandMutator(mutator) => {
<BytesExpandMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesInsertCopyMutator(mutator) => {
<BytesInsertCopyMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesInsertMutator(mutator) => {
<BytesInsertMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesRandInsertMutator(mutator) => {
<BytesRandInsertMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesRandSetMutator(mutator) => {
<BytesRandSetMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesSetMutator(mutator) => {
<BytesSetMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::BytesSwapMutator(mutator) => {
<BytesSwapMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::CrossoverInsertMutator(mutator) => return mutator.mutate(input, state),
LibAflMutator::CrossoverReplaceMutator(mutator) => return mutator.mutate(input, state),
LibAflMutator::DwordAddMutator(mutator) => {
<DwordAddMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::DwordInterestingMutator(mutator) => {
<DwordInterestingMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::QwordAddMutator(mutator) => {
<QwordAddMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::WordAddMutator(mutator) => {
<WordAddMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
LibAflMutator::WordInterestingMutator(mutator) => {
<WordInterestingMutator as libafl::mutators::Mutator<_, _>>::mutate(
mutator, state, input, 0,
)
}
}
.map_err(|source| {
error!("LibAFL mutator failed: {}", source);
FeroxFuzzError::MutationError { source }
})?;
Ok(())
}
}
impl Named for LibAflMutator {
fn name(&self) -> &str {
match self {
LibAflMutator::BitFlipMutator(mutator) => mutator.name(),
LibAflMutator::ByteAddMutator(mutator) => mutator.name(),
LibAflMutator::ByteDecMutator(mutator) => mutator.name(),
LibAflMutator::ByteFlipMutator(mutator) => mutator.name(),
LibAflMutator::ByteIncMutator(mutator) => mutator.name(),
LibAflMutator::ByteInterestingMutator(mutator) => mutator.name(),
LibAflMutator::ByteNegMutator(mutator) => mutator.name(),
LibAflMutator::ByteRandMutator(mutator) => mutator.name(),
LibAflMutator::BytesCopyMutator(mutator) => mutator.name(),
LibAflMutator::BytesDeleteMutator(mutator) => mutator.name(),
LibAflMutator::BytesExpandMutator(mutator) => mutator.name(),
LibAflMutator::BytesInsertCopyMutator(mutator) => mutator.name(),
LibAflMutator::BytesInsertMutator(mutator) => mutator.name(),
LibAflMutator::BytesRandInsertMutator(mutator) => mutator.name(),
LibAflMutator::BytesRandSetMutator(mutator) => mutator.name(),
LibAflMutator::BytesSetMutator(mutator) => mutator.name(),
LibAflMutator::BytesSwapMutator(mutator) => mutator.name(),
LibAflMutator::CrossoverInsertMutator(mutator) => mutator.name(),
LibAflMutator::CrossoverReplaceMutator(mutator) => mutator.name(),
LibAflMutator::DwordAddMutator(mutator) => mutator.name(),
LibAflMutator::DwordInterestingMutator(mutator) => mutator.name(),
LibAflMutator::QwordAddMutator(mutator) => mutator.name(),
LibAflMutator::WordAddMutator(mutator) => mutator.name(),
LibAflMutator::WordInterestingMutator(mutator) => mutator.name(),
}
}
}
impl AsAny for LibAflMutator {
fn as_any(&self) -> &dyn Any {
match self {
LibAflMutator::BitFlipMutator(mutator) => mutator,
LibAflMutator::ByteAddMutator(mutator) => mutator,
LibAflMutator::ByteDecMutator(mutator) => mutator,
LibAflMutator::ByteFlipMutator(mutator) => mutator,
LibAflMutator::ByteIncMutator(mutator) => mutator,
LibAflMutator::ByteInterestingMutator(mutator) => mutator,
LibAflMutator::ByteNegMutator(mutator) => mutator,
LibAflMutator::ByteRandMutator(mutator) => mutator,
LibAflMutator::BytesCopyMutator(mutator) => mutator,
LibAflMutator::BytesDeleteMutator(mutator) => mutator,
LibAflMutator::BytesExpandMutator(mutator) => mutator,
LibAflMutator::BytesInsertCopyMutator(mutator) => mutator,
LibAflMutator::BytesInsertMutator(mutator) => mutator,
LibAflMutator::BytesRandInsertMutator(mutator) => mutator,
LibAflMutator::BytesRandSetMutator(mutator) => mutator,
LibAflMutator::BytesSetMutator(mutator) => mutator,
LibAflMutator::BytesSwapMutator(mutator) => mutator,
LibAflMutator::CrossoverInsertMutator(mutator) => mutator,
LibAflMutator::CrossoverReplaceMutator(mutator) => mutator,
LibAflMutator::DwordAddMutator(mutator) => mutator,
LibAflMutator::DwordInterestingMutator(mutator) => mutator,
LibAflMutator::QwordAddMutator(mutator) => mutator,
LibAflMutator::WordAddMutator(mutator) => mutator,
LibAflMutator::WordInterestingMutator(mutator) => mutator,
}
}
}
impl Clone for LibAflMutator {
fn clone(&self) -> Self {
match self {
LibAflMutator::BitFlipMutator(_mutator) => {
LibAflMutator::BitFlipMutator(BitFlipMutator::new())
}
LibAflMutator::ByteAddMutator(_mutator) => {
LibAflMutator::ByteAddMutator(ByteAddMutator::new())
}
LibAflMutator::ByteDecMutator(_mutator) => {
LibAflMutator::ByteDecMutator(ByteDecMutator::new())
}
LibAflMutator::ByteFlipMutator(_mutator) => {
LibAflMutator::ByteFlipMutator(ByteFlipMutator::new())
}
LibAflMutator::ByteIncMutator(_mutator) => {
LibAflMutator::ByteIncMutator(ByteIncMutator::new())
}
LibAflMutator::ByteInterestingMutator(_mutator) => {
LibAflMutator::ByteInterestingMutator(ByteInterestingMutator::new())
}
LibAflMutator::ByteNegMutator(_mutator) => {
LibAflMutator::ByteNegMutator(ByteNegMutator::new())
}
LibAflMutator::ByteRandMutator(_mutator) => {
LibAflMutator::ByteRandMutator(ByteRandMutator::new())
}
LibAflMutator::BytesCopyMutator(_mutator) => {
LibAflMutator::BytesCopyMutator(BytesCopyMutator::new())
}
LibAflMutator::BytesDeleteMutator(_mutator) => {
LibAflMutator::BytesDeleteMutator(BytesDeleteMutator::new())
}
LibAflMutator::BytesExpandMutator(_mutator) => {
LibAflMutator::BytesExpandMutator(BytesExpandMutator::new())
}
LibAflMutator::BytesInsertCopyMutator(_mutator) => {
LibAflMutator::BytesInsertCopyMutator(BytesInsertCopyMutator::new())
}
LibAflMutator::BytesInsertMutator(_mutator) => {
LibAflMutator::BytesInsertMutator(BytesInsertMutator::new())
}
LibAflMutator::BytesRandInsertMutator(_mutator) => {
LibAflMutator::BytesRandInsertMutator(BytesRandInsertMutator::new())
}
LibAflMutator::BytesRandSetMutator(_mutator) => {
LibAflMutator::BytesRandSetMutator(BytesRandSetMutator::new())
}
LibAflMutator::BytesSetMutator(_mutator) => {
LibAflMutator::BytesSetMutator(BytesSetMutator::new())
}
LibAflMutator::BytesSwapMutator(_mutator) => {
LibAflMutator::BytesSwapMutator(BytesSwapMutator::new())
}
LibAflMutator::CrossoverInsertMutator(mutator) => {
LibAflMutator::CrossoverInsertMutator(CrossoverInsertMutator::new(
&mutator.corpus_name,
))
}
LibAflMutator::CrossoverReplaceMutator(mutator) => {
LibAflMutator::CrossoverReplaceMutator(CrossoverReplaceMutator::new(
&mutator.corpus_name,
))
}
LibAflMutator::DwordAddMutator(_mutator) => {
LibAflMutator::DwordAddMutator(DwordAddMutator::new())
}
LibAflMutator::DwordInterestingMutator(_mutator) => {
LibAflMutator::DwordInterestingMutator(DwordInterestingMutator::new())
}
LibAflMutator::QwordAddMutator(_mutator) => {
LibAflMutator::QwordAddMutator(QwordAddMutator::new())
}
LibAflMutator::WordAddMutator(_mutator) => {
LibAflMutator::WordAddMutator(WordAddMutator::new())
}
LibAflMutator::WordInterestingMutator(_mutator) => {
LibAflMutator::WordInterestingMutator(WordInterestingMutator::new())
}
}
}
}
#[cfg(feature = "serde")]
impl Serialize for LibAflMutator {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
LibAflMutator::BitFlipMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 0, "BitFlipMutator", "")
}
LibAflMutator::ByteAddMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 1, "ByteAddMutator", "")
}
LibAflMutator::ByteDecMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 2, "ByteDecMutator", "")
}
LibAflMutator::ByteFlipMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 3, "ByteFlipMutator", "")
}
LibAflMutator::ByteIncMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 4, "ByteIncMutator", "")
}
LibAflMutator::ByteInterestingMutator(_mutator) => serializer
.serialize_newtype_variant("LibAflMutator", 5, "ByteInterestingMutator", ""),
LibAflMutator::ByteNegMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 6, "ByteNegMutator", "")
}
LibAflMutator::ByteRandMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 7, "ByteRandMutator", "")
}
LibAflMutator::BytesCopyMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 8, "BytesCopyMutator", "")
}
LibAflMutator::BytesDeleteMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 9, "BytesDeleteMutator", "")
}
LibAflMutator::BytesExpandMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 10, "BytesExpandMutator", "")
}
LibAflMutator::BytesInsertCopyMutator(_mutator) => serializer
.serialize_newtype_variant("LibAflMutator", 11, "BytesInsertCopyMutator", ""),
LibAflMutator::BytesInsertMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 12, "BytesInsertMutator", "")
}
LibAflMutator::BytesRandInsertMutator(_mutator) => serializer
.serialize_newtype_variant("LibAflMutator", 13, "BytesRandInsertMutator", ""),
LibAflMutator::BytesRandSetMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 14, "BytesRandSetMutator", "")
}
LibAflMutator::BytesSetMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 15, "BytesSetMutator", "")
}
LibAflMutator::BytesSwapMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 16, "BytesSwapMutator", "")
}
LibAflMutator::CrossoverInsertMutator(mutator) => serializer.serialize_newtype_variant(
"LibAflMutator",
17,
"CrossoverInsertMutator",
&mutator.corpus_name,
),
LibAflMutator::CrossoverReplaceMutator(mutator) => serializer
.serialize_newtype_variant(
"LibAflMutator",
18,
"CrossoverReplaceMutator",
&mutator.corpus_name,
),
LibAflMutator::DwordAddMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 19, "DwordAddMutator", "")
}
LibAflMutator::DwordInterestingMutator(_mutator) => serializer
.serialize_newtype_variant("LibAflMutator", 20, "DwordInterestingMutator", ""),
LibAflMutator::QwordAddMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 21, "QwordAddMutator", "")
}
LibAflMutator::WordAddMutator(_mutator) => {
serializer.serialize_newtype_variant("LibAflMutator", 22, "WordAddMutator", "")
}
LibAflMutator::WordInterestingMutator(_mutator) => serializer
.serialize_newtype_variant("LibAflMutator", 23, "WordInterestingMutator", ""),
}
}
}
macro_rules! impl_libafl_mutation {
($mutation_type:ty) => {
impl AsAny for $mutation_type {
fn as_any(&self) -> &dyn Any {
self
}
}
};
}
impl_libafl_mutation!(BitFlipMutator);
impl_libafl_mutation!(ByteAddMutator);
impl_libafl_mutation!(ByteDecMutator);
impl_libafl_mutation!(ByteFlipMutator);
impl_libafl_mutation!(ByteIncMutator);
impl_libafl_mutation!(ByteInterestingMutator);
impl_libafl_mutation!(ByteNegMutator);
impl_libafl_mutation!(ByteRandMutator);
impl_libafl_mutation!(BytesCopyMutator);
impl_libafl_mutation!(BytesDeleteMutator);
impl_libafl_mutation!(BytesExpandMutator);
impl_libafl_mutation!(BytesInsertCopyMutator);
impl_libafl_mutation!(BytesInsertMutator);
impl_libafl_mutation!(BytesRandInsertMutator);
impl_libafl_mutation!(BytesRandSetMutator);
impl_libafl_mutation!(BytesSetMutator);
impl_libafl_mutation!(BytesSwapMutator);
impl_libafl_mutation!(DwordAddMutator);
impl_libafl_mutation!(DwordInterestingMutator);
impl_libafl_mutation!(QwordAddMutator);
impl_libafl_mutation!(WordAddMutator);
impl_libafl_mutation!(WordInterestingMutator);
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CrossoverInsertMutator {
corpus_name: String,
}
impl CrossoverInsertMutator {
#[must_use]
pub fn new(corpus_name: &str) -> Self {
Self {
corpus_name: corpus_name.to_owned(),
}
}
}
impl Mutator for CrossoverInsertMutator {
#[instrument(skip_all, fields(%self.corpus_name), level = "trace")]
fn mutate(&mut self, input: &mut Data, state: &mut SharedState) -> Result<(), FeroxFuzzError> {
let corpus = state.corpus_by_name(&self.corpus_name)?;
let size = input.bytes().len();
let count = corpus.len();
let random_index = state.rand_mut().below(count as u64) as usize;
let scheduled_idx = state.corpus_index_by_name(&self.corpus_name)?;
if random_index == atomic_load!(scheduled_idx) {
return Ok(());
}
if let Ok(guard) = corpus.read() {
let result = guard.get(random_index);
if result.is_none() {
error!(name=guard.name(), index=%random_index, "corpus entry not found");
return Err(FeroxFuzzError::CorpusEntryNotFound {
name: guard.name().to_string(),
index: random_index,
});
}
let other_entry = result.unwrap();
let other_size = other_entry.as_bytes().len();
if other_size < 2 {
return Ok(());
}
let max_size = state.max_size();
let from = state.rand_mut().below(other_size as u64) as usize;
let to = state.rand_mut().below(size as u64) as usize;
let mut len = 1 + state.rand_mut().below((other_size - from) as u64) as usize;
if size + len > max_size {
if max_size > size {
len = max_size - size;
} else {
debug!(%size, %max_size, "exceeded maximum size; skipping mutation");
return Ok(());
}
}
input.bytes_mut().resize(size + len, 0);
buffer_self_copy(input.bytes_mut(), to, to + len, size - to);
buffer_copy(input.bytes_mut(), other_entry.as_bytes(), from, to, len);
}
Ok(())
}
}
impl Named for CrossoverInsertMutator {
fn name(&self) -> &str {
"CrossoverInsertMutator"
}
}
impl AsAny for CrossoverInsertMutator {
fn as_any(&self) -> &dyn Any {
self
}
}
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CrossoverReplaceMutator {
corpus_name: String,
}
impl CrossoverReplaceMutator {
#[must_use]
pub fn new(corpus_name: &str) -> Self {
Self {
corpus_name: corpus_name.to_owned(),
}
}
}
impl Mutator for CrossoverReplaceMutator {
#[instrument(skip_all, fields(%self.corpus_name), level = "trace")]
fn mutate(&mut self, input: &mut Data, state: &mut SharedState) -> Result<(), FeroxFuzzError> {
let size = input.bytes().len();
if size == 0 {
return Ok(());
}
let corpus = state.corpus_by_name(&self.corpus_name)?;
let count = corpus.len();
let random_index = state.rand_mut().below(count as u64) as usize;
let scheduled_idx = state.corpus_index_by_name(&self.corpus_name)?;
if random_index == atomic_load!(scheduled_idx) {
return Ok(());
}
if let Ok(guard) = corpus.read() {
let result = guard.get(random_index);
if result.is_none() {
error!(name=guard.name(), index=%random_index, "corpus entry not found");
return Err(FeroxFuzzError::CorpusEntryNotFound {
name: guard.name().to_string(),
index: random_index,
});
}
let other_entry = result.unwrap();
let other_size = other_entry.as_bytes().len();
if other_size < 2 {
return Ok(());
}
let from = state.rand_mut().below(other_size as u64) as usize;
let len = state.rand_mut().below(min(other_size - from, size) as u64) as usize;
let to = state.rand_mut().below((size - len) as u64) as usize;
buffer_copy(input.bytes_mut(), other_entry.as_bytes(), from, to, len);
}
Ok(())
}
}
impl Named for CrossoverReplaceMutator {
fn name(&self) -> &str {
"CrossoverReplaceMutator"
}
}
impl AsAny for CrossoverReplaceMutator {
fn as_any(&self) -> &dyn Any {
self
}
}
#[cfg(feature = "serde")]
struct LibAflMutatorVisitor<K, V> {
_k: PhantomData<K>,
_v: PhantomData<V>,
}
#[cfg(feature = "serde")]
impl<K, V> LibAflMutatorVisitor<K, V> {
const fn new() -> Self {
Self {
_k: PhantomData,
_v: PhantomData,
}
}
}
#[cfg(feature = "serde")]
impl<'de> Visitor<'de> for LibAflMutatorVisitor<String, String> {
type Value = LibAflMutator;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a LibAflMutator")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
if let Some((key, value)) = map.next_entry::<String, String>()? {
return match key.as_str() {
"BitFlipMutator" => Ok(LibAflMutator::BitFlipMutator(BitFlipMutator::new())),
"ByteAddMutator" => Ok(LibAflMutator::ByteAddMutator(ByteAddMutator::new())),
"ByteDecMutator" => Ok(LibAflMutator::ByteDecMutator(ByteDecMutator::new())),
"ByteFlipMutator" => Ok(LibAflMutator::ByteFlipMutator(ByteFlipMutator::new())),
"ByteIncMutator" => Ok(LibAflMutator::ByteIncMutator(ByteIncMutator::new())),
"ByteInterestingMutator" => Ok(LibAflMutator::ByteInterestingMutator(
ByteInterestingMutator::new(),
)),
"ByteNegMutator" => Ok(LibAflMutator::ByteNegMutator(ByteNegMutator::new())),
"ByteRandMutator" => Ok(LibAflMutator::ByteRandMutator(ByteRandMutator::new())),
"BytesCopyMutator" => Ok(LibAflMutator::BytesCopyMutator(BytesCopyMutator::new())),
"BytesDeleteMutator" => {
Ok(LibAflMutator::BytesDeleteMutator(BytesDeleteMutator::new()))
}
"BytesExpandMutator" => {
Ok(LibAflMutator::BytesExpandMutator(BytesExpandMutator::new()))
}
"BytesInsertCopyMutator" => Ok(LibAflMutator::BytesInsertCopyMutator(
BytesInsertCopyMutator::new(),
)),
"BytesInsertMutator" => {
Ok(LibAflMutator::BytesInsertMutator(BytesInsertMutator::new()))
}
"BytesRandInsertMutator" => Ok(LibAflMutator::BytesRandInsertMutator(
BytesRandInsertMutator::new(),
)),
"BytesRandSetMutator" => Ok(LibAflMutator::BytesRandSetMutator(
BytesRandSetMutator::new(),
)),
"BytesSetMutator" => Ok(LibAflMutator::BytesSetMutator(BytesSetMutator::new())),
"BytesSwapMutator" => Ok(LibAflMutator::BytesSwapMutator(BytesSwapMutator::new())),
"CrossoverInsertMutator" => Ok(LibAflMutator::CrossoverInsertMutator(
CrossoverInsertMutator::new(&value),
)),
"CrossoverReplaceMutator" => Ok(LibAflMutator::CrossoverReplaceMutator(
CrossoverReplaceMutator::new(&value),
)),
"DwordAddMutator" => Ok(LibAflMutator::DwordAddMutator(DwordAddMutator::new())),
"DwordInterestingMutator" => Ok(LibAflMutator::DwordInterestingMutator(
DwordInterestingMutator::new(),
)),
"QwordAddMutator" => Ok(LibAflMutator::QwordAddMutator(QwordAddMutator::new())),
"WordAddMutator" => Ok(LibAflMutator::WordAddMutator(WordAddMutator::new())),
"WordInterestingMutator" => Ok(LibAflMutator::WordInterestingMutator(
WordInterestingMutator::new(),
)),
_ => Err(de::Error::custom(format!(
"unknown LibAflMutator variant: {}:{}",
key, value
))),
};
}
Err(de::Error::custom("unknown LibAflMutator variant"))
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for LibAflMutator {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let mutator = deserializer.deserialize_any(LibAflMutatorVisitor::<String, String>::new())?;
Ok(mutator)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_de_ser_smoke_test() {
let mutators = &[
LibAflMutator::BitFlipMutator(BitFlipMutator::new()),
LibAflMutator::ByteAddMutator(ByteAddMutator::new()),
LibAflMutator::ByteDecMutator(ByteDecMutator::new()),
LibAflMutator::ByteFlipMutator(ByteFlipMutator::new()),
LibAflMutator::ByteIncMutator(ByteIncMutator::new()),
LibAflMutator::ByteInterestingMutator(ByteInterestingMutator::new()),
LibAflMutator::ByteNegMutator(ByteNegMutator::new()),
LibAflMutator::ByteRandMutator(ByteRandMutator::new()),
LibAflMutator::BytesCopyMutator(BytesCopyMutator::new()),
LibAflMutator::BytesDeleteMutator(BytesDeleteMutator::new()),
LibAflMutator::BytesExpandMutator(BytesExpandMutator::new()),
LibAflMutator::BytesInsertCopyMutator(BytesInsertCopyMutator::new()),
LibAflMutator::BytesInsertMutator(BytesInsertMutator::new()),
LibAflMutator::BytesRandInsertMutator(BytesRandInsertMutator::new()),
LibAflMutator::BytesRandSetMutator(BytesRandSetMutator::new()),
LibAflMutator::BytesSetMutator(BytesSetMutator::new()),
LibAflMutator::BytesSwapMutator(BytesSwapMutator::new()),
LibAflMutator::DwordAddMutator(DwordAddMutator::new()),
LibAflMutator::DwordInterestingMutator(DwordInterestingMutator::new()),
LibAflMutator::QwordAddMutator(QwordAddMutator::new()),
LibAflMutator::WordAddMutator(WordAddMutator::new()),
LibAflMutator::WordInterestingMutator(WordInterestingMutator::new()),
];
for mutator in mutators {
let serialized = serde_json::to_string(&mutator).unwrap();
let _deserialized: LibAflMutator = serde_json::from_str(&serialized).unwrap();
}
}
}