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:
parent
2a36b78fd6
commit
a949452453
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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!
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)?;
|
||||||
}
|
}
|
||||||
|
@ -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(());
|
||||||
|
@ -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},
|
||||||
|
@ -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),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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!(
|
||||||
|
@ -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(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user