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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,13 +25,13 @@ use serde::{Deserialize, Serialize};
use crate::mutators::str_decode; use crate::mutators::str_decode;
use crate::{ use crate::{
corpus::{CorpusId, HasCurrentCorpusId}, corpus::{CorpusId, HasCurrentCorpusId},
inputs::HasMutatorResizableBytes, inputs::{HasMutatorBytes, ResizableMutator},
mutators::{ mutators::{
buffer_self_copy, mutations::buffer_copy, MultiMutator, MutationResult, Mutator, Named, buffer_self_copy, mutations::buffer_copy, MultiMutator, MutationResult, Mutator, Named,
}, },
observers::cmp::{AFLppCmpValuesMetadata, CmpValues, CmpValuesMetadata}, observers::cmp::{AFLppCmpValuesMetadata, CmpValues, CmpValuesMetadata},
stages::TaintMetadata, stages::TaintMetadata,
state::{HasMaxSize, HasRand}, state::{HasCorpus, HasMaxSize, HasRand},
Error, HasMetadata, Error, HasMetadata,
}; };
@ -306,7 +306,7 @@ pub struct TokenInsert;
impl<I, S> Mutator<I, S> for TokenInsert impl<I, S> Mutator<I, S> for TokenInsert
where where
S: HasMetadata + HasRand + HasMaxSize, S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorResizableBytes, I: ResizableMutator<u8> + HasMutatorBytes,
{ {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let max_size = state.max_size(); let max_size = state.max_size();
@ -322,7 +322,7 @@ where
}; };
let token_idx = state.rand_mut().below(tokens_len); let token_idx = state.rand_mut().below(tokens_len);
let size = input.bytes().len(); let size = input.mutator_bytes().len();
// # Safety // # Safety
// after saturating add it's always above 0 // after saturating add it's always above 0
@ -344,8 +344,8 @@ where
input.resize(size + len, 0); input.resize(size + len, 0);
unsafe { unsafe {
buffer_self_copy(input.bytes_mut(), off, off + len, size - off); buffer_self_copy(input.mutator_bytes_mut(), off, off + len, size - off);
buffer_copy(input.bytes_mut(), token, 0, off, len); buffer_copy(input.mutator_bytes_mut(), token, 0, off, len);
} }
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
@ -375,10 +375,10 @@ pub struct TokenReplace;
impl<I, S> Mutator<I, S> for TokenReplace impl<I, S> Mutator<I, S> for TokenReplace
where where
S: HasMetadata + HasRand + HasMaxSize, S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorResizableBytes, I: ResizableMutator<u8> + HasMutatorBytes,
{ {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { 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) { let off = if let Some(nz) = NonZero::new(size) {
state.rand_mut().below(nz) state.rand_mut().below(nz)
} else { } else {
@ -405,7 +405,7 @@ where
} }
unsafe { unsafe {
buffer_copy(input.bytes_mut(), token, 0, off, len); buffer_copy(input.mutator_bytes_mut(), token, 0, off, len);
} }
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
@ -435,11 +435,11 @@ pub struct I2SRandReplace;
impl<I, S> Mutator<I, S> for I2SRandReplace impl<I, S> Mutator<I, S> for I2SRandReplace
where where
S: HasMetadata + HasRand + HasMaxSize, S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorResizableBytes, I: ResizableMutator<u8> + HasMutatorBytes,
{ {
#[expect(clippy::too_many_lines)] #[expect(clippy::too_many_lines)]
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { 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 { let Some(size) = NonZero::new(size) else {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
}; };
@ -459,8 +459,8 @@ where
let idx = state.rand_mut().below(cmps_len); let idx = state.rand_mut().below(cmps_len);
let off = state.rand_mut().below(size); let off = state.rand_mut().below(size);
let len = input.bytes().len(); let len = input.mutator_bytes().len();
let bytes = input.bytes_mut(); let bytes = input.mutator_bytes_mut();
let meta = state.metadata_map().get::<CmpValuesMetadata>().unwrap(); let meta = state.metadata_map().get::<CmpValuesMetadata>().unwrap();
let cmp_values = &meta.list[idx]; let cmp_values = &meta.list[idx];
@ -571,9 +571,9 @@ where
'outer: for i in off..len { 'outer: for i in off..len {
let mut size = core::cmp::min(v.0.len(), len - i); let mut size = core::cmp::min(v.0.len(), len - i);
while size != 0 { 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 { 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; result = MutationResult::Mutated;
break 'outer; break 'outer;
@ -582,9 +582,9 @@ where
} }
size = core::cmp::min(v.1.len(), len - i); size = core::cmp::min(v.1.len(), len - i);
while size != 0 { 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 { 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; result = MutationResult::Mutated;
break 'outer; break 'outer;
@ -636,11 +636,11 @@ where
impl<I, S> Mutator<I, S> for I2SRandReplaceBinonly impl<I, S> Mutator<I, S> for I2SRandReplaceBinonly
where where
S: HasMetadata + HasRand + HasMaxSize, S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorResizableBytes, I: ResizableMutator<u8> + HasMutatorBytes,
{ {
#[expect(clippy::too_many_lines)] #[expect(clippy::too_many_lines)]
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { 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); return Ok(MutationResult::Skipped);
}; };
let Some(meta) = state.metadata_map().get::<CmpValuesMetadata>() else { let Some(meta) = state.metadata_map().get::<CmpValuesMetadata>() else {
@ -654,8 +654,8 @@ where
let idx = state.rand_mut().below(cmps_len); let idx = state.rand_mut().below(cmps_len);
let off = state.rand_mut().below(size); let off = state.rand_mut().below(size);
let len = input.bytes().len(); let len = input.mutator_bytes().len();
let bytes = input.bytes_mut(); let bytes = input.mutator_bytes_mut();
let meta = state.metadata_map().get::<CmpValuesMetadata>().unwrap(); let meta = state.metadata_map().get::<CmpValuesMetadata>().unwrap();
let cmp_values = &meta.list[idx]; let cmp_values = &meta.list[idx];
@ -779,9 +779,9 @@ where
'outer: for i in off..len { 'outer: for i in off..len {
let mut size = core::cmp::min(v.0.len(), len - i); let mut size = core::cmp::min(v.0.len(), len - i);
while size != 0 { 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 { 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; result = MutationResult::Mutated;
break 'outer; break 'outer;
@ -790,9 +790,9 @@ where
} }
size = core::cmp::min(v.1.len(), len - i); size = core::cmp::min(v.1.len(), len - i);
while size != 0 { 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 { 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; result = MutationResult::Mutated;
break 'outer; break 'outer;
@ -1305,8 +1305,8 @@ impl AFLppRedQueen {
impl<I, S> MultiMutator<I, S> for AFLppRedQueen impl<I, S> MultiMutator<I, S> for AFLppRedQueen
where where
S: HasMetadata + HasRand + HasMaxSize + HasCurrentCorpusId, S: HasMetadata + HasRand + HasMaxSize + HasCorpus<I> + HasCurrentCorpusId,
I: HasMutatorResizableBytes + From<Vec<u8>>, I: ResizableMutator<u8> + From<Vec<u8>> + HasMutatorBytes,
{ {
#[expect(clippy::needless_range_loop, clippy::too_many_lines)] #[expect(clippy::needless_range_loop, clippy::too_many_lines)]
fn multi_mutate( fn multi_mutate(
@ -1317,7 +1317,7 @@ where
) -> Result<Vec<I>, Error> { ) -> Result<Vec<I>, Error> {
// TODO // TODO
// handle 128-bits logs // handle 128-bits logs
let size = input.bytes().len(); let size = input.mutator_bytes().len();
if size == 0 { if size == 0 {
return Ok(vec![]); return Ok(vec![]);
} }
@ -1342,9 +1342,9 @@ where
let orig_cmpvals = cmp_meta.orig_cmpvals(); let orig_cmpvals = cmp_meta.orig_cmpvals();
let new_cmpvals = cmp_meta.new_cmpvals(); let new_cmpvals = cmp_meta.new_cmpvals();
let headers = cmp_meta.headers(); 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 new_bytes = taint_meta.input_vec();
let orig_bytes = input.bytes(); let orig_bytes = input.mutator_bytes();
let taint = taint_meta.ranges(); let taint = taint_meta.ranges();
let mut ret = max_count.map_or_else(Vec::new, Vec::with_capacity); 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::{ use crate::{
corpus::{CorpusId, HasTestcase, Testcase}, corpus::{CorpusId, HasTestcase, Testcase},
inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes}, inputs::{BytesInput, HasMutatorBytes, ResizableMutator},
mutators::{rand_range, MutationResult, Mutator, Tokens}, mutators::{rand_range, MutationResult, Mutator, Tokens},
nonzero, nonzero,
stages::{ stages::{
@ -233,7 +233,7 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
) -> MutationResult { ) -> MutationResult {
let temp_range = rand_range(state, range.end - range.start, nonzero!(MAX_CHARS)); 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 = (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, Ok(_) => range,
Err(e) => range.start..(range.start + e.valid_up_to()), 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!( println!(
"mutating range: {:?} ({:?})", "mutating range: {:?} ({:?})",
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 { if range.start == range.end {
return MutationResult::Skipped; 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.0.splice(range, replacement);
input.1 = extract_metadata(input.0.bytes()); input.1 = extract_metadata(input.0.mutator_bytes());
MutationResult::Mutated MutationResult::Mutated
} }
@ -292,11 +292,11 @@ where
S: HasRand + HasMaxSize, S: HasRand + HasMaxSize,
{ {
fn mutate(&mut self, state: &mut S, input: &mut UnicodeInput) -> Result<MutationResult, Error> { 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); return Ok(MutationResult::Skipped);
} }
let bytes = input.0.bytes(); let bytes = input.0.mutator_bytes();
let meta = &input.1; let meta = &input.1;
if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) { if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) {
let substring = core::str::from_utf8(&bytes[base..][..len])?; let substring = core::str::from_utf8(&bytes[base..][..len])?;
@ -354,11 +354,11 @@ where
S: HasRand + HasMaxSize, S: HasRand + HasMaxSize,
{ {
fn mutate(&mut self, state: &mut S, input: &mut UnicodeInput) -> Result<MutationResult, Error> { 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); return Ok(MutationResult::Skipped);
} }
let bytes = input.0.bytes(); let bytes = input.0.mutator_bytes();
let meta = &input.1; let meta = &input.1;
if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) { if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) {
let substring = core::str::from_utf8(&bytes[base..][..len])?; let substring = core::str::from_utf8(&bytes[base..][..len])?;
@ -404,7 +404,7 @@ where
S: HasRand + HasMaxSize + HasMetadata, S: HasRand + HasMaxSize + HasMetadata,
{ {
fn mutate(&mut self, state: &mut S, input: &mut UnicodeInput) -> Result<MutationResult, Error> { 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); return Ok(MutationResult::Skipped);
} }
@ -418,7 +418,7 @@ where
let token_idx = state.rand_mut().below(tokens_len); let token_idx = state.rand_mut().below(tokens_len);
let bytes = input.0.bytes(); let bytes = input.0.mutator_bytes();
let meta = &input.1; let meta = &input.1;
if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) { if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) {
let substring = core::str::from_utf8(&bytes[base..][..len])?; let substring = core::str::from_utf8(&bytes[base..][..len])?;
@ -439,7 +439,7 @@ where
} }
input.0.splice(range, token.iter().copied()); 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); return Ok(MutationResult::Mutated);
} }
@ -463,7 +463,7 @@ where
S: HasRand + HasMaxSize + HasMetadata, S: HasRand + HasMaxSize + HasMetadata,
{ {
fn mutate(&mut self, state: &mut S, input: &mut UnicodeInput) -> Result<MutationResult, Error> { 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); return Ok(MutationResult::Skipped);
} }
@ -477,7 +477,7 @@ where
let token_idx = state.rand_mut().below(tokens_len); let token_idx = state.rand_mut().below(tokens_len);
let bytes = input.0.bytes(); let bytes = input.0.mutator_bytes();
let meta = &input.1; let meta = &input.1;
if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) { if let Some((base, len)) = choose_start(state.rand_mut(), bytes, meta) {
let substring = core::str::from_utf8(&bytes[base..][..len])?; let substring = core::str::from_utf8(&bytes[base..][..len])?;
@ -498,7 +498,7 @@ where
} }
input.0.splice(range, token.iter().copied()); 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); return Ok(MutationResult::Mutated);
} }
@ -536,10 +536,13 @@ mod test {
)?; )?;
for _ in 0..(1 << 12) { for _ in 0..(1 << 12) {
let metadata = extract_metadata(bytes.bytes()); let metadata = extract_metadata(bytes.mutator_bytes());
let mut input = (bytes, metadata); let mut input = (bytes, metadata);
let _ = mutator.mutate(&mut state, &mut input); 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; bytes = input.0;
} }
@ -568,10 +571,13 @@ mod test {
)?; )?;
for _ in 0..(1 << 12) { for _ in 0..(1 << 12) {
let metadata = extract_metadata(bytes.bytes()); let metadata = extract_metadata(bytes.mutator_bytes());
let mut input = (bytes, metadata); let mut input = (bytes, metadata);
let _ = mutator.mutate(&mut state, &mut input); 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; bytes = input.0;
} }

View File

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

View File

@ -411,7 +411,7 @@ where
for mutation in mutations { for mutation in mutations {
let mut input_copy = state.current_input_cloned()?; let mut input_copy = state.current_input_cloned()?;
for (index, new_byte) in mutation { 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)?; fuzzer.evaluate_filtered(state, executor, manager, input_copy)?;
} }

View File

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

View File

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

View File

@ -767,9 +767,12 @@ where
.match_first_type_mut::<DrCovRuntime>() .match_first_type_mut::<DrCovRuntime>()
{ {
log::trace!("{basic_block_start:#016X}:{basic_block_size:X}"); 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( rt.drcov_basic_blocks.push(DrCovBasicBlock::new(
basic_block_start, 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 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); drop(testcase);
if input.len() >= size { if input.len() >= size {
eprintln!( eprintln!(

View File

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