Rename ResizableMutator, make it generic (#2859)

* Rename ResizableMutator, make it generic

* fix

* more fix

* reorer

* fmt, fixes

* fixes

* more commit

* fmt
This commit is contained in:
Dominik Maier 2025-01-19 17:17:50 +00:00 committed by GitHub
parent 2a36b78fd6
commit a949452453
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 285 additions and 226 deletions

View File

@ -11,7 +11,7 @@ use core::cell::RefCell;
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
use super::ValueInput;
use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes, HasTargetBytes};
use crate::inputs::{HasMutatorBytes, HasTargetBytes, ResizableMutator};
/// A bytes input is the basic input
pub type BytesInput = ValueInput<Vec<u8>>;
@ -24,16 +24,16 @@ impl From<BytesInput> for Rc<RefCell<BytesInput>> {
}
impl HasMutatorBytes for BytesInput {
fn bytes(&self) -> &[u8] {
fn mutator_bytes(&self) -> &[u8] {
self.as_ref()
}
fn bytes_mut(&mut self) -> &mut [u8] {
fn mutator_bytes_mut(&mut self) -> &mut [u8] {
self.as_mut()
}
}
impl HasMutatorResizableBytes for BytesInput {
impl ResizableMutator<u8> for BytesInput {
fn resize(&mut self, new_len: usize, value: u8) {
self.as_mut().resize(new_len, value);
}

View File

@ -11,7 +11,7 @@ use libafl_bolts::{
HasLen,
};
use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes};
use crate::inputs::{HasMutatorBytes, ResizableMutator};
/// The [`BytesSubInput`] makes it possible to use [`crate::mutators::Mutator`]`s` that work on
/// inputs implementing the [`HasMutatorBytes`] for a sub-range of this input.
@ -31,13 +31,13 @@ use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes};
/// let mut sub_input = bytes_input.sub_input(1..);
///
/// // Run any mutations on the sub input.
/// sub_input.bytes_mut()[0] = 42;
/// sub_input.mutator_bytes_mut()[0] = 42;
///
/// // The mutations are applied to the underlying input.
/// assert_eq!(bytes_input.bytes()[1], 42);
/// assert_eq!(bytes_input.mutator_bytes()[1], 42);
/// ```
///
/// If inputs implement the [`HasMutatorResizableBytes`] trait, growing or shrinking the sub input
/// If inputs implement the [`ResizableMutator`] trait, growing or shrinking the sub input
/// will grow or shrink the parent input,
/// and keep elements around the current range untouched / move them accordingly.
///
@ -45,7 +45,7 @@ use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes};
/// ```rust
/// # extern crate alloc;
/// # extern crate libafl;
/// # use libafl::inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes};
/// # use libafl::inputs::{BytesInput, HasMutatorBytes, ResizableMutator};
/// # use alloc::vec::Vec;
/// #
/// # #[cfg(not(feature = "std"))]
@ -57,13 +57,13 @@ use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes};
/// // Note that the range ends on an exclusive value this time.
/// let mut sub_input = bytes_input.sub_input(1..=3);
///
/// assert_eq!(sub_input.bytes(), &[2, 3, 4]);
/// assert_eq!(sub_input.mutator_bytes(), &[2, 3, 4]);
///
/// // We extend it with a few values.
/// sub_input.extend(&[42, 42, 42]);
///
/// // The values outside of the range are moved back and forwards, accordingly.
/// assert_eq!(bytes_input.bytes(), [1, 2, 3, 4, 42, 42, 42, 5]);
/// assert_eq!(bytes_input.mutator_bytes(), [1, 2, 3, 4, 42, 42, 42, 5]);
/// ```
///
/// The input supports all methods in the [`HasMutatorBytes`] trait if the parent input also implements this trait.
@ -102,19 +102,19 @@ where
I: HasMutatorBytes,
{
#[inline]
fn bytes(&self) -> &[u8] {
&self.parent_input.bytes()[self.range.clone()]
fn mutator_bytes(&self) -> &[u8] {
&self.parent_input.mutator_bytes()[self.range.clone()]
}
#[inline]
fn bytes_mut(&mut self) -> &mut [u8] {
&mut self.parent_input.bytes_mut()[self.range.clone()]
fn mutator_bytes_mut(&mut self) -> &mut [u8] {
&mut self.parent_input.mutator_bytes_mut()[self.range.clone()]
}
}
impl<I> HasMutatorResizableBytes for BytesSubInput<'_, I>
impl<I> ResizableMutator<u8> for BytesSubInput<'_, I>
where
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes + HasLen,
{
fn resize(&mut self, new_len: usize, value: u8) {
let start_index = self.range.start;
@ -134,7 +134,7 @@ where
if old_parent_len > end_index {
// the parent has a reminder, move it back.
let parent_bytes = self.parent_input.bytes_mut();
let parent_bytes = self.parent_input.mutator_bytes_mut();
// move right
let (_, rest) = parent_bytes.split_at_mut(start_index + old_len);
@ -151,7 +151,7 @@ where
// We shrink. Remove the values, then remove the underlying buffer.
let diff = old_len - new_len;
let parent_bytes = self.parent_input.bytes_mut();
let parent_bytes = self.parent_input.mutator_bytes_mut();
// move left
let (_, rest) = parent_bytes.split_at_mut(start_index + new_len);
@ -171,7 +171,7 @@ where
let new_values: Vec<u8> = iter.into_iter().copied().collect();
self.resize(old_len + new_values.len(), 0);
self.bytes_mut()[old_len..].copy_from_slice(&new_values);
self.mutator_bytes_mut()[old_len..].copy_from_slice(&new_values);
}
/// Creates a splicing iterator that replaces the specified range in the vector
@ -214,7 +214,7 @@ mod tests {
use libafl_bolts::HasLen;
use crate::{
inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes, NopInput},
inputs::{BytesInput, HasMutatorBytes, NopInput, ResizableMutator},
mutators::{havoc_mutations_no_crossover, MutatorsTuple},
state::NopState,
};
@ -245,19 +245,19 @@ mod tests {
let mut sub_input = bytes_input.sub_input(0..1);
assert_eq!(sub_input.len(), 1);
sub_input.bytes_mut()[0] = 2;
assert_eq!(bytes_input.bytes()[0], 2);
sub_input.mutator_bytes_mut()[0] = 2;
assert_eq!(bytes_input.mutator_bytes()[0], 2);
let mut sub_input = bytes_input.sub_input(1..=2);
assert_eq!(sub_input.len(), 2);
sub_input.bytes_mut()[0] = 3;
assert_eq!(bytes_input.bytes()[1], 3);
sub_input.mutator_bytes_mut()[0] = 3;
assert_eq!(bytes_input.mutator_bytes()[1], 3);
let mut sub_input = bytes_input.sub_input(..);
assert_eq!(sub_input.len(), len_orig);
sub_input.bytes_mut()[0] = 1;
sub_input.bytes_mut()[1] = 2;
assert_eq!(bytes_input.bytes()[0], 1);
sub_input.mutator_bytes_mut()[0] = 1;
sub_input.mutator_bytes_mut()[1] = 2;
assert_eq!(bytes_input.mutator_bytes()[0], 1);
}
#[test]
@ -268,10 +268,10 @@ mod tests {
let mut sub_input = bytes_input.sub_input(2..);
assert_eq!(sub_input.len(), len_orig - 2);
sub_input.resize(len_orig, 0);
assert_eq!(sub_input.bytes()[sub_input.len() - 1], 0);
assert_eq!(sub_input.mutator_bytes()[sub_input.len() - 1], 0);
assert_eq!(sub_input.len(), len_orig);
assert_eq!(bytes_input.len(), len_orig + 2);
assert_eq!(bytes_input.bytes()[bytes_input.len() - 1], 0);
assert_eq!(bytes_input.mutator_bytes()[bytes_input.len() - 1], 0);
let (mut bytes_input, len_orig) = init_bytes_input();
@ -279,7 +279,7 @@ mod tests {
assert_eq!(sub_input.len(), 2);
sub_input.resize(3, 0);
assert_eq!(sub_input.len(), 3);
assert_eq!(sub_input.bytes()[sub_input.len() - 1], 0);
assert_eq!(sub_input.mutator_bytes()[sub_input.len() - 1], 0);
assert_eq!(bytes_input.len(), len_orig + 1);
let mut sub_input = bytes_input.sub_input(..3);
@ -300,7 +300,7 @@ mod tests {
sub_input.resize(10, 0);
assert_eq!(sub_input.len(), 10);
assert_eq!(bytes_input.len(), 10);
assert_eq!(bytes_input.bytes()[2], 0);
assert_eq!(bytes_input.mutator_bytes()[2], 0);
let mut sub_input = bytes_input.sub_input(..);
sub_input.resize(1, 0);

View File

@ -158,17 +158,17 @@ pub trait HasTargetBytes {
/// Contains mutable bytes
pub trait HasMutatorBytes: HasLen {
/// The bytes
fn bytes(&self) -> &[u8];
fn mutator_bytes(&self) -> &[u8];
/// The bytes to mutate
fn bytes_mut(&mut self) -> &mut [u8];
fn mutator_bytes_mut(&mut self) -> &mut [u8];
/// Creates a [`SubRangeSlice`] from this input, that can be used to slice a byte array.
fn sub_bytes<R>(&self, range: R) -> SubRangeSlice<u8>
where
R: RangeBounds<usize>,
{
SubRangeSlice::new(OwnedSlice::from(self.bytes()), range)
SubRangeSlice::new(OwnedSlice::from(self.mutator_bytes()), range)
}
/// Creates a [`SubRangeMutSlice`] from this input, that can be used to slice a byte array.
@ -176,7 +176,7 @@ pub trait HasMutatorBytes: HasLen {
where
R: RangeBounds<usize>,
{
SubRangeMutSlice::new(OwnedMutSlice::from(self.bytes_mut()), range)
SubRangeMutSlice::new(OwnedMutSlice::from(self.mutator_bytes_mut()), range)
}
/// Creates a [`BytesSubInput`] from this input, that can be used for local mutations.
@ -189,11 +189,11 @@ pub trait HasMutatorBytes: HasLen {
}
impl HasMutatorBytes for Vec<u8> {
fn bytes(&self) -> &[u8] {
fn mutator_bytes(&self) -> &[u8] {
self.as_ref()
}
fn bytes_mut(&mut self) -> &mut [u8] {
fn mutator_bytes_mut(&mut self) -> &mut [u8] {
self.as_mut()
}
}
@ -203,63 +203,68 @@ impl HasMutatorBytes for Vec<u8> {
pub type MutVecInput<'a> = &'a mut Vec<u8>;
impl HasMutatorBytes for &'_ mut Vec<u8> {
fn bytes(&self) -> &[u8] {
fn mutator_bytes(&self) -> &[u8] {
self
}
fn bytes_mut(&mut self) -> &mut [u8] {
fn mutator_bytes_mut(&mut self) -> &mut [u8] {
self
}
}
/// Contains mutable and resizable bytes
pub trait HasMutatorResizableBytes: HasMutatorBytes {
/// Resize the mutator bytes to a given new size.
/// Contains resizable bytes
pub trait ResizableMutator<T> {
/// Resize the mutator content to a given new size.
/// Use `value` to fill new slots in case the buffer grows.
/// See [`Vec::splice`].
fn resize(&mut self, new_len: usize, value: u8);
fn resize(&mut self, new_len: usize, value: T);
/// Extends the given buffer with an iterator. See [`alloc::vec::Vec::extend`]
fn extend<'a, I: IntoIterator<Item = &'a u8>>(&mut self, iter: I);
fn extend<'a, I: IntoIterator<Item = &'a T>>(&mut self, iter: I)
where
T: 'a;
/// Splices the given target bytes according to [`Vec::splice`]'s rules
/// Splices the given target values according to [`Vec::splice`]'s rules
fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = u8>;
I: IntoIterator<Item = T>;
/// Drains the given target bytes according to [`Vec::drain`]'s rules
fn drain<R>(&mut self, range: R) -> Drain<'_, u8>
/// Drains the given target value according to [`Vec::drain`]'s rules
fn drain<R>(&mut self, range: R) -> Drain<'_, T>
where
R: RangeBounds<usize>;
}
impl HasMutatorResizableBytes for Vec<u8> {
fn resize(&mut self, new_len: usize, value: u8) {
<Vec<u8>>::resize(self, new_len, value);
impl<T> ResizableMutator<T> for Vec<T>
where
T: Copy + 'static,
{
fn resize(&mut self, new_len: usize, value: T) {
<Vec<T>>::resize(self, new_len, value);
}
fn extend<'a, I: IntoIterator<Item = &'a u8>>(&mut self, iter: I) {
<Vec<u8> as Extend<I::Item>>::extend(self, iter);
fn extend<'a, I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
<Vec<T> as Extend<I::Item>>::extend(self, iter);
}
fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = u8>,
I: IntoIterator<Item = T>,
{
<Vec<u8>>::splice(self, range, replace_with)
<Vec<T>>::splice(self, range, replace_with)
}
fn drain<R>(&mut self, range: R) -> Drain<'_, u8>
fn drain<R>(&mut self, range: R) -> Drain<'_, T>
where
R: RangeBounds<usize>,
{
<Vec<u8>>::drain(self, range)
<Vec<T>>::drain(self, range)
}
}
impl HasMutatorResizableBytes for &mut Vec<u8> {
impl ResizableMutator<u8> for &mut Vec<u8> {
fn resize(&mut self, new_len: usize, value: u8) {
self.deref_mut().resize(new_len, value);
}

View File

@ -10,7 +10,7 @@ use libafl_bolts::{rands::Rand, Error};
use crate::{
corpus::{Corpus, CorpusId},
impl_default_multipart,
inputs::{multi::MultipartInput, HasMutatorResizableBytes, Input},
inputs::{multi::MultipartInput, HasMutatorBytes, Input, ResizableMutator},
mutators::{
mutations::{
rand_range, BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator,
@ -119,7 +119,7 @@ impl_default_multipart!(
impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverInsertMutator
where
S: HasCorpus<MultipartInput<I>> + HasMaxSize + HasRand,
I: Input + HasMutatorResizableBytes,
I: Input + ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(
&mut self,
@ -140,7 +140,7 @@ where
let choice = name_choice % input.names().len();
let name = input.names()[choice].clone();
let other_size = input.parts()[choice].bytes().len();
let other_size = input.parts()[choice].mutator_bytes().len();
if other_size < 2 {
return Ok(MutationResult::Skipped);
}
@ -155,7 +155,7 @@ where
.parts_by_name(&name)
.filter(|&(p, _)| p != choice)
.nth(part_choice % parts)
.map(|(id, part)| (id, part.bytes().len()));
.map(|(id, part)| (id, part.mutator_bytes().len()));
if let Some((part_idx, size)) = maybe_size {
let Some(nz) = NonZero::new(size) else {
@ -186,7 +186,7 @@ where
size,
target,
range,
chosen.bytes(),
chosen.mutator_bytes(),
));
}
@ -204,7 +204,7 @@ where
let choice = name_choice % other.names().len();
let name = &other.names()[choice];
let other_size = other.parts()[choice].bytes().len();
let other_size = other.parts()[choice].mutator_bytes().len();
if other_size < 2 {
return Ok(MutationResult::Skipped);
}
@ -217,7 +217,7 @@ where
.nth(part_choice % parts)
.unwrap();
drop(other_testcase);
let size = part.bytes().len();
let size = part.mutator_bytes().len();
let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
@ -240,7 +240,7 @@ where
size,
target,
range,
other.parts()[choice].bytes(),
other.parts()[choice].mutator_bytes(),
))
} else {
// just add it!
@ -254,7 +254,7 @@ where
impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverReplaceMutator
where
S: HasCorpus<MultipartInput<I>> + HasMaxSize + HasRand,
I: Input + HasMutatorResizableBytes,
I: Input + ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(
&mut self,
@ -275,7 +275,7 @@ where
let choice = name_choice % input.names().len();
let name = input.names()[choice].clone();
let other_size = input.parts()[choice].bytes().len();
let other_size = input.parts()[choice].mutator_bytes().len();
if other_size < 2 {
return Ok(MutationResult::Skipped);
}
@ -290,7 +290,7 @@ where
.parts_by_name(&name)
.filter(|&(p, _)| p != choice)
.nth(part_choice % parts)
.map(|(id, part)| (id, part.bytes().len()));
.map(|(id, part)| (id, part.mutator_bytes().len()));
if let Some((part_idx, size)) = maybe_size {
let Some(nz) = NonZero::new(size) else {
@ -316,7 +316,12 @@ where
}
};
return Ok(Self::crossover_replace(part, target, range, chosen.bytes()));
return Ok(Self::crossover_replace(
part,
target,
range,
chosen.mutator_bytes(),
));
}
return Ok(MutationResult::Skipped);
@ -333,7 +338,7 @@ where
let choice = name_choice % other.names().len();
let name = &other.names()[choice];
let other_size = other.parts()[choice].bytes().len();
let other_size = other.parts()[choice].mutator_bytes().len();
if other_size < 2 {
return Ok(MutationResult::Skipped);
}
@ -346,7 +351,7 @@ where
.nth(part_choice % parts)
.unwrap();
drop(other_testcase);
let size = part.bytes().len();
let size = part.mutator_bytes().len();
let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
@ -367,7 +372,7 @@ where
part,
target,
range,
other.parts()[choice].bytes(),
other.parts()[choice].mutator_bytes(),
))
} else {
// just add it!

View File

@ -16,7 +16,7 @@ use libafl_bolts::{rands::Rand, Named};
use crate::{
corpus::Corpus,
inputs::{HasMutatorBytes, HasMutatorResizableBytes},
inputs::{HasMutatorBytes, ResizableMutator},
mutators::{MutationResult, Mutator},
nonzero, random_corpus_id_with_disabled,
state::{HasCorpus, HasMaxSize, HasRand},
@ -132,11 +132,11 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
if input.bytes().is_empty() {
if input.mutator_bytes().is_empty() {
Ok(MutationResult::Skipped)
} else {
let bit = 1 << state.rand_mut().choose(0..8).unwrap();
let byte = state.rand_mut().choose(input.bytes_mut()).unwrap();
let byte = state.rand_mut().choose(input.mutator_bytes_mut()).unwrap();
*byte ^= bit;
Ok(MutationResult::Mutated)
}
@ -168,10 +168,10 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
if input.bytes().is_empty() {
if input.mutator_bytes().is_empty() {
Ok(MutationResult::Skipped)
} else {
*state.rand_mut().choose(input.bytes_mut()).unwrap() ^= 0xff;
*state.rand_mut().choose(input.mutator_bytes_mut()).unwrap() ^= 0xff;
Ok(MutationResult::Mutated)
}
}
@ -202,10 +202,10 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
if input.bytes().is_empty() {
if input.mutator_bytes().is_empty() {
Ok(MutationResult::Skipped)
} else {
let byte = state.rand_mut().choose(input.bytes_mut()).unwrap();
let byte = state.rand_mut().choose(input.mutator_bytes_mut()).unwrap();
*byte = byte.wrapping_add(1);
Ok(MutationResult::Mutated)
}
@ -237,10 +237,10 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
if input.bytes().is_empty() {
if input.mutator_bytes().is_empty() {
Ok(MutationResult::Skipped)
} else {
let byte = state.rand_mut().choose(input.bytes_mut()).unwrap();
let byte = state.rand_mut().choose(input.mutator_bytes_mut()).unwrap();
*byte = byte.wrapping_sub(1);
Ok(MutationResult::Mutated)
}
@ -272,10 +272,10 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
if input.bytes().is_empty() {
if input.mutator_bytes().is_empty() {
Ok(MutationResult::Skipped)
} else {
let byte = state.rand_mut().choose(input.bytes_mut()).unwrap();
let byte = state.rand_mut().choose(input.mutator_bytes_mut()).unwrap();
*byte = (!(*byte)).wrapping_add(1);
Ok(MutationResult::Mutated)
}
@ -307,10 +307,10 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
if input.bytes().is_empty() {
if input.mutator_bytes().is_empty() {
Ok(MutationResult::Skipped)
} else {
let byte = state.rand_mut().choose(input.bytes_mut()).unwrap();
let byte = state.rand_mut().choose(input.mutator_bytes_mut()).unwrap();
*byte ^= 1 + state.rand_mut().below(nonzero!(254)) as u8;
Ok(MutationResult::Mutated)
}
@ -352,13 +352,13 @@ macro_rules! add_mutator_impl {
input: &mut I,
) -> Result<MutationResult, Error> {
if input.bytes().len() < size_of::<$size>() {
if input.mutator_bytes().len() < size_of::<$size>() {
Ok(MutationResult::Skipped)
} else {
// choose a random window of bytes (windows overlap) and convert to $size
let (index, bytes) = state
.rand_mut()
.choose(input.bytes().windows(size_of::<$size>()).enumerate()).unwrap();
.choose(input.mutator_bytes().windows(size_of::<$size>()).enumerate()).unwrap();
let val = <$size>::from_ne_bytes(bytes.try_into().unwrap());
// mutate
@ -371,7 +371,7 @@ macro_rules! add_mutator_impl {
};
// set bytes to mutated value
let new_bytes = &mut input.bytes_mut()[index..index + size_of::<$size>()];
let new_bytes = &mut input.mutator_bytes_mut()[index..index + size_of::<$size>()];
new_bytes.copy_from_slice(&new_val.to_ne_bytes());
Ok(MutationResult::Mutated)
}
@ -415,10 +415,10 @@ macro_rules! interesting_mutator_impl {
{
#[expect(clippy::cast_sign_loss)]
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
if input.bytes().len() < size_of::<$size>() {
if input.mutator_bytes().len() < size_of::<$size>() {
Ok(MutationResult::Skipped)
} else {
let bytes = input.bytes_mut();
let bytes = input.mutator_bytes_mut();
let upper_bound = (bytes.len() + 1 - size_of::<$size>());
// # Safety
// the length is at least as large as the size here (checked above), and we add a 1 -> never zero.
@ -464,10 +464,10 @@ pub struct BytesDeleteMutator;
impl<I, S> Mutator<I, S> for BytesDeleteMutator
where
S: HasRand,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size <= 2 {
return Ok(MutationResult::Skipped);
}
@ -506,11 +506,11 @@ pub struct BytesExpandMutator;
impl<I, S> Mutator<I, S> for BytesExpandMutator
where
S: HasRand + HasMaxSize,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let max_size = state.max_size();
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size == 0 || size >= max_size {
return Ok(MutationResult::Skipped);
}
@ -524,7 +524,7 @@ where
input.resize(size + range.len(), 0);
unsafe {
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
range.start,
range.start + range.len(),
size - range.start,
@ -557,11 +557,11 @@ pub struct BytesInsertMutator;
impl<I, S> Mutator<I, S> for BytesInsertMutator
where
S: HasRand + HasMaxSize,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let max_size = state.max_size();
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size == 0 || size >= max_size {
return Ok(MutationResult::Skipped);
}
@ -584,15 +584,20 @@ where
// # Safety
// size is larger than 0, checked above.
let val = input.bytes()[state
let val = input.mutator_bytes()[state
.rand_mut()
.below(unsafe { NonZero::new(size).unwrap_unchecked() })];
input.resize(size + amount, 0);
unsafe {
buffer_self_copy(input.bytes_mut(), offset, offset + amount, size - offset);
buffer_self_copy(
input.mutator_bytes_mut(),
offset,
offset + amount,
size - offset,
);
}
buffer_set(input.bytes_mut(), offset, amount, val);
buffer_set(input.mutator_bytes_mut(), offset, amount, val);
Ok(MutationResult::Mutated)
}
@ -620,11 +625,11 @@ pub struct BytesRandInsertMutator;
impl<I, S> Mutator<I, S> for BytesRandInsertMutator
where
S: HasRand + HasMaxSize,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let max_size = state.max_size();
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size >= max_size {
return Ok(MutationResult::Skipped);
}
@ -648,9 +653,14 @@ where
input.resize(size + amount, 0);
unsafe {
buffer_self_copy(input.bytes_mut(), offset, offset + amount, size - offset);
buffer_self_copy(
input.mutator_bytes_mut(),
offset,
offset + amount,
size - offset,
);
}
buffer_set(input.bytes_mut(), offset, amount, val);
buffer_set(input.mutator_bytes_mut(), offset, amount, val);
Ok(MutationResult::Mutated)
}
@ -681,7 +691,7 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size == 0 {
return Ok(MutationResult::Skipped);
}
@ -691,9 +701,9 @@ where
NonZero::new(min(size, 16)).unwrap_unchecked()
});
let val = *state.rand_mut().choose(input.bytes()).unwrap();
let val = *state.rand_mut().choose(input.mutator_bytes()).unwrap();
let quantity = range.len();
buffer_set(input.bytes_mut(), range.start, quantity, val);
buffer_set(input.mutator_bytes_mut(), range.start, quantity, val);
Ok(MutationResult::Mutated)
}
@ -724,7 +734,7 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size == 0 {
return Ok(MutationResult::Skipped);
}
@ -736,7 +746,7 @@ where
let val = state.rand_mut().next() as u8;
let quantity = range.len();
buffer_set(input.bytes_mut(), range.start, quantity, val);
buffer_set(input.mutator_bytes_mut(), range.start, quantity, val);
Ok(MutationResult::Mutated)
}
@ -767,7 +777,7 @@ where
I: HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size <= 1 {
return Ok(MutationResult::Skipped);
}
@ -784,7 +794,7 @@ where
});
unsafe {
buffer_self_copy(input.bytes_mut(), range.start, target, range.len());
buffer_self_copy(input.mutator_bytes_mut(), range.start, target, range.len());
}
Ok(MutationResult::Mutated)
@ -815,10 +825,10 @@ pub struct BytesInsertCopyMutator {
impl<I, S> Mutator<I, S> for BytesInsertCopyMutator
where
S: HasRand + HasMaxSize,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size <= 1 || size >= state.max_size() {
return Ok(MutationResult::Skipped);
}
@ -843,19 +853,25 @@ where
unsafe {
buffer_copy(
&mut self.tmp_buf,
input.bytes(),
input.mutator_bytes(),
range.start,
0,
range.len(),
);
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
target,
target + range.len(),
size - target,
);
buffer_copy(input.bytes_mut(), &self.tmp_buf, 0, target, range.len());
buffer_copy(
input.mutator_bytes_mut(),
&self.tmp_buf,
0,
target,
range.len(),
);
}
Ok(MutationResult::Mutated)
}
@ -886,10 +902,10 @@ pub struct BytesSwapMutator {
impl<I, S> Mutator<I, S> for BytesSwapMutator
where
S: HasRand,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size <= 1 {
return Ok(MutationResult::Skipped);
}
@ -916,7 +932,7 @@ where
// copy first range to tmp
buffer_copy(
&mut self.tmp_buf,
input.bytes(),
input.mutator_bytes(),
first.start,
0,
first.len(),
@ -924,7 +940,7 @@ where
// adjust second.end..first.start, move them by diff_in_size to the right
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
second.end,
second.end + diff_in_size,
first.start - second.end,
@ -932,7 +948,7 @@ where
// copy second to where first was
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
second.start,
first.start + diff_in_size,
second.len(),
@ -940,7 +956,7 @@ where
// copy first back
buffer_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
&self.tmp_buf,
0,
second.start,
@ -952,7 +968,7 @@ where
// copy first range to tmp
buffer_copy(
&mut self.tmp_buf,
input.bytes(),
input.mutator_bytes(),
first.start,
0,
first.len(),
@ -960,7 +976,7 @@ where
// adjust second.end..first.start, move them by diff_in_size to the left
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
second.end,
second.end - diff_in_size,
first.start - second.end,
@ -968,7 +984,7 @@ where
// copy second to where first was
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
second.start,
first.start - diff_in_size,
second.len(),
@ -976,7 +992,7 @@ where
// copy first back
buffer_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
&self.tmp_buf,
0,
second.start,
@ -1001,7 +1017,7 @@ where
// copy second range to tmp
buffer_copy(
&mut self.tmp_buf,
input.bytes(),
input.mutator_bytes(),
second.start,
0,
second.len(),
@ -1009,7 +1025,7 @@ where
// adjust first.end..second.start, move them by diff_in_size to the right
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
first.end,
first.end + diff_in_size,
second.start - first.end,
@ -1017,7 +1033,7 @@ where
// copy first to where second was
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
first.start,
second.start + diff_in_size,
first.len(),
@ -1025,7 +1041,7 @@ where
// copy second back
buffer_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
&self.tmp_buf,
0,
first.start,
@ -1036,7 +1052,7 @@ where
// copy second range to tmp
buffer_copy(
&mut self.tmp_buf,
input.bytes(),
input.mutator_bytes(),
second.start,
0,
second.len(),
@ -1044,7 +1060,7 @@ where
// adjust first.end..second.start, move them by diff_in_size to the left
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
first.end,
first.end - diff_in_size,
second.start - first.end,
@ -1052,7 +1068,7 @@ where
// copy first to where second was
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
first.start,
second.start - diff_in_size,
first.len(),
@ -1060,7 +1076,7 @@ where
// copy second back
buffer_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
&self.tmp_buf,
0,
first.start,
@ -1104,12 +1120,12 @@ impl CrossoverInsertMutator {
other: &[u8],
) -> MutationResult
where
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
input.resize(size + range.len(), 0);
unsafe {
buffer_self_copy(
input.bytes_mut(),
input.mutator_bytes_mut(),
target,
target + range.len(),
size - target,
@ -1117,7 +1133,13 @@ impl CrossoverInsertMutator {
}
unsafe {
buffer_copy(input.bytes_mut(), other, range.start, target, range.len());
buffer_copy(
input.mutator_bytes_mut(),
other,
range.start,
target,
range.len(),
);
}
MutationResult::Mutated
}
@ -1125,11 +1147,11 @@ impl CrossoverInsertMutator {
impl<I, S> Mutator<I, S> for CrossoverInsertMutator
where
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
S: HasCorpus<I> + HasRand + HasMaxSize,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
let Some(nonzero_size) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
@ -1149,7 +1171,10 @@ where
let other_size = {
let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
other_testcase.load_input(state.corpus())?.bytes().len()
other_testcase
.load_input(state.corpus())?
.mutator_bytes()
.len()
};
if other_size < 2 {
@ -1173,7 +1198,7 @@ where
size,
target,
range,
other.bytes(),
other.mutator_bytes(),
))
}
}
@ -1208,7 +1233,13 @@ impl CrossoverReplaceMutator {
I: HasMutatorBytes,
{
unsafe {
buffer_copy(input.bytes_mut(), other, range.start, target, range.len());
buffer_copy(
input.mutator_bytes_mut(),
other,
range.start,
target,
range.len(),
);
}
MutationResult::Mutated
}
@ -1220,7 +1251,7 @@ where
S: HasCorpus<I> + HasRand,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size == 0 {
return Ok(MutationResult::Skipped);
}
@ -1235,7 +1266,7 @@ where
let other_size = {
let mut testcase = state.corpus().get_from_all(id)?.borrow_mut();
testcase.load_input(state.corpus())?.bytes().len()
testcase.load_input(state.corpus())?.mutator_bytes().len()
};
if other_size < 2 {
@ -1258,7 +1289,12 @@ where
// No need to load the input again, it'll still be cached.
let other = other_testcase.input().as_ref().unwrap();
Ok(Self::crossover_replace(input, target, range, other.bytes()))
Ok(Self::crossover_replace(
input,
target,
range,
other.mutator_bytes(),
))
}
}
@ -1313,12 +1349,12 @@ impl<F, I, O> MappedCrossoverInsertMutator<F, I, O> {
impl<S, F, I1, I2, O> Mutator<I2, S> for MappedCrossoverInsertMutator<F, I1, O>
where
F: Fn(&I1) -> &O,
I2: HasMutatorResizableBytes,
I2: ResizableMutator<u8> + HasMutatorBytes,
O: IntoOptionBytes,
S: HasCorpus<I1> + HasMaxSize + HasRand,
{
fn mutate(&mut self, state: &mut S, input: &mut I2) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
let max_size = state.max_size();
// TODO: fix bug if size is 0 (?)
if size >= max_size || size == 0 {
@ -1407,7 +1443,7 @@ where
S: HasCorpus<I1> + HasMaxSize + HasRand,
{
fn mutate(&mut self, state: &mut S, input: &mut I2) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size == 0 {
return Ok(MutationResult::Skipped);
}
@ -1491,7 +1527,7 @@ pub struct SpliceMutator;
impl<I, S> Mutator<I, S> for SpliceMutator
where
S: HasCorpus<I> + HasRand,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
#[expect(clippy::cast_sign_loss)]
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
@ -1507,7 +1543,7 @@ where
let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
let other = other_testcase.load_input(state.corpus())?;
let (f, l) = locate_diffs(input.bytes(), other.bytes());
let (f, l) = locate_diffs(input.mutator_bytes(), other.mutator_bytes());
if f != l && f >= 0 && l >= 2 {
(f as usize, l as usize)
@ -1522,7 +1558,10 @@ where
// Input will already be loaded.
let other = other_testcase.input().as_ref().unwrap();
input.splice(split_at.., other.bytes()[split_at..].iter().copied());
input.splice(
split_at..,
other.mutator_bytes()[split_at..].iter().copied(),
);
Ok(MutationResult::Mutated)
}

View File

@ -352,10 +352,10 @@ mod tests {
let mut splice = SpliceMutator::new();
splice.mutate(&mut state, &mut input).unwrap();
log::trace!("{:?}", input.bytes());
log::trace!("{:?}", input.mutator_bytes());
// The pre-seeded rand should have spliced at position 2.
assert_eq!(input.bytes(), b"abf");
assert_eq!(input.mutator_bytes(), b"abf");
}
#[test]

View File

@ -25,13 +25,13 @@ use serde::{Deserialize, Serialize};
use crate::mutators::str_decode;
use crate::{
corpus::{CorpusId, HasCurrentCorpusId},
inputs::HasMutatorResizableBytes,
inputs::{HasMutatorBytes, ResizableMutator},
mutators::{
buffer_self_copy, mutations::buffer_copy, MultiMutator, MutationResult, Mutator, Named,
},
observers::cmp::{AFLppCmpValuesMetadata, CmpValues, CmpValuesMetadata},
stages::TaintMetadata,
state::{HasMaxSize, HasRand},
state::{HasCorpus, HasMaxSize, HasRand},
Error, HasMetadata,
};
@ -306,7 +306,7 @@ pub struct TokenInsert;
impl<I, S> Mutator<I, S> for TokenInsert
where
S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let max_size = state.max_size();
@ -322,7 +322,7 @@ where
};
let token_idx = state.rand_mut().below(tokens_len);
let size = input.bytes().len();
let size = input.mutator_bytes().len();
// # Safety
// after saturating add it's always above 0
@ -344,8 +344,8 @@ where
input.resize(size + len, 0);
unsafe {
buffer_self_copy(input.bytes_mut(), off, off + len, size - off);
buffer_copy(input.bytes_mut(), token, 0, off, len);
buffer_self_copy(input.mutator_bytes_mut(), off, off + len, size - off);
buffer_copy(input.mutator_bytes_mut(), token, 0, off, len);
}
Ok(MutationResult::Mutated)
@ -375,10 +375,10 @@ pub struct TokenReplace;
impl<I, S> Mutator<I, S> for TokenReplace
where
S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
let off = if let Some(nz) = NonZero::new(size) {
state.rand_mut().below(nz)
} else {
@ -405,7 +405,7 @@ where
}
unsafe {
buffer_copy(input.bytes_mut(), token, 0, off, len);
buffer_copy(input.mutator_bytes_mut(), token, 0, off, len);
}
Ok(MutationResult::Mutated)
@ -435,11 +435,11 @@ pub struct I2SRandReplace;
impl<I, S> Mutator<I, S> for I2SRandReplace
where
S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
#[expect(clippy::too_many_lines)]
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let size = input.mutator_bytes().len();
let Some(size) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
@ -459,8 +459,8 @@ where
let idx = state.rand_mut().below(cmps_len);
let off = state.rand_mut().below(size);
let len = input.bytes().len();
let bytes = input.bytes_mut();
let len = input.mutator_bytes().len();
let bytes = input.mutator_bytes_mut();
let meta = state.metadata_map().get::<CmpValuesMetadata>().unwrap();
let cmp_values = &meta.list[idx];
@ -571,9 +571,9 @@ where
'outer: for i in off..len {
let mut size = core::cmp::min(v.0.len(), len - i);
while size != 0 {
if v.0.as_slice()[0..size] == input.bytes()[i..i + size] {
if v.0.as_slice()[0..size] == input.mutator_bytes()[i..i + size] {
unsafe {
buffer_copy(input.bytes_mut(), v.1.as_slice(), 0, i, size);
buffer_copy(input.mutator_bytes_mut(), v.1.as_slice(), 0, i, size);
}
result = MutationResult::Mutated;
break 'outer;
@ -582,9 +582,9 @@ where
}
size = core::cmp::min(v.1.len(), len - i);
while size != 0 {
if v.1.as_slice()[0..size] == input.bytes()[i..i + size] {
if v.1.as_slice()[0..size] == input.mutator_bytes()[i..i + size] {
unsafe {
buffer_copy(input.bytes_mut(), v.0.as_slice(), 0, i, size);
buffer_copy(input.mutator_bytes_mut(), v.0.as_slice(), 0, i, size);
}
result = MutationResult::Mutated;
break 'outer;
@ -636,11 +636,11 @@ where
impl<I, S> Mutator<I, S> for I2SRandReplaceBinonly
where
S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes,
{
#[expect(clippy::too_many_lines)]
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let Some(size) = NonZero::new(input.bytes().len()) else {
let Some(size) = NonZero::new(input.mutator_bytes().len()) else {
return Ok(MutationResult::Skipped);
};
let Some(meta) = state.metadata_map().get::<CmpValuesMetadata>() else {
@ -654,8 +654,8 @@ where
let idx = state.rand_mut().below(cmps_len);
let off = state.rand_mut().below(size);
let len = input.bytes().len();
let bytes = input.bytes_mut();
let len = input.mutator_bytes().len();
let bytes = input.mutator_bytes_mut();
let meta = state.metadata_map().get::<CmpValuesMetadata>().unwrap();
let cmp_values = &meta.list[idx];
@ -779,9 +779,9 @@ where
'outer: for i in off..len {
let mut size = core::cmp::min(v.0.len(), len - i);
while size != 0 {
if v.0.as_slice()[0..size] == input.bytes()[i..i + size] {
if v.0.as_slice()[0..size] == input.mutator_bytes()[i..i + size] {
unsafe {
buffer_copy(input.bytes_mut(), v.1.as_slice(), 0, i, size);
buffer_copy(input.mutator_bytes_mut(), v.1.as_slice(), 0, i, size);
}
result = MutationResult::Mutated;
break 'outer;
@ -790,9 +790,9 @@ where
}
size = core::cmp::min(v.1.len(), len - i);
while size != 0 {
if v.1.as_slice()[0..size] == input.bytes()[i..i + size] {
if v.1.as_slice()[0..size] == input.mutator_bytes()[i..i + size] {
unsafe {
buffer_copy(input.bytes_mut(), v.0.as_slice(), 0, i, size);
buffer_copy(input.mutator_bytes_mut(), v.0.as_slice(), 0, i, size);
}
result = MutationResult::Mutated;
break 'outer;
@ -1305,8 +1305,8 @@ impl AFLppRedQueen {
impl<I, S> MultiMutator<I, S> for AFLppRedQueen
where
S: HasMetadata + HasRand + HasMaxSize + HasCurrentCorpusId,
I: HasMutatorResizableBytes + From<Vec<u8>>,
S: HasMetadata + HasRand + HasMaxSize + HasCorpus<I> + HasCurrentCorpusId,
I: ResizableMutator<u8> + From<Vec<u8>> + HasMutatorBytes,
{
#[expect(clippy::needless_range_loop, clippy::too_many_lines)]
fn multi_mutate(
@ -1317,7 +1317,7 @@ where
) -> Result<Vec<I>, Error> {
// TODO
// handle 128-bits logs
let size = input.bytes().len();
let size = input.mutator_bytes().len();
if size == 0 {
return Ok(vec![]);
}
@ -1342,9 +1342,9 @@ where
let orig_cmpvals = cmp_meta.orig_cmpvals();
let new_cmpvals = cmp_meta.new_cmpvals();
let headers = cmp_meta.headers();
let input_len = input.bytes().len();
let input_len = input.mutator_bytes().len();
let new_bytes = taint_meta.input_vec();
let orig_bytes = input.bytes();
let orig_bytes = input.mutator_bytes();
let taint = taint_meta.ranges();
let mut ret = max_count.map_or_else(Vec::new, Vec::with_capacity);

View File

@ -11,7 +11,7 @@ use libafl_bolts::{rands::Rand, Error, HasLen, Named};
use crate::{
corpus::{CorpusId, HasTestcase, Testcase},
inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes},
inputs::{BytesInput, HasMutatorBytes, ResizableMutator},
mutators::{rand_range, MutationResult, Mutator, Tokens},
nonzero,
stages::{
@ -233,7 +233,7 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
) -> MutationResult {
let temp_range = rand_range(state, range.end - range.start, nonzero!(MAX_CHARS));
let range = (range.start + temp_range.start)..(range.start + temp_range.end);
let range = match core::str::from_utf8(&input.0.bytes()[range.clone()]) {
let range = match core::str::from_utf8(&input.0.mutator_bytes()[range.clone()]) {
Ok(_) => range,
Err(e) => range.start..(range.start + e.valid_up_to()),
};
@ -242,7 +242,7 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
println!(
"mutating range: {:?} ({:?})",
range,
core::str::from_utf8(&input.0.bytes()[range.clone()])
core::str::from_utf8(&input.0.mutator_bytes()[range.clone()])
);
if range.start == range.end {
return MutationResult::Skipped;
@ -270,7 +270,7 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
}
input.0.splice(range, replacement);
input.1 = extract_metadata(input.0.bytes());
input.1 = extract_metadata(input.0.mutator_bytes());
MutationResult::Mutated
}
@ -292,11 +292,11 @@ where
S: HasRand + HasMaxSize,
{
fn mutate(&mut self, state: &mut S, input: &mut UnicodeInput) -> Result<MutationResult, Error> {
if input.0.bytes().is_empty() {
if input.0.mutator_bytes().is_empty() {
return Ok(MutationResult::Skipped);
}
let bytes = input.0.bytes();
let bytes = input.0.mutator_bytes();
let meta = &input.1;
if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) {
let substring = core::str::from_utf8(&bytes[base..][..len])?;
@ -354,11 +354,11 @@ where
S: HasRand + HasMaxSize,
{
fn mutate(&mut self, state: &mut S, input: &mut UnicodeInput) -> Result<MutationResult, Error> {
if input.0.bytes().is_empty() {
if input.0.mutator_bytes().is_empty() {
return Ok(MutationResult::Skipped);
}
let bytes = input.0.bytes();
let bytes = input.0.mutator_bytes();
let meta = &input.1;
if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) {
let substring = core::str::from_utf8(&bytes[base..][..len])?;
@ -404,7 +404,7 @@ where
S: HasRand + HasMaxSize + HasMetadata,
{
fn mutate(&mut self, state: &mut S, input: &mut UnicodeInput) -> Result<MutationResult, Error> {
if input.0.bytes().is_empty() {
if input.0.mutator_bytes().is_empty() {
return Ok(MutationResult::Skipped);
}
@ -418,7 +418,7 @@ where
let token_idx = state.rand_mut().below(tokens_len);
let bytes = input.0.bytes();
let bytes = input.0.mutator_bytes();
let meta = &input.1;
if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) {
let substring = core::str::from_utf8(&bytes[base..][..len])?;
@ -439,7 +439,7 @@ where
}
input.0.splice(range, token.iter().copied());
input.1 = extract_metadata(input.0.bytes());
input.1 = extract_metadata(input.0.mutator_bytes());
return Ok(MutationResult::Mutated);
}
@ -463,7 +463,7 @@ where
S: HasRand + HasMaxSize + HasMetadata,
{
fn mutate(&mut self, state: &mut S, input: &mut UnicodeInput) -> Result<MutationResult, Error> {
if input.0.bytes().is_empty() {
if input.0.mutator_bytes().is_empty() {
return Ok(MutationResult::Skipped);
}
@ -477,7 +477,7 @@ where
let token_idx = state.rand_mut().below(tokens_len);
let bytes = input.0.bytes();
let bytes = input.0.mutator_bytes();
let meta = &input.1;
if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) {
let substring = core::str::from_utf8(&bytes[base..][..len])?;
@ -498,7 +498,7 @@ where
}
input.0.splice(range, token.iter().copied());
input.1 = extract_metadata(input.0.bytes());
input.1 = extract_metadata(input.0.mutator_bytes());
return Ok(MutationResult::Mutated);
}
@ -536,10 +536,13 @@ mod test {
)?;
for _ in 0..(1 << 12) {
let metadata = extract_metadata(bytes.bytes());
let metadata = extract_metadata(bytes.mutator_bytes());
let mut input = (bytes, metadata);
let _ = mutator.mutate(&mut state, &mut input);
println!("{:?}", core::str::from_utf8(input.0.bytes()).unwrap());
println!(
"{:?}",
core::str::from_utf8(input.0.mutator_bytes()).unwrap()
);
bytes = input.0;
}
@ -568,10 +571,13 @@ mod test {
)?;
for _ in 0..(1 << 12) {
let metadata = extract_metadata(bytes.bytes());
let metadata = extract_metadata(bytes.mutator_bytes());
let mut input = (bytes, metadata);
let _ = mutator.mutate(&mut state, &mut input);
println!("{:?}", core::str::from_utf8(input.0.bytes()).unwrap());
println!(
"{:?}",
core::str::from_utf8(input.0.mutator_bytes()).unwrap()
);
bytes = input.0;
}

View File

@ -18,7 +18,7 @@ use crate::{
corpus::HasCurrentCorpusId,
events::EventFirer,
executors::{Executor, HasObservers},
inputs::HasMutatorResizableBytes,
inputs::{HasMutatorBytes, ResizableMutator},
mutators::mutations::buffer_copy,
nonzero,
observers::ObserversTuple,
@ -81,7 +81,7 @@ where
E: HasObservers + Executor<EM, I, S, Z>,
S: HasCorpus<I> + HasMetadata + HasRand + HasNamedMetadata + HasCurrentCorpusId,
E::Observers: ObserversTuple<I, S>,
I: HasMutatorResizableBytes + Clone,
I: ResizableMutator<u8> + HasMutatorBytes + Clone,
O: Hash,
C: AsRef<O> + Named,
{
@ -158,7 +158,7 @@ where
E: HasObservers + Executor<EM, I, S, Z>,
E::Observers: ObserversTuple<I, S>,
S: HasCorpus<I> + HasMetadata + HasRand + HasCurrentCorpusId + HasCurrentTestcase<I>,
I: HasMutatorResizableBytes + Clone,
I: ResizableMutator<u8> + HasMutatorBytes + Clone,
{
#[inline]
fn colorize(
@ -179,7 +179,7 @@ where
// Idea: No need to do this every time
let orig_hash =
Self::get_raw_map_hash_run(fuzzer, executor, state, manager, &input, observer_handle)?;
let changed_bytes = changed.bytes_mut();
let changed_bytes = changed.mutator_bytes_mut();
let input_len = changed_bytes.len();
// Binary heap, pop is logN, insert is logN
@ -208,8 +208,8 @@ where
let copy_len = r.len();
unsafe {
buffer_copy(
input.bytes_mut(),
changed.bytes(),
input.mutator_bytes_mut(),
changed.mutator_bytes(),
range_start,
range_start,
copy_len,
@ -236,8 +236,8 @@ where
// Revert the changes
unsafe {
buffer_copy(
input.bytes_mut(),
backup.bytes(),
input.mutator_bytes_mut(),
backup.mutator_bytes(),
range_start,
range_start,
copy_len,
@ -280,11 +280,11 @@ where
}
if let Some(meta) = state.metadata_map_mut().get_mut::<TaintMetadata>() {
meta.update(input.bytes().to_vec(), res);
meta.update(input.mutator_bytes().to_vec(), res);
// println!("meta: {:#?}", meta);
} else {
let meta = TaintMetadata::new(input.bytes().to_vec(), res);
let meta = TaintMetadata::new(input.mutator_bytes().to_vec(), res);
state.add_metadata::<TaintMetadata>(meta);
}

View File

@ -411,7 +411,7 @@ where
for mutation in mutations {
let mut input_copy = state.current_input_cloned()?;
for (index, new_byte) in mutation {
input_copy.bytes_mut()[index] = new_byte;
input_copy.mutator_bytes_mut()[index] = new_byte;
}
fuzzer.evaluate_filtered(state, executor, manager, input_copy)?;
}

View File

@ -18,8 +18,7 @@ use crate::{
executors::{Executor, HasObservers},
feedbacks::map::MapNoveltiesMetadata,
inputs::{
BytesInput, GeneralizedInputMetadata, GeneralizedItem, HasMutatorBytes,
HasMutatorResizableBytes,
BytesInput, GeneralizedInputMetadata, GeneralizedItem, HasMutatorBytes, ResizableMutator,
},
mark_feature_time,
observers::{CanTrack, MapObserver, ObserversTuple},
@ -119,7 +118,7 @@ where
let mut entry = state.corpus().get(corpus_id)?.borrow_mut();
let input = entry.input_mut().as_mut().unwrap();
let payload: Vec<_> = input.bytes().iter().map(|&x| Some(x)).collect();
let payload: Vec<_> = input.mutator_bytes().iter().map(|&x| Some(x)).collect();
if payload.len() > MAX_GENERALIZED_LEN {
return Ok(());

View File

@ -9,7 +9,6 @@ use frida_gum::{
};
#[cfg(windows)]
use libafl::{
corpus::Corpus,
executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks},
inputs::Input,
state::{HasCurrentTestcase, HasSolutions},

View File

@ -767,9 +767,12 @@ where
.match_first_type_mut::<DrCovRuntime>()
{
log::trace!("{basic_block_start:#016X}:{basic_block_size:X}");
// We can maybe remove the `basic_block_size as u64`` cast in the future
#[allow(trivial_numeric_casts)]
rt.drcov_basic_blocks.push(DrCovBasicBlock::new(
basic_block_start,
basic_block_start + basic_block_size as u64,
basic_block_start + (basic_block_size as u64),
));
}
}

View File

@ -110,7 +110,10 @@ fn minimize_crash_with_mutator<M: Mutator<BytesInput, TMinState>>(
}
let mut testcase = state.testcase_mut(id)?;
let input = testcase.load_input(state.corpus())?.bytes().to_vec();
let input = testcase
.load_input(state.corpus())?
.mutator_bytes()
.to_vec();
drop(testcase);
if input.len() >= size {
eprintln!(

View File

@ -11,7 +11,7 @@ use std::{
use libafl::{
corpus::Corpus,
inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes},
inputs::{BytesInput, HasMutatorBytes, ResizableMutator},
mutators::{
ComposedByMutations, MutationId, MutationResult, Mutator, MutatorsTuple, ScheduledMutator,
},
@ -172,7 +172,7 @@ where
drop(result);
if succeeded {
let target = intermediary.bytes();
let target = intermediary.mutator_bytes();
if target.as_slice().len() > max_size {
self.result
.replace(Err(Error::illegal_state("Mutation result was too long!")))
@ -322,7 +322,7 @@ where
input: &mut BytesInput,
) -> Result<MutationResult, Error> {
let seed = state.rand_mut().next();
let len_orig = input.bytes().len();
let len_orig = input.mutator_bytes().len();
let max_len = state.max_size();
input.resize(max_len, 0);
@ -335,7 +335,7 @@ where
});
let new_len = unsafe {
libafl_targets_libfuzzer_custom_mutator(
input.bytes_mut().as_mut_ptr(),
input.mutator_bytes_mut().as_mut_ptr(),
len_orig,
max_len,
seed as u32,
@ -408,7 +408,7 @@ where
let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
let other = other_testcase.load_input(state.corpus())?;
let data2 = Vec::from(other.bytes());
let data2 = Vec::from(other.mutator_bytes());
drop(other_testcase);
let seed = state.rand_mut().next();
@ -428,7 +428,7 @@ where
});
let new_len = unsafe {
libafl_targets_libfuzzer_custom_crossover(
input.bytes_mut().as_mut_ptr(),
input.mutator_bytes_mut().as_mut_ptr(),
len_orig,
data2.as_ptr(),
data2.len(),