pub trait Mutate<T>where
T: ?Sized,{
// Required method
fn mutate(
&mut self,
mutations: &mut Candidates<'_>,
value: &mut T,
) -> Result<()>;
// Provided methods
fn generate_via_mutate(
&mut self,
context: &mut Context,
iters: usize,
) -> Result<T>
where T: Sized + Default { ... }
fn or<M>(self, other: M) -> Or<Self, M>
where Self: Sized { ... }
fn map<F>(self, f: F) -> Map<Self, F>
where Self: Sized,
F: FnMut(&mut Context, &mut T) -> Result<()> { ... }
fn proj<F, U>(self, f: F) -> Proj<Self, F>
where Self: Sized,
F: FnMut(&mut U) -> &mut T { ... }
fn by_ref(&mut self) -> &mut Self
where Self: Sized { ... }
}Expand description
A trait for mutating values.
You can think of Mutate<T> as a streaming iterator of Ts but instead of
internally containing and yielding access to the Ts, it takes an &mut T
as an argument and mutates it in place.
The main method is the mutate method, which applies one
of many potential mutations to the given value, or returns an error.
§Example: Using a Type’s Default Mutator
Many types implement the DefaultMutate trait, which provides a default
mutator for that type. You can use this default mutator by calling
mutate on a Session with a value of
that type.
use mutatis::{Context, Session};
let mut session = Session::new();
let mut x = 1234;
session.mutate(&mut x)?;
for _ in 0..5 {
session.mutate(&mut x)?;
println!("mutated x is {x}");
}
panic!();
// Example output:
//
// mutated x is 1682887620§Example: Using Custom Mutators
use mutatis::{mutators as m, Mutate, Session};
// Define a mutator for `u32`s that only creates multiples-of-four
let mut mutator = m::u32()
.map(|_ctx, x| {
*x = *x & !3; // Clear the bottom two bits to make `x` a multiple of four.
Ok(())
});
// Mutate a value a bunch of times!
let mut x = 1234;
let mut session = Session::new();
for _ in 0..5 {
session.mutate_with(&mut mutator, &mut x)?;
println!("mutated x is {x}");
}
panic!();
// Example output:
//
// mutated x is 2436583184
// mutated x is 2032949584
// mutated x is 2631247496
// mutated x is 199875380
// mutated x is 3751781284§Exhaustion
A mutator may become exhausted, meaning that it doesn’t have any more
mutations it can perform for a given value. In this case, the mutator may
return an error of kind
ErrorKind::Exhausted. Many mutators
are effectively inexhaustible (or it would be prohibitively expensive to
precisely track whether they’ve already emitted every possible variant of a
value) and therefore it is valid for a mutator to never report exhaustion.
You may also ignore exhaustion errors via the
mutatis::error::ResultExt::ignore_exhausted
extension method.
Note that you should never return an ErrorKind::Exhausted error from your
own manual Mutate implementations. Instead, simply avoid registering any
candidate mutations and, if no other sibling or parent mutators have any
potential mutations either, then the library will return an exhaustion error
for you.
§Many-to-Many
Note that the relationship between mutator types and mutated types is not one-to-one: a single mutator type can mutate many different types, and a single type can be mutated by many different mutator types. This gives you the flexibility to define new mutators for existing types (including those that are not defined by your own crate).
use mutatis::{
mutators as m, DefaultMutate, Mutate, Session, Candidates,
Result,
};
#[derive(Mutate)] // Derive a default mutator for `Foo`s.
pub struct Foo(u32);
// Also define and implement a second mutator type for `Foo` by hand!
pub struct AlignedFooMutator{
inner: <Foo as DefaultMutate>::DefaultMutate,
alignment: u32,
}
impl Mutate<Foo> for AlignedFooMutator {
fn mutate(&mut self, mutations: &mut Candidates, foo: &mut Foo) -> Result<()> {
self.inner
.by_ref()
.map(|_context, foo| {
// Clear the bottom bits to keep the `Foo` "aligned".
debug_assert!(self.alignment.is_power_of_two());
let mask = !(self.alignment - 1);
foo.0 = foo.0 & mask;
Ok(())
})
.mutate(mutations, foo)
}
}Required Methods§
Sourcefn mutate(
&mut self,
mutations: &mut Candidates<'_>,
value: &mut T,
) -> Result<()>
fn mutate( &mut self, mutations: &mut Candidates<'_>, value: &mut T, ) -> Result<()>
Pseudo-randomly mutate the given value.
§Calling the mutate Method
If you just want to mutate a value, use Session::mutate or
Session::mutate_with instead of invoking this trait method
directly. See their documentation for more details.
§Implementing the mutate Method
Register every mutation that a mutator could perform by invoking the
mutations.mutation(...) function, passing in
a closure that performs that mutation, updating value and self as
necessary.
mutate implementations must only mutate self and the given value
from inside a registered mutation closure. It must not update self or
modify value outside of one of those mutation closures.
Furthermore, all mutate implementations must be deterministic: given
the same inputs, the same set of mutations must be registered in the
same order.
These requirements exist because, under the hood, the mutate method is
called twice for every mutation that is actually performed:
-
First,
mutateis called to count all the possible mutations that could be performed. In this phase, the mutation closures are ignored. -
Next, a random index
ibetween0and that count is chosen. This is the index of the mutation that we will actually be applied. -
Finally,
mutateis called again. In this phase, theith mutation closure is invoked, applying the mutation, while all others are ignored.
Note that the registered mutations are roughly uniformly selected from, so if you wish to skew the distribution of mutations, making certain mutations more probable than others, you may register mutations multiple times or register overlapping mutations.
§Example
use mutatis::{
mutators as m, Generate, Mutate, Session, Candidates,
Result,
};
// A custom mutator that creates pairs where the first element is less
// than or equal to the second.
pub struct OrderedPairs;
impl Mutate<(u64, u64)> for OrderedPairs {
fn mutate(
&mut self,
mutations: &mut Candidates<'_>,
pair: &mut (u64, u64),
) -> Result<()> {
// We *cannot* mutate `self` or `pair` out here.
if *pair != (0, 0) {
// Note: we register this mutation -- even when not
// shrinking and even though the subsequent mutation
// subsumes this one -- to bias the distribution towards
// smaller values.
mutations.mutation(|ctx| {
// We *can* mutate `self` and `pair` inside here.
let a = m::mrange(0..=pair.0).generate(ctx)?;
let b = m::mrange(0..=pair.1).generate(ctx)?;
*pair = (a.min(b), a.max(b));
Ok(())
})?;
}
if !mutations.shrink() {
// Only register this fully-general mutation when we are
// not shrinking, as this can grow the pair.
mutations.mutation(|ctx| {
// We *can* mutate `self` and `pair` inside here.
let a = m::u64().generate(ctx)?;
let b = m::u64().generate(ctx)?;
*pair = (a.min(b), a.max(b));
Ok(())
})?;
}
Ok(())
}
}
// Create a pair.
let mut pair = (1000, 2000);
// And mutate it a bunch of times!
let mut session = Session::new();
for _ in 0..3 {
session.mutate_with(&mut OrderedPairs, &mut pair)?;
println!("mutated pair is {pair:?}");
}
// Example output:
//
// mutated pair is (11, 861)
// mutated pair is (8, 818)
// mutated pair is (3305948426120559093, 16569598107406464568)Provided Methods§
Sourcefn generate_via_mutate(
&mut self,
context: &mut Context,
iters: usize,
) -> Result<T>
fn generate_via_mutate( &mut self, context: &mut Context, iters: usize, ) -> Result<T>
Generate a new value by mutating its default value iters times.
The iters argument controls how many mutations are performed. More
mutations will lead to generated values that are generally more
different from the default value, but will take longer to generate. A
small number, even just 1, is usually sufficient, because the fuzzer
will continue to mutate the input.
This is a helper utility that allows you to implement Generate<T> “for
free” if you already have T: Default and Mutate<T> implementations.
This is especially useful when implementing Generate<T> with a uniform
output distribution is otherwise difficult. For example, the natural way
to write a generator is often a decision tree, but keeping decision
trees balanced is difficult, which can easily bias the results
(especially when the choices are abstracted away behind helper
functions). Consider the following psuedocode:
if ctx.gen_bool() {
A
} else if ctx.gen_bool() {
B
} else if ctx.gen_bool() {
C
} else {
D
}We would ideally want to generate A, B, C, and D with equal
probability, but we actually end up generating A 50% of the time, B
25% of the time, and C and D 12.5% of the time. Of course, this is
fairly obvious when we look at this code directly, but it may be
non-obvious in other cases due to code factoring.
§Example
Here we are generating random expressions, which contain factors, which contain terms. We don’t want to bias towards generating more top-level expressions than top-level factors, for example.
use mutatis::{
mutators as m, Candidates, Context, DefaultMutate, Generate, Mutate, MutateInRange,
Result, Session,
};
#[derive(Debug, Mutate)]
enum Expr {
Add(Factor, Factor),
Sub(Factor, Factor),
Factor(Factor),
}
impl Default for Expr {
fn default() -> Self {
Expr::Factor(Default::default())
}
}
impl Generate<Expr> for ExprMutator {
fn generate(&mut self, context: &mut Context) -> Result<Expr> {
self.generate_via_mutate(context, 2)
}
}
#[derive(Debug, Mutate)]
enum Factor {
Mul(Term, Term),
Div(Term, Term),
Term(Term),
}
impl Default for Factor {
fn default() -> Self {
Factor::Term(Default::default())
}
}
impl Generate<Factor> for FactorMutator {
fn generate(&mut self, context: &mut Context) -> Result<Factor> {
self.generate_via_mutate(context, 2)
}
}
#[derive(Debug, Mutate)]
enum Term {
Var(Var),
Num(u8),
}
impl Default for Term {
fn default() -> Self {
Term::Num(Default::default())
}
}
impl Generate<Term> for TermMutator {
fn generate(&mut self, context: &mut Context) -> Result<Term> {
self.generate_via_mutate(context, 1)
}
}
#[derive(Default, Debug)]
struct Var(char);
#[derive(Default)]
struct VarMutator;
impl Mutate<Var> for VarMutator {
fn mutate(&mut self, c: &mut Candidates<'_>, var: &mut Var) -> Result<()> {
let range = 'a'..='z';
m::char().mutate_in_range(c, &mut var.0, &range)
}
}
impl Generate<Var> for VarMutator {
fn generate(&mut self, context: &mut Context) -> Result<Var> {
self.generate_via_mutate(context, 1)
}
}
impl DefaultMutate for Var {
type DefaultMutate = VarMutator;
}
let mut session = Session::new();
for _ in 0..5 {
let expr: Expr = session.generate()?;
println!("expr = {expr:?}");
}
// Example output:
//
// expr = Factor(Mul(Num(12), Var(Var('z'))))
// expr = Sub(Div(Num(185), Var(Var('k'))), Div(Num(105), Var(Var('l'))))
// expr = Factor(Mul(Num(26), Var(Var('y'))))
// expr = Sub(Term(Num(121)), Mul(Var(Var('k')), Num(69)))
// expr = Factor(Term(Var(Var('p'))))Sourcefn or<M>(self, other: M) -> Or<Self, M>where
Self: Sized,
fn or<M>(self, other: M) -> Or<Self, M>where
Self: Sized,
Create a new mutator that performs either this mutation or the other
mutation.
§Example
use mutatis::{mutators as m, Mutate, Session};
let mut session = Session::new();
// Either generate `-1`...
let mut mutator = m::just(-1)
// ...or values in the range `0x40..=0x4f`...
.or(m::mrange(0x40..=0x4f))
// ...or values with just a single bit set.
.or(m::mrange(0..=31).map(|_ctx, x| {
*x = 1 << *x;
Ok(())
}));
let mut value = 0;
for _ in 0..5 {
session.mutate_with(&mut mutator, &mut value)?;
println!("mutated value is {value:#x}");
}
// Example output:
//
// mutated value is 0x4a
// mutated value is 0xffffffff
// mutated value is 0x400000
// mutated value is 0x20000000
// mutated value is 0x4eSourcefn map<F>(self, f: F) -> Map<Self, F>
fn map<F>(self, f: F) -> Map<Self, F>
Map a function over the mutations produced by this mutator.
§Example
use mutatis::{mutators as m, Mutate, Session};
let mut session = Session::new();
let mut mutator = m::i32().map(|context, value| {
// Ensure that the value is always positive.
if *value <= 0 {
*value = i32::from(context.rng().gen_u16());
}
Ok(())
});
let mut value = -42;
for _ in 0..10 {
session.mutate_with(&mut mutator, &mut value)?;
assert!(value > 0, "the mutated value is always positive");
}Sourcefn proj<F, U>(self, f: F) -> Proj<Self, F>
fn proj<F, U>(self, f: F) -> Proj<Self, F>
Given a projection function F: FnMut(&mut U) -> &mut T, turn this
Mutate<T> into a Mutate<U>.
§Example
use mutatis::{mutators as m, Mutate, Session};
#[derive(Debug)]
pub struct NewType(u32);
let mut value = NewType(0);
let mut mutator = m::u32().proj(|x: &mut NewType| &mut x.0);
let mut session = Session::new();
for _ in 0..3 {
session.mutate_with(&mut mutator, &mut value)?;
println!("mutated value is {value:?}");
}
// Example output:
//
// mutated value is NewType(3729462868)
// mutated value is NewType(49968845)
// mutated value is NewType(2440803355)Sourcefn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Borrows a mutator, rather than consuming it.
This is useful to allow applying mutator adapters while still retaining ownership of the original mutator.
§Example
use mutatis::{mutators as m, Mutate, Session};
let mut mutator = m::u32().map(|_context, x| {
*x = *x & !3;
Ok(())
});
let mut value = 1234;
let mut session = Session::new();
{
let mut borrowed_mutator = mutator.by_ref().map(|_context, x| {
*x = x.wrapping_add(1);
Ok(())
});
session.mutate_with(&mut borrowed_mutator, &mut value)?;
println!("first mutated value is {value}");
}
// In the outer scope, we can still use the original mutator.
session.mutate_with(&mut mutator, &mut value)?;
println!("second mutated value is {value}");
// Example output:
//
// first mutated value is 3729462869
// second mutated value is 49968844Implementations on Foreign Types§
Implementors§
impl Mutate<IpAddr> for IpAddrMutator
std only.impl Mutate<SocketAddr> for SocketAddrMutator
std only.impl Mutate<bool> for Bool
impl Mutate<char> for AsciiChar
impl Mutate<char> for Char
impl Mutate<f32> for F32
impl Mutate<f64> for F64
impl Mutate<i8> for I8
impl Mutate<i16> for I16
impl Mutate<i32> for I32
impl Mutate<i64> for I64
impl Mutate<i128> for I128
impl Mutate<isize> for Isize
impl Mutate<u8> for U8
impl Mutate<u16> for U16
impl Mutate<u32> for U32
impl Mutate<u64> for U64
impl Mutate<u128> for U128
impl Mutate<()> for Unit
impl Mutate<usize> for Usize
impl Mutate<CString> for CStringMutator
alloc only.impl Mutate<Ipv4Addr> for Ipv4AddrMutator
std only.impl Mutate<Ipv6Addr> for Ipv6AddrMutator
std only.impl Mutate<SocketAddrV4> for SocketAddrV4Mutator
std only.impl Mutate<SocketAddrV6> for SocketAddrV6Mutator
std only.impl Mutate<NonZero<i8>> for NonZeroI8
impl Mutate<NonZero<i16>> for NonZeroI16
impl Mutate<NonZero<i32>> for NonZeroI32
impl Mutate<NonZero<i64>> for NonZeroI64
impl Mutate<NonZero<i128>> for NonZeroI128
impl Mutate<NonZero<isize>> for NonZeroIsize
impl Mutate<NonZero<u8>> for NonZeroU8
impl Mutate<NonZero<u16>> for NonZeroU16
impl Mutate<NonZero<u32>> for NonZeroU32
impl Mutate<NonZero<u64>> for NonZeroU64
impl Mutate<NonZero<u128>> for NonZeroU128
impl Mutate<NonZero<usize>> for NonZeroUsize
impl Mutate<Atomic<bool>> for AtomicBool
impl Mutate<Atomic<isize>> for AtomicIsize
impl Mutate<Atomic<usize>> for AtomicUsize
impl Mutate<OsString> for OsStringMutator
std only.impl Mutate<PathBuf> for PathBufMutator
std only.impl<'a, M, B> Mutate<Cow<'a, B>> for CowMutator<M>
alloc only.impl<C> Mutate<String> for StringMutator<C>
alloc only.impl<F, T> Mutate<T> for FromFn<F, T>
impl<KM, VM, K, V> Mutate<BTreeMap<K, V>> for BTreeMap<KM, VM>
alloc only.impl<KM, VM, K, V> Mutate<HashMap<K, V>> for HashMap<KM, VM>
std only.impl<M0, T0> Mutate<(T0,)> for Tuple1<M0>where
M0: Mutate<T0>,
impl<M0, T0, M1, T1> Mutate<(T0, T1)> for Tuple2<M0, M1>
impl<M0, T0, M1, T1, M2, T2> Mutate<(T0, T1, T2)> for Tuple3<M0, M1, M2>
impl<M0, T0, M1, T1, M2, T2, M3, T3> Mutate<(T0, T1, T2, T3)> for Tuple4<M0, M1, M2, M3>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4> Mutate<(T0, T1, T2, T3, T4)> for Tuple5<M0, M1, M2, M3, M4>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5> Mutate<(T0, T1, T2, T3, T4, T5)> for Tuple6<M0, M1, M2, M3, M4, M5>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6> Mutate<(T0, T1, T2, T3, T4, T5, T6)> for Tuple7<M0, M1, M2, M3, M4, M5, M6>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7)> for Tuple8<M0, M1, M2, M3, M4, M5, M6, M7>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8)> for Tuple9<M0, M1, M2, M3, M4, M5, M6, M7, M8>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)> for Tuple10<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> for Tuple11<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)> for Tuple12<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11, M12, T12> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)> for Tuple13<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11, M12, T12, M13, T13> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)> for Tuple14<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11, M12, T12, M13, T13, M14, T14> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)> for Tuple15<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14>
impl<M0, T0, M1, T1, M2, T2, M3, T3, M4, T4, M5, T5, M6, T6, M7, T7, M8, T8, M9, T9, M10, T10, M11, T11, M12, T12, M13, T13, M14, T14, M15, T15> Mutate<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)> for Tuple16<M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15>
impl<M1, M2, T> Mutate<T> for Or<M1, M2>
impl<M, F, T> Mutate<T> for Map<M, F>
impl<M, F, T, U> Mutate<T> for Proj<M, F>
impl<M, T> Mutate<Bound<T>> for Bound<M>where
M: Generate<T>,
impl<M, T> Mutate<Option<T>> for Option<M>where
M: Generate<T>,
impl<M, T> Mutate<Option<T>> for Some<M>where
M: Generate<T>,
impl<M, T> Mutate<Box<T>> for Boxed<M>where
M: Mutate<T>,
alloc only.impl<M, T> Mutate<BinaryHeap<T>> for BinaryHeap<M>
alloc only.impl<M, T> Mutate<BTreeSet<T>> for BTreeSet<M>
alloc only.impl<M, T> Mutate<LinkedList<T>> for LinkedList<M>
alloc only.impl<M, T> Mutate<VecDeque<T>> for VecDeque<M>
alloc only.impl<M, T> Mutate<Vec<T>> for Vec<M>where
M: Generate<T>,
alloc only.impl<M, T> Mutate<Cell<T>> for Cell<M>where
M: Mutate<T>,
impl<M, T> Mutate<RefCell<T>> for RefCell<M>where
M: Mutate<T>,
impl<M, T> Mutate<UnsafeCell<T>> for UnsafeCellMutator<M>where
M: Mutate<T>,
impl<M, T> Mutate<Reverse<T>> for Reverse<M>where
M: Mutate<T>,
impl<M, T> Mutate<Wrapping<T>> for Wrapping<M>where
M: Mutate<T>,
impl<M, T> Mutate<Range<T>> for Range<M>where
M: Mutate<T>,
impl<M, T> Mutate<RangeFrom<T>> for RangeFrom<M>where
M: Mutate<T>,
impl<M, T> Mutate<RangeInclusive<T>> for RangeInclusive<M>
impl<M, T> Mutate<RangeTo<T>> for RangeTo<M>where
M: Mutate<T>,
impl<M, T> Mutate<RangeToInclusive<T>> for RangeToInclusive<M>where
M: Mutate<T>,
impl<M, T> Mutate<HashSet<T>> for HashSet<M>
std only.impl<M, T> Mutate<Mutex<T>> for MutexMutator<M>where
M: Mutate<T>,
std only.