Skip to content

Commit

Permalink
Rename ResizableMutator, make it generic (#2859)
Browse files Browse the repository at this point in the history
* Rename ResizableMutator, make it generic

* fix

* more fix

* reorer

* fmt, fixes

* fixes

* more commit

* fmt
  • Loading branch information
domenukk authored Jan 19, 2025
1 parent 2a36b78 commit a949452
Show file tree
Hide file tree
Showing 15 changed files with 285 additions and 226 deletions.
8 changes: 4 additions & 4 deletions libafl/src/inputs/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use core::cell::RefCell;
use libafl_bolts::{ownedref::OwnedSlice, HasLen};

use super::ValueInput;
use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes, HasTargetBytes};
use crate::inputs::{HasMutatorBytes, HasTargetBytes, ResizableMutator};

/// A bytes input is the basic input
pub type BytesInput = ValueInput<Vec<u8>>;
Expand All @@ -24,16 +24,16 @@ impl From<BytesInput> for Rc<RefCell<BytesInput>> {
}

impl HasMutatorBytes for BytesInput {
fn bytes(&self) -> &[u8] {
fn mutator_bytes(&self) -> &[u8] {
self.as_ref()
}

fn bytes_mut(&mut self) -> &mut [u8] {
fn mutator_bytes_mut(&mut self) -> &mut [u8] {
self.as_mut()
}
}

impl HasMutatorResizableBytes for BytesInput {
impl ResizableMutator<u8> for BytesInput {
fn resize(&mut self, new_len: usize, value: u8) {
self.as_mut().resize(new_len, value);
}
Expand Down
56 changes: 28 additions & 28 deletions libafl/src/inputs/bytessub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use libafl_bolts::{
HasLen,
};

use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes};
use crate::inputs::{HasMutatorBytes, ResizableMutator};

/// The [`BytesSubInput`] makes it possible to use [`crate::mutators::Mutator`]`s` that work on
/// inputs implementing the [`HasMutatorBytes`] for a sub-range of this input.
Expand All @@ -31,21 +31,21 @@ use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes};
/// let mut sub_input = bytes_input.sub_input(1..);
///
/// // Run any mutations on the sub input.
/// sub_input.bytes_mut()[0] = 42;
/// sub_input.mutator_bytes_mut()[0] = 42;
///
/// // The mutations are applied to the underlying input.
/// assert_eq!(bytes_input.bytes()[1], 42);
/// assert_eq!(bytes_input.mutator_bytes()[1], 42);
/// ```
///
/// If inputs implement the [`HasMutatorResizableBytes`] trait, growing or shrinking the sub input
/// If inputs implement the [`ResizableMutator`] trait, growing or shrinking the sub input
/// will grow or shrink the parent input,
/// and keep elements around the current range untouched / move them accordingly.
///
/// For example:
/// ```rust
/// # extern crate alloc;
/// # extern crate libafl;
/// # use libafl::inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes};
/// # use libafl::inputs::{BytesInput, HasMutatorBytes, ResizableMutator};
/// # use alloc::vec::Vec;
/// #
/// # #[cfg(not(feature = "std"))]
Expand All @@ -57,13 +57,13 @@ use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes};
/// // Note that the range ends on an exclusive value this time.
/// let mut sub_input = bytes_input.sub_input(1..=3);
///
/// assert_eq!(sub_input.bytes(), &[2, 3, 4]);
/// assert_eq!(sub_input.mutator_bytes(), &[2, 3, 4]);
///
/// // We extend it with a few values.
/// sub_input.extend(&[42, 42, 42]);
///
/// // The values outside of the range are moved back and forwards, accordingly.
/// assert_eq!(bytes_input.bytes(), [1, 2, 3, 4, 42, 42, 42, 5]);
/// assert_eq!(bytes_input.mutator_bytes(), [1, 2, 3, 4, 42, 42, 42, 5]);
/// ```
///
/// The input supports all methods in the [`HasMutatorBytes`] trait if the parent input also implements this trait.
Expand Down Expand Up @@ -102,19 +102,19 @@ where
I: HasMutatorBytes,
{
#[inline]
fn bytes(&self) -> &[u8] {
&self.parent_input.bytes()[self.range.clone()]
fn mutator_bytes(&self) -> &[u8] {
&self.parent_input.mutator_bytes()[self.range.clone()]
}

#[inline]
fn bytes_mut(&mut self) -> &mut [u8] {
&mut self.parent_input.bytes_mut()[self.range.clone()]
fn mutator_bytes_mut(&mut self) -> &mut [u8] {
&mut self.parent_input.mutator_bytes_mut()[self.range.clone()]
}
}

impl<I> HasMutatorResizableBytes for BytesSubInput<'_, I>
impl<I> ResizableMutator<u8> for BytesSubInput<'_, I>
where
I: HasMutatorResizableBytes,
I: ResizableMutator<u8> + HasMutatorBytes + HasLen,
{
fn resize(&mut self, new_len: usize, value: u8) {
let start_index = self.range.start;
Expand All @@ -134,7 +134,7 @@ where

if old_parent_len > end_index {
// the parent has a reminder, move it back.
let parent_bytes = self.parent_input.bytes_mut();
let parent_bytes = self.parent_input.mutator_bytes_mut();

// move right
let (_, rest) = parent_bytes.split_at_mut(start_index + old_len);
Expand All @@ -151,7 +151,7 @@ where
// We shrink. Remove the values, then remove the underlying buffer.
let diff = old_len - new_len;

let parent_bytes = self.parent_input.bytes_mut();
let parent_bytes = self.parent_input.mutator_bytes_mut();

// move left
let (_, rest) = parent_bytes.split_at_mut(start_index + new_len);
Expand All @@ -171,7 +171,7 @@ where

let new_values: Vec<u8> = iter.into_iter().copied().collect();
self.resize(old_len + new_values.len(), 0);
self.bytes_mut()[old_len..].copy_from_slice(&new_values);
self.mutator_bytes_mut()[old_len..].copy_from_slice(&new_values);
}

/// Creates a splicing iterator that replaces the specified range in the vector
Expand Down Expand Up @@ -214,7 +214,7 @@ mod tests {
use libafl_bolts::HasLen;

use crate::{
inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes, NopInput},
inputs::{BytesInput, HasMutatorBytes, NopInput, ResizableMutator},
mutators::{havoc_mutations_no_crossover, MutatorsTuple},
state::NopState,
};
Expand Down Expand Up @@ -245,19 +245,19 @@ mod tests {

let mut sub_input = bytes_input.sub_input(0..1);
assert_eq!(sub_input.len(), 1);
sub_input.bytes_mut()[0] = 2;
assert_eq!(bytes_input.bytes()[0], 2);
sub_input.mutator_bytes_mut()[0] = 2;
assert_eq!(bytes_input.mutator_bytes()[0], 2);

let mut sub_input = bytes_input.sub_input(1..=2);
assert_eq!(sub_input.len(), 2);
sub_input.bytes_mut()[0] = 3;
assert_eq!(bytes_input.bytes()[1], 3);
sub_input.mutator_bytes_mut()[0] = 3;
assert_eq!(bytes_input.mutator_bytes()[1], 3);

let mut sub_input = bytes_input.sub_input(..);
assert_eq!(sub_input.len(), len_orig);
sub_input.bytes_mut()[0] = 1;
sub_input.bytes_mut()[1] = 2;
assert_eq!(bytes_input.bytes()[0], 1);
sub_input.mutator_bytes_mut()[0] = 1;
sub_input.mutator_bytes_mut()[1] = 2;
assert_eq!(bytes_input.mutator_bytes()[0], 1);
}

#[test]
Expand All @@ -268,18 +268,18 @@ mod tests {
let mut sub_input = bytes_input.sub_input(2..);
assert_eq!(sub_input.len(), len_orig - 2);
sub_input.resize(len_orig, 0);
assert_eq!(sub_input.bytes()[sub_input.len() - 1], 0);
assert_eq!(sub_input.mutator_bytes()[sub_input.len() - 1], 0);
assert_eq!(sub_input.len(), len_orig);
assert_eq!(bytes_input.len(), len_orig + 2);
assert_eq!(bytes_input.bytes()[bytes_input.len() - 1], 0);
assert_eq!(bytes_input.mutator_bytes()[bytes_input.len() - 1], 0);

let (mut bytes_input, len_orig) = init_bytes_input();

let mut sub_input = bytes_input.sub_input(..2);
assert_eq!(sub_input.len(), 2);
sub_input.resize(3, 0);
assert_eq!(sub_input.len(), 3);
assert_eq!(sub_input.bytes()[sub_input.len() - 1], 0);
assert_eq!(sub_input.mutator_bytes()[sub_input.len() - 1], 0);
assert_eq!(bytes_input.len(), len_orig + 1);

let mut sub_input = bytes_input.sub_input(..3);
Expand All @@ -300,7 +300,7 @@ mod tests {
sub_input.resize(10, 0);
assert_eq!(sub_input.len(), 10);
assert_eq!(bytes_input.len(), 10);
assert_eq!(bytes_input.bytes()[2], 0);
assert_eq!(bytes_input.mutator_bytes()[2], 0);

let mut sub_input = bytes_input.sub_input(..);
sub_input.resize(1, 0);
Expand Down
59 changes: 32 additions & 27 deletions libafl/src/inputs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,25 +158,25 @@ pub trait HasTargetBytes {
/// Contains mutable bytes
pub trait HasMutatorBytes: HasLen {
/// The bytes
fn bytes(&self) -> &[u8];
fn mutator_bytes(&self) -> &[u8];

/// The bytes to mutate
fn bytes_mut(&mut self) -> &mut [u8];
fn mutator_bytes_mut(&mut self) -> &mut [u8];

/// Creates a [`SubRangeSlice`] from this input, that can be used to slice a byte array.
fn sub_bytes<R>(&self, range: R) -> SubRangeSlice<u8>
where
R: RangeBounds<usize>,
{
SubRangeSlice::new(OwnedSlice::from(self.bytes()), range)
SubRangeSlice::new(OwnedSlice::from(self.mutator_bytes()), range)
}

/// Creates a [`SubRangeMutSlice`] from this input, that can be used to slice a byte array.
fn sub_bytes_mut<R>(&mut self, range: R) -> SubRangeMutSlice<u8>
where
R: RangeBounds<usize>,
{
SubRangeMutSlice::new(OwnedMutSlice::from(self.bytes_mut()), range)
SubRangeMutSlice::new(OwnedMutSlice::from(self.mutator_bytes_mut()), range)
}

/// Creates a [`BytesSubInput`] from this input, that can be used for local mutations.
Expand All @@ -189,11 +189,11 @@ pub trait HasMutatorBytes: HasLen {
}

impl HasMutatorBytes for Vec<u8> {
fn bytes(&self) -> &[u8] {
fn mutator_bytes(&self) -> &[u8] {
self.as_ref()
}

fn bytes_mut(&mut self) -> &mut [u8] {
fn mutator_bytes_mut(&mut self) -> &mut [u8] {
self.as_mut()
}
}
Expand All @@ -203,63 +203,68 @@ impl HasMutatorBytes for Vec<u8> {
pub type MutVecInput<'a> = &'a mut Vec<u8>;

impl HasMutatorBytes for &'_ mut Vec<u8> {
fn bytes(&self) -> &[u8] {
fn mutator_bytes(&self) -> &[u8] {
self
}

fn bytes_mut(&mut self) -> &mut [u8] {
fn mutator_bytes_mut(&mut self) -> &mut [u8] {
self
}
}

/// Contains mutable and resizable bytes
pub trait HasMutatorResizableBytes: HasMutatorBytes {
/// Resize the mutator bytes to a given new size.
/// Contains resizable bytes
pub trait ResizableMutator<T> {
/// Resize the mutator content to a given new size.
/// Use `value` to fill new slots in case the buffer grows.
/// See [`Vec::splice`].
fn resize(&mut self, new_len: usize, value: u8);
fn resize(&mut self, new_len: usize, value: T);

/// Extends the given buffer with an iterator. See [`alloc::vec::Vec::extend`]
fn extend<'a, I: IntoIterator<Item = &'a u8>>(&mut self, iter: I);
fn extend<'a, I: IntoIterator<Item = &'a T>>(&mut self, iter: I)
where
T: 'a;

/// Splices the given target bytes according to [`Vec::splice`]'s rules
/// Splices the given target values according to [`Vec::splice`]'s rules
fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = u8>;
I: IntoIterator<Item = T>;

/// Drains the given target bytes according to [`Vec::drain`]'s rules
fn drain<R>(&mut self, range: R) -> Drain<'_, u8>
/// Drains the given target value according to [`Vec::drain`]'s rules
fn drain<R>(&mut self, range: R) -> Drain<'_, T>
where
R: RangeBounds<usize>;
}

impl HasMutatorResizableBytes for Vec<u8> {
fn resize(&mut self, new_len: usize, value: u8) {
<Vec<u8>>::resize(self, new_len, value);
impl<T> ResizableMutator<T> for Vec<T>
where
T: Copy + 'static,
{
fn resize(&mut self, new_len: usize, value: T) {
<Vec<T>>::resize(self, new_len, value);
}

fn extend<'a, I: IntoIterator<Item = &'a u8>>(&mut self, iter: I) {
<Vec<u8> as Extend<I::Item>>::extend(self, iter);
fn extend<'a, I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
<Vec<T> as Extend<I::Item>>::extend(self, iter);
}

fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = u8>,
I: IntoIterator<Item = T>,
{
<Vec<u8>>::splice(self, range, replace_with)
<Vec<T>>::splice(self, range, replace_with)
}

fn drain<R>(&mut self, range: R) -> Drain<'_, u8>
fn drain<R>(&mut self, range: R) -> Drain<'_, T>
where
R: RangeBounds<usize>,
{
<Vec<u8>>::drain(self, range)
<Vec<T>>::drain(self, range)
}
}

impl HasMutatorResizableBytes for &mut Vec<u8> {
impl ResizableMutator<u8> for &mut Vec<u8> {
fn resize(&mut self, new_len: usize, value: u8) {
self.deref_mut().resize(new_len, value);
}
Expand Down
Loading

0 comments on commit a949452

Please sign in to comment.