(See #2853.)
This commit attempts to improve the [`HasMutatorBytes`] trait to allow it to
be used along with input types that cannot be resizable.
[`HasMutatorBytes`] is split into two traits:
- [`HasMutatorBytes`]: requires `bytes` and `bytes_mut`.
- `HasMutatorResizableBytes`: requires [`HasMutatorBytes`], and also requires
a few other methods for resizing / shrinking the underlying input type.
N.B.: I believe that if merged, this would introduce a breaking change.
[`HasMutatorBytes`]: 198cd5dbc5/libafl/src/inputs/bytes.rs (L26)
This commit is contained in:
parent
198cd5dbc5
commit
15aa498d5e
@ -11,7 +11,7 @@ use core::cell::RefCell;
|
||||
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
|
||||
|
||||
use super::ValueInput;
|
||||
use crate::inputs::{HasMutatorBytes, HasTargetBytes};
|
||||
use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes, HasTargetBytes};
|
||||
|
||||
/// A bytes input is the basic input
|
||||
pub type BytesInput = ValueInput<Vec<u8>>;
|
||||
@ -31,7 +31,9 @@ impl HasMutatorBytes for BytesInput {
|
||||
fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasMutatorResizableBytes for BytesInput {
|
||||
fn resize(&mut self, new_len: usize, value: u8) {
|
||||
self.as_mut().resize(new_len, value);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use libafl_bolts::{
|
||||
HasLen,
|
||||
};
|
||||
|
||||
use crate::inputs::HasMutatorBytes;
|
||||
use crate::inputs::{HasMutatorBytes, HasMutatorResizableBytes};
|
||||
|
||||
/// 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.
|
||||
@ -37,14 +37,15 @@ use crate::inputs::HasMutatorBytes;
|
||||
/// assert_eq!(bytes_input.bytes()[1], 42);
|
||||
/// ```
|
||||
///
|
||||
/// Growing or shrinking the sub input will grow or shrink the parent input,
|
||||
/// If inputs implement the [`HasMutatorResizableBytes`] 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};
|
||||
/// # use libafl::inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes};
|
||||
/// # use alloc::vec::Vec;
|
||||
/// #
|
||||
/// # #[cfg(not(feature = "std"))]
|
||||
@ -109,7 +110,12 @@ where
|
||||
fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.parent_input.bytes_mut()[self.range.clone()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> HasMutatorResizableBytes for BytesSubInput<'_, I>
|
||||
where
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn resize(&mut self, new_len: usize, value: u8) {
|
||||
let start_index = self.range.start;
|
||||
let end_index = self.range.end;
|
||||
@ -208,7 +214,7 @@ mod tests {
|
||||
use libafl_bolts::HasLen;
|
||||
|
||||
use crate::{
|
||||
inputs::{BytesInput, HasMutatorBytes, NopInput},
|
||||
inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes, NopInput},
|
||||
mutators::{havoc_mutations_no_crossover, MutatorsTuple},
|
||||
state::NopState,
|
||||
};
|
||||
|
@ -155,7 +155,7 @@ pub trait HasTargetBytes {
|
||||
fn target_bytes(&self) -> OwnedSlice<u8>;
|
||||
}
|
||||
|
||||
/// Contains mutable and resizable bytes
|
||||
/// Contains mutable bytes
|
||||
pub trait HasMutatorBytes: HasLen {
|
||||
/// The bytes
|
||||
fn bytes(&self) -> &[u8];
|
||||
@ -163,25 +163,6 @@ pub trait HasMutatorBytes: HasLen {
|
||||
/// The bytes to mutate
|
||||
fn bytes_mut(&mut self) -> &mut [u8];
|
||||
|
||||
/// Resize the mutator bytes 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);
|
||||
|
||||
/// Extends the given buffer with an iterator. See [`alloc::vec::Vec::extend`]
|
||||
fn extend<'a, I: IntoIterator<Item = &'a u8>>(&mut self, iter: I);
|
||||
|
||||
/// Splices the given target bytes 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>;
|
||||
|
||||
/// Drains the given target bytes according to [`Vec::drain`]'s rules
|
||||
fn drain<R>(&mut self, range: R) -> Drain<'_, u8>
|
||||
where
|
||||
R: RangeBounds<usize>;
|
||||
|
||||
/// 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
|
||||
@ -215,7 +196,45 @@ impl HasMutatorBytes for Vec<u8> {
|
||||
fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper type that allows us to use mutators for Mutators for `&mut `[`Vec`].
|
||||
#[deprecated(since = "0.15.0", note = "Use &mut Vec<u8> directly")]
|
||||
pub type MutVecInput<'a> = &'a mut Vec<u8>;
|
||||
|
||||
impl HasMutatorBytes for &'_ mut Vec<u8> {
|
||||
fn bytes(&self) -> &[u8] {
|
||||
self
|
||||
}
|
||||
|
||||
fn 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.
|
||||
/// Use `value` to fill new slots in case the buffer grows.
|
||||
/// See [`Vec::splice`].
|
||||
fn resize(&mut self, new_len: usize, value: u8);
|
||||
|
||||
/// Extends the given buffer with an iterator. See [`alloc::vec::Vec::extend`]
|
||||
fn extend<'a, I: IntoIterator<Item = &'a u8>>(&mut self, iter: I);
|
||||
|
||||
/// Splices the given target bytes 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>;
|
||||
|
||||
/// Drains the given target bytes according to [`Vec::drain`]'s rules
|
||||
fn drain<R>(&mut self, range: R) -> Drain<'_, u8>
|
||||
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);
|
||||
}
|
||||
@ -240,19 +259,7 @@ impl HasMutatorBytes for Vec<u8> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper type that allows us to use mutators for Mutators for `&mut `[`Vec`].
|
||||
#[deprecated(since = "0.15.0", note = "Use &mut Vec<u8> directly")]
|
||||
pub type MutVecInput<'a> = &'a mut Vec<u8>;
|
||||
|
||||
impl HasMutatorBytes for &mut Vec<u8> {
|
||||
fn bytes(&self) -> &[u8] {
|
||||
self
|
||||
}
|
||||
|
||||
fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
self
|
||||
}
|
||||
|
||||
impl HasMutatorResizableBytes for &mut Vec<u8> {
|
||||
fn resize(&mut self, new_len: usize, value: u8) {
|
||||
self.deref_mut().resize(new_len, value);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use libafl_bolts::{rands::Rand, Error};
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId},
|
||||
impl_default_multipart,
|
||||
inputs::{multi::MultipartInput, HasMutatorBytes, Input},
|
||||
inputs::{multi::MultipartInput, HasMutatorResizableBytes, Input},
|
||||
mutators::{
|
||||
mutations::{
|
||||
rand_range, BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator,
|
||||
@ -119,7 +119,7 @@ impl_default_multipart!(
|
||||
impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverInsertMutator
|
||||
where
|
||||
S: HasCorpus + HasMaxSize + HasRand,
|
||||
I: Input + HasMutatorBytes,
|
||||
I: Input + HasMutatorResizableBytes,
|
||||
S::Corpus: Corpus<Input = MultipartInput<I>>,
|
||||
{
|
||||
fn mutate(
|
||||
@ -255,7 +255,7 @@ where
|
||||
impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverReplaceMutator
|
||||
where
|
||||
S: HasCorpus + HasMaxSize + HasRand,
|
||||
I: Input + HasMutatorBytes,
|
||||
I: Input + HasMutatorResizableBytes,
|
||||
S::Corpus: Corpus<Input = MultipartInput<I>>,
|
||||
{
|
||||
fn mutate(
|
||||
|
@ -16,7 +16,7 @@ use libafl_bolts::{rands::Rand, Named};
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
inputs::HasMutatorBytes,
|
||||
inputs::{HasMutatorBytes, HasMutatorResizableBytes},
|
||||
mutators::{MutationResult, Mutator},
|
||||
nonzero, random_corpus_id_with_disabled,
|
||||
state::{HasCorpus, HasMaxSize, HasRand},
|
||||
@ -464,7 +464,7 @@ pub struct BytesDeleteMutator;
|
||||
impl<I, S> Mutator<I, S> for BytesDeleteMutator
|
||||
where
|
||||
S: HasRand,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let size = input.bytes().len();
|
||||
@ -506,7 +506,7 @@ pub struct BytesExpandMutator;
|
||||
impl<I, S> Mutator<I, S> for BytesExpandMutator
|
||||
where
|
||||
S: HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let max_size = state.max_size();
|
||||
@ -557,7 +557,7 @@ pub struct BytesInsertMutator;
|
||||
impl<I, S> Mutator<I, S> for BytesInsertMutator
|
||||
where
|
||||
S: HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let max_size = state.max_size();
|
||||
@ -620,7 +620,7 @@ pub struct BytesRandInsertMutator;
|
||||
impl<I, S> Mutator<I, S> for BytesRandInsertMutator
|
||||
where
|
||||
S: HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let max_size = state.max_size();
|
||||
@ -815,7 +815,7 @@ pub struct BytesInsertCopyMutator {
|
||||
impl<I, S> Mutator<I, S> for BytesInsertCopyMutator
|
||||
where
|
||||
S: HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let size = input.bytes().len();
|
||||
@ -886,7 +886,7 @@ pub struct BytesSwapMutator {
|
||||
impl<I, S> Mutator<I, S> for BytesSwapMutator
|
||||
where
|
||||
S: HasRand,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let size = input.bytes().len();
|
||||
@ -1104,7 +1104,7 @@ impl CrossoverInsertMutator {
|
||||
other: &[u8],
|
||||
) -> MutationResult
|
||||
where
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
input.resize(size + range.len(), 0);
|
||||
unsafe {
|
||||
@ -1127,7 +1127,7 @@ impl<I, S> Mutator<I, S> for CrossoverInsertMutator
|
||||
where
|
||||
S: HasCorpus + HasRand + HasMaxSize,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorBytes,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let size = input.bytes().len();
|
||||
@ -1315,7 +1315,7 @@ impl<F, O> MappedCrossoverInsertMutator<F, O> {
|
||||
impl<S, F, I, O> Mutator<I, S> for MappedCrossoverInsertMutator<F, O>
|
||||
where
|
||||
S: HasCorpus + HasMaxSize + HasRand,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
O: IntoOptionBytes,
|
||||
F: Fn(&<S::Corpus as Corpus>::Input) -> &O,
|
||||
{
|
||||
@ -1494,7 +1494,7 @@ impl<I, S> Mutator<I, S> for SpliceMutator
|
||||
where
|
||||
S: HasCorpus + HasRand,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorBytes,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
|
@ -25,7 +25,7 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::mutators::str_decode;
|
||||
use crate::{
|
||||
corpus::{CorpusId, HasCurrentCorpusId},
|
||||
inputs::HasMutatorBytes,
|
||||
inputs::HasMutatorResizableBytes,
|
||||
mutators::{
|
||||
buffer_self_copy, mutations::buffer_copy, MultiMutator, MutationResult, Mutator, Named,
|
||||
},
|
||||
@ -306,7 +306,7 @@ pub struct TokenInsert;
|
||||
impl<I, S> Mutator<I, S> for TokenInsert
|
||||
where
|
||||
S: HasMetadata + HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let max_size = state.max_size();
|
||||
@ -375,7 +375,7 @@ pub struct TokenReplace;
|
||||
impl<I, S> Mutator<I, S> for TokenReplace
|
||||
where
|
||||
S: HasMetadata + HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
let size = input.bytes().len();
|
||||
@ -435,7 +435,7 @@ pub struct I2SRandReplace;
|
||||
impl<I, S> Mutator<I, S> for I2SRandReplace
|
||||
where
|
||||
S: HasMetadata + HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
#[expect(clippy::too_many_lines)]
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
@ -636,7 +636,7 @@ where
|
||||
impl<I, S> Mutator<I, S> for I2SRandReplaceBinonly
|
||||
where
|
||||
S: HasMetadata + HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
I: HasMutatorResizableBytes,
|
||||
{
|
||||
#[expect(clippy::too_many_lines)]
|
||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||
@ -1306,7 +1306,7 @@ impl AFLppRedQueen {
|
||||
impl<I, S> MultiMutator<I, S> for AFLppRedQueen
|
||||
where
|
||||
S: HasMetadata + HasRand + HasMaxSize + HasCorpus + HasCurrentCorpusId,
|
||||
I: HasMutatorBytes + From<Vec<u8>>,
|
||||
I: HasMutatorResizableBytes + From<Vec<u8>>,
|
||||
{
|
||||
#[expect(clippy::needless_range_loop, clippy::too_many_lines)]
|
||||
fn multi_mutate(
|
||||
|
@ -11,7 +11,7 @@ use libafl_bolts::{rands::Rand, Error, HasLen, Named};
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
|
||||
inputs::{BytesInput, HasMutatorBytes},
|
||||
inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes},
|
||||
mutators::{rand_range, MutationResult, Mutator, Tokens},
|
||||
nonzero,
|
||||
stages::{
|
||||
|
@ -17,7 +17,7 @@ use crate::{
|
||||
corpus::{Corpus, HasCurrentCorpusId},
|
||||
events::EventFirer,
|
||||
executors::{Executor, HasObservers},
|
||||
inputs::HasMutatorBytes,
|
||||
inputs::{HasMutatorBytes, HasMutatorResizableBytes},
|
||||
mutators::mutations::buffer_copy,
|
||||
nonzero,
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
@ -80,7 +80,7 @@ where
|
||||
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
S: HasCorpus + HasMetadata + HasRand + HasNamedMetadata + HasCurrentCorpusId,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorBytes + Clone,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorResizableBytes + Clone,
|
||||
O: MapObserver,
|
||||
C: AsRef<O> + Named,
|
||||
{
|
||||
@ -157,7 +157,7 @@ where
|
||||
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus + HasMetadata + HasRand + HasCurrentCorpusId + HasCurrentTestcase,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorBytes + Clone,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorResizableBytes + Clone,
|
||||
{
|
||||
#[inline]
|
||||
fn colorize(
|
||||
|
@ -17,7 +17,10 @@ use crate::{
|
||||
corpus::{Corpus, HasCurrentCorpusId},
|
||||
executors::{Executor, HasObservers},
|
||||
feedbacks::map::MapNoveltiesMetadata,
|
||||
inputs::{BytesInput, GeneralizedInputMetadata, GeneralizedItem, HasMutatorBytes},
|
||||
inputs::{
|
||||
BytesInput, GeneralizedInputMetadata, GeneralizedItem, HasMutatorBytes,
|
||||
HasMutatorResizableBytes,
|
||||
},
|
||||
mark_feature_time,
|
||||
observers::{CanTrack, MapObserver, ObserversTuple},
|
||||
require_novelties_tracking,
|
||||
|
@ -11,7 +11,7 @@ use std::{
|
||||
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
inputs::{BytesInput, HasMutatorBytes},
|
||||
inputs::{BytesInput, HasMutatorBytes, HasMutatorResizableBytes},
|
||||
mutators::{
|
||||
ComposedByMutations, MutationId, MutationResult, Mutator, MutatorsTuple, ScheduledMutator,
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user