Skip to content

Commit

Permalink
More progress on creating a mutator toolkit.
Browse files Browse the repository at this point in the history
e.g., added helper functions to mutate arrays/vec of numbers.
Generalized a couple of helper functions to be generic over all copy types, etc.
  • Loading branch information
Michael Rodler committed Jan 24, 2024
1 parent a6aff70 commit 54a802f
Show file tree
Hide file tree
Showing 10 changed files with 633 additions and 121 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ rustc-hash = "1.1.0"
indexmap = "2.1"
smallvec = { version = "1", features = ["union", "const_generics"] }
regex = "1"
num-traits = "0.2"

# For addr2line implementation
addr2line = "0.21"
Expand Down
76 changes: 8 additions & 68 deletions src/mutators/bytes/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,91 +530,31 @@ pub fn overwrite_from_dictionary<T: AsMut<[u8]>>(
}

/// helper to splice data within a vector.
#[inline]
pub fn splice_within<T: AsMut<[u8]>>(
input: &mut T,
rng: &mut impl rand::Rng,
) -> (isize, isize, usize) {
let input = input.as_mut();
// Pre-compute random numbers to avoid borrowing from the &mut fuzzer
#[allow(clippy::cast_possible_wrap)]
let src = (rng.gen::<usize>() % input.len()) as isize;

#[allow(clippy::cast_possible_wrap)]
let dst = (rng.gen::<usize>() % input.len()) as isize;

// Get the larger of the two positions
let largest = std::cmp::max(src, dst);

// Get the maximum slice that is not out of bounds
let max_len: usize = input.len() - largest as usize;

// Randomly choose a length of slice to copy that is in bounds
let len = rng.gen::<usize>() % max_len;

// Copy the slice internally. These buffers could overlap
// SAFETY: src and dst are within the bounds of input
unsafe {
std::ptr::copy(
input.as_mut_ptr().offset(src),
input.as_mut_ptr().offset(dst),
len,
);
}

(src, dst, len)
) -> Option<(isize, isize, usize)> {
crate::mutators::helpers::splice_within(input, rng)
}

/// Copy a random sub-slice from `src` into a random subslice of `dst`.
/// This will potentially grow or shrink the destination vector.
#[inline]
pub fn splice_bytes_extend(
dst: &mut Vec<u8>,
src: &[u8],
rng: &mut impl rand::Rng,
) -> (std::ops::Range<usize>, std::ops::Range<usize>) {
// gen_range panics on empty ranges, so we need to make sure that we can sample at least one
// number out of these ranges. if both `dst` and `src` are non-empty this is always the
// case.
debug_assert!(!dst.is_empty() && !src.is_empty());
let src_start = rng.gen_range(0..src.len());
let src_end = rng.gen_range(src_start..=src.len());

let dst_start = rng.gen_range(0..dst.len());
let dst_end = rng.gen_range(dst_start..=dst.len());

crate::utils::vec::splice_into(dst, dst_start..dst_end, &src[src_start..src_end]);
((dst_start..dst_end), (src_start..src_end))
) -> Option<(std::ops::Range<usize>, std::ops::Range<usize>)> {
crate::mutators::helpers::splice_extend(dst, src, rng)
}

/// Copy sub-slice from another byte slice into the current one.
#[inline]
pub fn splice_other_inplace<T: AsMut<[u8]>, S: AsRef<[u8]>>(
input: &mut T,
other: &S,
rng: &mut impl rand::Rng,
) -> Option<(usize, usize, usize)> {
let input = input.as_mut();
let other = other.as_ref();
if other.is_empty() || input.is_empty() || input.len() < 8 {
return None;
}

let other_start = rng.gen_range(0..other.len()); // at least 0..1 -> no panic
let other_end = rng.gen_range(other_start..=other.len()); // at least 1..=1 -> no panic

// skip splicing another small input
if (other_end - other_start) < 4 {
return None;
}
let splice_from = &other[other_start..other_end];
if splice_from.len() >= input.len() {
return None;
}

let splice_len = splice_from.len();
let input_offset = rng.gen_range(0_usize..(input.len() - splice_len));

// Splice the found
input[input_offset..(input_offset + splice_len)].copy_from_slice(splice_from);

// Output mutation
Some((input_offset, other_start, splice_len))
crate::mutators::helpers::splice_other_inplace(input, other, rng)
}
2 changes: 1 addition & 1 deletion src/mutators/bytes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ pub fn splice_input(
return None;
}

let (src, dst, len) = helpers::splice_within(input, rng);
let (src, dst, len) = helpers::splice_within(input, rng)?;

// Output mutation
Some(format!(
Expand Down
Loading

0 comments on commit 54a802f

Please sign in to comment.