mutations
This commit is contained in:
parent
8b22a06ec9
commit
95281dbfef
@ -1,26 +1,28 @@
|
|||||||
use core::{marker::PhantomData};
|
use core::{marker::PhantomData};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{CorpusScheduler},
|
corpus::{CorpusScheduler, Corpus},
|
||||||
events::{Event, EventManager},
|
events::{Event, EventManager},
|
||||||
executors::{Executor},
|
executors::{Executor},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
stages::StagesTuple,
|
stages::StagesTuple,
|
||||||
utils::{current_milliseconds, current_time},
|
state::{HasRand, HasCorpus},
|
||||||
|
utils::{Rand, current_milliseconds, current_time},
|
||||||
Error
|
Error
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Holds a set of stages
|
/// Holds a set of stages
|
||||||
pub trait HasStages<ST>
|
pub trait HasStages<ST, I>
|
||||||
where
|
where
|
||||||
ST: StagesTuple,
|
ST: StagesTuple<I>,
|
||||||
|
I: Input
|
||||||
{
|
{
|
||||||
fn stages(&self) -> &ST;
|
fn stages(&self) -> &ST;
|
||||||
|
|
||||||
fn stages_mut(&mut self) -> &mut ST;
|
fn stages_mut(&mut self) -> &mut ST;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds a set of stages
|
/// Holds a scheduler
|
||||||
pub trait HasCorpusScheduler<CS>
|
pub trait HasCorpusScheduler<CS>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler,
|
CS: CorpusScheduler,
|
||||||
@ -31,7 +33,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The main fuzzer trait.
|
/// The main fuzzer trait.
|
||||||
pub trait Fuzzer<CS, ST, I>: HasCorpusScheduler<CS> + HasStages<ST>
|
pub trait Fuzzer<CS, ST, I>: HasCorpusScheduler<CS> + HasStages<ST, I>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler,
|
CS: CorpusScheduler,
|
||||||
ST: StagesTuple<I>,
|
ST: StagesTuple<I>,
|
||||||
@ -45,16 +47,7 @@ where
|
|||||||
) -> Result<usize, Error>
|
) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
E: Executor<I>,
|
E: Executor<I>;
|
||||||
{
|
|
||||||
let idx = self.scheduler().next(state)?;
|
|
||||||
|
|
||||||
self.stages()
|
|
||||||
.perform_all(executor, state, manager, idx)?;
|
|
||||||
|
|
||||||
manager.process(state, executor)?;
|
|
||||||
Ok(idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fuzz_loop<E, EM, S>(
|
fn fuzz_loop<E, EM, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -64,25 +57,7 @@ where
|
|||||||
) -> Result<usize, Error>
|
) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
E: Executor<I>,
|
E: Executor<I>;
|
||||||
{
|
|
||||||
let mut last = current_milliseconds();
|
|
||||||
loop {
|
|
||||||
self.fuzz_one(executor, state, manager)?;
|
|
||||||
let cur = current_milliseconds();
|
|
||||||
if cur - last > 60 * 100 {
|
|
||||||
last = cur;
|
|
||||||
manager.fire(
|
|
||||||
state,
|
|
||||||
Event::UpdateStats {
|
|
||||||
executions: state.executions(),
|
|
||||||
time: current_time(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Your default fuzzer instance, for everyday use.
|
/// Your default fuzzer instance, for everyday use.
|
||||||
@ -97,7 +72,7 @@ where
|
|||||||
stages: ST,
|
stages: ST,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CS, ST, I> HasStages<ST> for StdFuzzer<CS, ST, I>
|
impl<CS, ST, I> HasStages<ST, I> for StdFuzzer<CS, ST, I>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler,
|
CS: CorpusScheduler,
|
||||||
ST: StagesTuple<I>,
|
ST: StagesTuple<I>,
|
||||||
@ -127,6 +102,67 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<CS, ST, I> Fuzzer<CS, ST, I> for StdFuzzer<CS, ST, I>
|
||||||
|
where
|
||||||
|
CS: CorpusScheduler,
|
||||||
|
ST: StagesTuple<I>,
|
||||||
|
I: Input
|
||||||
|
{
|
||||||
|
fn fuzz_one<C, E, EM, R, S>(
|
||||||
|
&mut self,
|
||||||
|
executor: &mut E,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
) -> Result<usize, Error>
|
||||||
|
where
|
||||||
|
EM: EventManager<I>,
|
||||||
|
E: Executor<I>,
|
||||||
|
S: HasCorpus<C, I> + HasRand<R>,
|
||||||
|
C: Corpus<I>,
|
||||||
|
R: Rand
|
||||||
|
{
|
||||||
|
let idx = self.scheduler().next(state)?;
|
||||||
|
|
||||||
|
self.stages()
|
||||||
|
.perform_all(executor, state, manager, idx)?;
|
||||||
|
|
||||||
|
manager.process(state, executor)?;
|
||||||
|
Ok(idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fuzz_loop<C, E, EM, R, S>(
|
||||||
|
&mut self,
|
||||||
|
executor: &mut E,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
) -> Result<usize, Error>
|
||||||
|
where
|
||||||
|
EM: EventManager<I>,
|
||||||
|
E: Executor<I>,
|
||||||
|
S: HasCorpus<C, I> + HasRand<R>,
|
||||||
|
C: Corpus<I>,
|
||||||
|
R: Rand
|
||||||
|
{
|
||||||
|
let mut last = current_milliseconds();
|
||||||
|
loop {
|
||||||
|
self.fuzz_one(executor, state, manager)?;
|
||||||
|
let cur = current_milliseconds();
|
||||||
|
if cur - last > 60 * 100 {
|
||||||
|
last = cur;
|
||||||
|
manager.fire(
|
||||||
|
state,
|
||||||
|
Event::UpdateStats {
|
||||||
|
executions: state.executions(),
|
||||||
|
time: current_time(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
},
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<CS, ST, I> StdFuzzer<CS, ST, I>
|
impl<CS, ST, I> StdFuzzer<CS, ST, I>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler,
|
CS: CorpusScheduler,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
inputs::{HasBytesVec, Input},
|
inputs::{HasBytesVec, Input},
|
||||||
mutators::Corpus,
|
corpus::Corpus,
|
||||||
mutators::*,
|
mutators::*,
|
||||||
|
state::{HasRand, HasCorpus},
|
||||||
utils::Rand,
|
utils::Rand,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
@ -15,42 +16,6 @@ use std::{
|
|||||||
io::{BufRead, BufReader},
|
io::{BufRead, BufReader},
|
||||||
};
|
};
|
||||||
|
|
||||||
const ARITH_MAX: u64 = 35;
|
|
||||||
|
|
||||||
const INTERESTING_8: [i8; 9] = [-128, -1, 0, 1, 16, 32, 64, 100, 127];
|
|
||||||
const INTERESTING_16: [i16; 19] = [
|
|
||||||
-128, -1, 0, 1, 16, 32, 64, 100, 127, -32768, -129, 128, 255, 256, 512, 1000, 1024, 4096, 32767,
|
|
||||||
];
|
|
||||||
const INTERESTING_32: [i32; 27] = [
|
|
||||||
-128,
|
|
||||||
-1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
16,
|
|
||||||
32,
|
|
||||||
64,
|
|
||||||
100,
|
|
||||||
127,
|
|
||||||
-32768,
|
|
||||||
-129,
|
|
||||||
128,
|
|
||||||
255,
|
|
||||||
256,
|
|
||||||
512,
|
|
||||||
1000,
|
|
||||||
1024,
|
|
||||||
4096,
|
|
||||||
32767,
|
|
||||||
-2147483648,
|
|
||||||
-100663046,
|
|
||||||
-32769,
|
|
||||||
32768,
|
|
||||||
65535,
|
|
||||||
65536,
|
|
||||||
100663045,
|
|
||||||
2147483647,
|
|
||||||
];
|
|
||||||
|
|
||||||
/// The result of a mutation.
|
/// The result of a mutation.
|
||||||
/// If the mutation got skipped, the target
|
/// If the mutation got skipped, the target
|
||||||
/// will not be executed with the returned input.
|
/// will not be executed with the returned input.
|
||||||
@ -62,24 +27,21 @@ pub enum MutationResult {
|
|||||||
|
|
||||||
// TODO maybe the mutator arg is not needed
|
// TODO maybe the mutator arg is not needed
|
||||||
/// The generic function type that identifies mutations
|
/// The generic function type that identifies mutations
|
||||||
pub type MutationFunction<I, M, R, S> =
|
pub type MutationFunction<I, M, S> =
|
||||||
fn(&mut M, &mut R, &mut S, &mut I) -> Result<MutationResult, Error>;
|
fn(&mut M, &mut S, &mut I) -> Result<MutationResult, Error>;
|
||||||
|
|
||||||
pub trait ComposedByMutations<C, I, R, S>
|
pub trait ComposedByMutations<I, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
|
||||||
{
|
{
|
||||||
/// Get a mutation by index
|
/// Get a mutation by index
|
||||||
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, R, S>;
|
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, S>;
|
||||||
|
|
||||||
/// Get the number of mutations
|
/// Get the number of mutations
|
||||||
fn mutations_count(&self) -> usize;
|
fn mutations_count(&self) -> usize;
|
||||||
|
|
||||||
/// Add a mutation
|
/// Add a mutation
|
||||||
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, R, S>);
|
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, S>);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mem move in the own vec
|
/// Mem move in the own vec
|
||||||
@ -125,21 +87,58 @@ fn buffer_set(data: &mut [u8], from: usize, len: usize, val: u8) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const ARITH_MAX: u64 = 35;
|
||||||
|
|
||||||
|
const INTERESTING_8: [i8; 9] = [-128, -1, 0, 1, 16, 32, 64, 100, 127];
|
||||||
|
const INTERESTING_16: [i16; 19] = [
|
||||||
|
-128, -1, 0, 1, 16, 32, 64, 100, 127, -32768, -129, 128, 255, 256, 512, 1000, 1024, 4096, 32767,
|
||||||
|
];
|
||||||
|
const INTERESTING_32: [i32; 27] = [
|
||||||
|
-128,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
16,
|
||||||
|
32,
|
||||||
|
64,
|
||||||
|
100,
|
||||||
|
127,
|
||||||
|
-32768,
|
||||||
|
-129,
|
||||||
|
128,
|
||||||
|
255,
|
||||||
|
256,
|
||||||
|
512,
|
||||||
|
1000,
|
||||||
|
1024,
|
||||||
|
4096,
|
||||||
|
32767,
|
||||||
|
-2147483648,
|
||||||
|
-100663046,
|
||||||
|
-32769,
|
||||||
|
32768,
|
||||||
|
65535,
|
||||||
|
65536,
|
||||||
|
100663045,
|
||||||
|
2147483647,
|
||||||
|
];
|
||||||
|
|
||||||
/// Bitflip mutation for inputs with a bytes vector
|
/// Bitflip mutation for inputs with a bytes vector
|
||||||
pub fn mutation_bitflip<I, M, R, S>(
|
pub fn mutation_bitflip<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
state: &mut S,
|
||||||
_: &mut S,
|
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
R: Rand,
|
S: HasRand<R>,
|
||||||
|
R: Rand
|
||||||
{
|
{
|
||||||
if input.bytes().len() == 0 {
|
if input.bytes().len() == 0 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let bit = rand.below((input.bytes().len() << 3) as u64) as usize;
|
let bit = state.rand_mut().below((input.bytes().len() << 3) as u64) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
*input.bytes_mut().get_unchecked_mut(bit >> 3) ^= (128 >> (bit & 7)) as u8;
|
*input.bytes_mut().get_unchecked_mut(bit >> 3) ^= (128 >> (bit & 7)) as u8;
|
||||||
@ -150,18 +149,19 @@ where
|
|||||||
|
|
||||||
pub fn mutation_byteflip<I, M, R, S>(
|
pub fn mutation_byteflip<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() == 0 {
|
if input.bytes().len() == 0 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
*input.bytes_mut().get_unchecked_mut(idx) ^= 0xff;
|
*input.bytes_mut().get_unchecked_mut(idx) ^= 0xff;
|
||||||
@ -172,18 +172,19 @@ where
|
|||||||
|
|
||||||
pub fn mutation_byteinc<I, M, R, S>(
|
pub fn mutation_byteinc<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() == 0 {
|
if input.bytes().len() == 0 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
let ptr = input.bytes_mut().get_unchecked_mut(idx);
|
let ptr = input.bytes_mut().get_unchecked_mut(idx);
|
||||||
@ -195,18 +196,19 @@ where
|
|||||||
|
|
||||||
pub fn mutation_bytedec<I, M, R, S>(
|
pub fn mutation_bytedec<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() == 0 {
|
if input.bytes().len() == 0 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
let ptr = input.bytes_mut().get_unchecked_mut(idx);
|
let ptr = input.bytes_mut().get_unchecked_mut(idx);
|
||||||
@ -218,18 +220,19 @@ where
|
|||||||
|
|
||||||
pub fn mutation_byteneg<I, M, R, S>(
|
pub fn mutation_byteneg<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() == 0 {
|
if input.bytes().len() == 0 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
*input.bytes_mut().get_unchecked_mut(idx) = !(*input.bytes().get_unchecked(idx));
|
*input.bytes_mut().get_unchecked_mut(idx) = !(*input.bytes().get_unchecked(idx));
|
||||||
@ -240,21 +243,22 @@ where
|
|||||||
|
|
||||||
pub fn mutation_byterand<I, M, R, S>(
|
pub fn mutation_byterand<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() == 0 {
|
if input.bytes().len() == 0 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
*input.bytes_mut().get_unchecked_mut(idx) = rand.below(256) as u8;
|
*input.bytes_mut().get_unchecked_mut(idx) = state.rand_mut().below(256) as u8;
|
||||||
}
|
}
|
||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
@ -262,23 +266,24 @@ where
|
|||||||
|
|
||||||
pub fn mutation_byteadd<I, M, R, S>(
|
pub fn mutation_byteadd<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() == 0 {
|
if input.bytes().len() == 0 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut u8;
|
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut u8;
|
||||||
let num = 1 + rand.below(ARITH_MAX) as u8;
|
let num = 1 + state.rand_mut().below(ARITH_MAX) as u8;
|
||||||
match rand.below(2) {
|
match state.rand_mut().below(2) {
|
||||||
0 => *ptr = (*ptr).wrapping_add(num),
|
0 => *ptr = (*ptr).wrapping_add(num),
|
||||||
_ => *ptr = (*ptr).wrapping_sub(num),
|
_ => *ptr = (*ptr).wrapping_sub(num),
|
||||||
};
|
};
|
||||||
@ -289,23 +294,24 @@ where
|
|||||||
|
|
||||||
pub fn mutation_wordadd<I, M, R, S>(
|
pub fn mutation_wordadd<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() < 2 {
|
if input.bytes().len() < 2 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64 - 1) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64 - 1) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u16;
|
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u16;
|
||||||
let num = 1 + rand.below(ARITH_MAX) as u16;
|
let num = 1 + state.rand_mut().below(ARITH_MAX) as u16;
|
||||||
match rand.below(4) {
|
match state.rand_mut().below(4) {
|
||||||
0 => *ptr = (*ptr).wrapping_add(num),
|
0 => *ptr = (*ptr).wrapping_add(num),
|
||||||
1 => *ptr = (*ptr).wrapping_sub(num),
|
1 => *ptr = (*ptr).wrapping_sub(num),
|
||||||
2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(),
|
2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(),
|
||||||
@ -318,23 +324,24 @@ where
|
|||||||
|
|
||||||
pub fn mutation_dwordadd<I, M, R, S>(
|
pub fn mutation_dwordadd<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() < 4 {
|
if input.bytes().len() < 4 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64 - 3) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64 - 3) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u32;
|
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u32;
|
||||||
let num = 1 + rand.below(ARITH_MAX) as u32;
|
let num = 1 + state.rand_mut().below(ARITH_MAX) as u32;
|
||||||
match rand.below(4) {
|
match state.rand_mut().below(4) {
|
||||||
0 => *ptr = (*ptr).wrapping_add(num),
|
0 => *ptr = (*ptr).wrapping_add(num),
|
||||||
1 => *ptr = (*ptr).wrapping_sub(num),
|
1 => *ptr = (*ptr).wrapping_sub(num),
|
||||||
2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(),
|
2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(),
|
||||||
@ -347,23 +354,24 @@ where
|
|||||||
|
|
||||||
pub fn mutation_qwordadd<I, M, R, S>(
|
pub fn mutation_qwordadd<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() < 8 {
|
if input.bytes().len() < 8 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64 - 7) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64 - 7) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u64;
|
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u64;
|
||||||
let num = 1 + rand.below(ARITH_MAX) as u64;
|
let num = 1 + state.rand_mut().below(ARITH_MAX) as u64;
|
||||||
match rand.below(4) {
|
match state.rand_mut().below(4) {
|
||||||
0 => *ptr = (*ptr).wrapping_add(num),
|
0 => *ptr = (*ptr).wrapping_add(num),
|
||||||
1 => *ptr = (*ptr).wrapping_sub(num),
|
1 => *ptr = (*ptr).wrapping_sub(num),
|
||||||
2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(),
|
2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(),
|
||||||
@ -376,19 +384,20 @@ where
|
|||||||
|
|
||||||
pub fn mutation_byteinteresting<I, M, R, S>(
|
pub fn mutation_byteinteresting<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() == 0 {
|
if input.bytes().len() == 0 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
let val = INTERESTING_8[rand.below(INTERESTING_8.len() as u64) as usize] as u8;
|
let val = INTERESTING_8[state.rand_mut().below(INTERESTING_8.len() as u64) as usize] as u8;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
*input.bytes_mut().get_unchecked_mut(idx) = val;
|
*input.bytes_mut().get_unchecked_mut(idx) = val;
|
||||||
@ -399,23 +408,24 @@ where
|
|||||||
|
|
||||||
pub fn mutation_wordinteresting<I, M, R, S>(
|
pub fn mutation_wordinteresting<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() < 2 {
|
if input.bytes().len() < 2 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64 - 1) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64 - 1) as usize;
|
||||||
let val = INTERESTING_16[rand.below(INTERESTING_8.len() as u64) as usize] as u16;
|
let val = INTERESTING_16[state.rand_mut().below(INTERESTING_8.len() as u64) as usize] as u16;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u16;
|
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u16;
|
||||||
if rand.below(2) == 0 {
|
if state.rand_mut().below(2) == 0 {
|
||||||
*ptr = val;
|
*ptr = val;
|
||||||
} else {
|
} else {
|
||||||
*ptr = val.swap_bytes();
|
*ptr = val.swap_bytes();
|
||||||
@ -427,23 +437,24 @@ where
|
|||||||
|
|
||||||
pub fn mutation_dwordinteresting<I, M, R, S>(
|
pub fn mutation_dwordinteresting<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
if input.bytes().len() < 4 {
|
if input.bytes().len() < 4 {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let idx = rand.below(input.bytes().len() as u64 - 3) as usize;
|
let idx = state.rand_mut().below(input.bytes().len() as u64 - 3) as usize;
|
||||||
let val = INTERESTING_32[rand.below(INTERESTING_8.len() as u64) as usize] as u32;
|
let val = INTERESTING_32[state.rand_mut().below(INTERESTING_8.len() as u64) as usize] as u32;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Moar speed, no bound check
|
// Moar speed, no bound check
|
||||||
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u32;
|
let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u32;
|
||||||
if rand.below(2) == 0 {
|
if state.rand_mut().below(2) == 0 {
|
||||||
*ptr = val;
|
*ptr = val;
|
||||||
} else {
|
} else {
|
||||||
*ptr = val.swap_bytes();
|
*ptr = val.swap_bytes();
|
||||||
@ -455,12 +466,13 @@ where
|
|||||||
|
|
||||||
pub fn mutation_bytesdelete<I, M, R, S>(
|
pub fn mutation_bytesdelete<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
@ -468,8 +480,8 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let off = rand.below(size as u64) as usize;
|
let off = state.rand_mut().below(size as u64) as usize;
|
||||||
let len = rand.below((size - off) as u64) as usize;
|
let len = state.rand_mut().below((size - off) as u64) as usize;
|
||||||
input.bytes_mut().drain(off..off + len);
|
input.bytes_mut().drain(off..off + len);
|
||||||
|
|
||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
@ -478,18 +490,18 @@ where
|
|||||||
pub fn mutation_bytesexpand<I, M, R, S>(
|
pub fn mutation_bytesexpand<I, M, R, S>(
|
||||||
// TODO: max_size instead of mutator?
|
// TODO: max_size instead of mutator?
|
||||||
mutator: &mut M,
|
mutator: &mut M,
|
||||||
rand: &mut R,
|
state: &mut S,
|
||||||
_: &mut S,
|
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
M: HasMaxSize,
|
M: HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = rand.below((size + 1) as u64) as usize;
|
let off = state.rand_mut().below((size + 1) as u64) as usize;
|
||||||
let mut len = 1 + rand.below(16) as usize;
|
let mut len = 1 + state.rand_mut().below(16) as usize;
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
if mutator.max_size() > size {
|
if mutator.max_size() > size {
|
||||||
@ -507,18 +519,18 @@ where
|
|||||||
|
|
||||||
pub fn mutation_bytesinsert<I, M, R, S>(
|
pub fn mutation_bytesinsert<I, M, R, S>(
|
||||||
mutator: &mut M,
|
mutator: &mut M,
|
||||||
rand: &mut R,
|
state: &mut S,
|
||||||
_: &mut S,
|
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
M: HasMaxSize,
|
M: HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = rand.below((size + 1) as u64) as usize;
|
let off = state.rand_mut().below((size + 1) as u64) as usize;
|
||||||
let mut len = 1 + rand.below(16) as usize;
|
let mut len = 1 + state.rand_mut().below(16) as usize;
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
if mutator.max_size() > size {
|
if mutator.max_size() > size {
|
||||||
@ -528,7 +540,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let val = input.bytes()[rand.below(size as u64) as usize];
|
let val = input.bytes()[state.rand_mut().below(size as u64) as usize];
|
||||||
|
|
||||||
input.bytes_mut().resize(size + len, 0);
|
input.bytes_mut().resize(size + len, 0);
|
||||||
buffer_self_copy(input.bytes_mut(), off, off + len, size - off);
|
buffer_self_copy(input.bytes_mut(), off, off + len, size - off);
|
||||||
@ -539,18 +551,19 @@ where
|
|||||||
|
|
||||||
pub fn mutation_bytesrandinsert<I, M, R, S>(
|
pub fn mutation_bytesrandinsert<I, M, R, S>(
|
||||||
mutator: &mut M,
|
mutator: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
M: HasMaxSize,
|
M: HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = rand.below((size + 1) as u64) as usize;
|
let off = state.rand_mut().below((size + 1) as u64) as usize;
|
||||||
let mut len = 1 + rand.below(16) as usize;
|
let mut len = 1 + state.rand_mut().below(16) as usize;
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
if mutator.max_size() > size {
|
if mutator.max_size() > size {
|
||||||
@ -560,7 +573,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let val = rand.below(256) as u8;
|
let val = state.rand_mut().below(256) as u8;
|
||||||
|
|
||||||
input.bytes_mut().resize(size + len, 0);
|
input.bytes_mut().resize(size + len, 0);
|
||||||
buffer_self_copy(input.bytes_mut(), off, off + len, size - off);
|
buffer_self_copy(input.bytes_mut(), off, off + len, size - off);
|
||||||
@ -571,22 +584,23 @@ where
|
|||||||
|
|
||||||
pub fn mutation_bytesset<I, M, R, S>(
|
pub fn mutation_bytesset<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
let off = rand.below(size as u64) as usize;
|
let off = state.rand_mut().below(size as u64) as usize;
|
||||||
let len = 1 + rand.below(min(16, size - off) as u64) as usize;
|
let len = 1 + state.rand_mut().below(min(16, size - off) as u64) as usize;
|
||||||
|
|
||||||
let val = input.bytes()[rand.below(size as u64) as usize];
|
let val = input.bytes()[state.rand_mut().below(size as u64) as usize];
|
||||||
|
|
||||||
buffer_set(input.bytes_mut(), off, len, val);
|
buffer_set(input.bytes_mut(), off, len, val);
|
||||||
|
|
||||||
@ -595,22 +609,23 @@ where
|
|||||||
|
|
||||||
pub fn mutation_bytesrandset<I, M, R, S>(
|
pub fn mutation_bytesrandset<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
let off = rand.below(size as u64) as usize;
|
let off = state.rand_mut().below(size as u64) as usize;
|
||||||
let len = 1 + rand.below(min(16, size - off) as u64) as usize;
|
let len = 1 + state.rand_mut().below(min(16, size - off) as u64) as usize;
|
||||||
|
|
||||||
let val = rand.below(256) as u8;
|
let val = state.rand_mut().below(256) as u8;
|
||||||
|
|
||||||
buffer_set(input.bytes_mut(), off, len, val);
|
buffer_set(input.bytes_mut(), off, len, val);
|
||||||
|
|
||||||
@ -619,12 +634,13 @@ where
|
|||||||
|
|
||||||
pub fn mutation_bytescopy<I, M, R, S>(
|
pub fn mutation_bytescopy<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
@ -632,9 +648,9 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let from = rand.below(input.bytes().len() as u64) as usize;
|
let from = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
let to = rand.below(input.bytes().len() as u64) as usize;
|
let to = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
let len = 1 + rand.below((size - max(from, to)) as u64) as usize;
|
let len = 1 + state.rand_mut().below((size - max(from, to)) as u64) as usize;
|
||||||
|
|
||||||
buffer_self_copy(input.bytes_mut(), from, to, len);
|
buffer_self_copy(input.bytes_mut(), from, to, len);
|
||||||
|
|
||||||
@ -643,12 +659,13 @@ where
|
|||||||
|
|
||||||
pub fn mutation_bytesswap<I, M, R, S>(
|
pub fn mutation_bytesswap<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
_: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
@ -656,9 +673,9 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let first = rand.below(input.bytes().len() as u64) as usize;
|
let first = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
let second = rand.below(input.bytes().len() as u64) as usize;
|
let second = state.rand_mut().below(input.bytes().len() as u64) as usize;
|
||||||
let len = 1 + rand.below((size - max(first, second)) as u64) as usize;
|
let len = 1 + state.rand_mut().below((size - max(first, second)) as u64) as usize;
|
||||||
|
|
||||||
let tmp = input.bytes()[first..(first + len)].to_vec();
|
let tmp = input.bytes()[first..(first + len)].to_vec();
|
||||||
buffer_self_copy(input.bytes_mut(), second, first, len);
|
buffer_self_copy(input.bytes_mut(), second, first, len);
|
||||||
@ -670,21 +687,20 @@ where
|
|||||||
/// Crossover insert mutation
|
/// Crossover insert mutation
|
||||||
pub fn mutation_crossover_insert<C, I, M, R, S>(
|
pub fn mutation_crossover_insert<C, I, M, R, S>(
|
||||||
mutator: &mut M,
|
mutator: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
M: HasMaxSize,
|
M: HasMaxSize,
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R>,
|
S: HasRand<R> + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
|
|
||||||
// We don't want to use the testcase we're already using for splicing
|
// We don't want to use the testcase we're already using for splicing
|
||||||
let (other_testcase, idx) = state.corpus().random_entry(rand)?;
|
let (other_testcase, idx) = state.random_corpus_entry()?;
|
||||||
if idx == state.corpus().current_testcase().1 {
|
if idx == state.corpus().current_testcase().1 {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
@ -697,9 +713,9 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let from = rand.below(other_size as u64) as usize;
|
let from = state.rand_mut().below(other_size as u64) as usize;
|
||||||
let to = rand.below(size as u64) as usize;
|
let to = state.rand_mut().below(size as u64) as usize;
|
||||||
let mut len = rand.below((other_size - from) as u64) as usize;
|
let mut len = state.rand_mut().below((other_size - from) as u64) as usize;
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
if mutator.max_size() > size {
|
if mutator.max_size() > size {
|
||||||
@ -719,20 +735,20 @@ where
|
|||||||
/// Crossover replace mutation
|
/// Crossover replace mutation
|
||||||
pub fn mutation_crossover_replace<C, I, M, R, S>(
|
pub fn mutation_crossover_replace<C, I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R>,
|
S: HasRand<R> + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
|
|
||||||
// We don't want to use the testcase we're already using for splicing
|
// We don't want to use the testcase we're already using for splicing
|
||||||
let (other_testcase, idx) = state.corpus().random_entry(rand)?;
|
let (other_testcase, idx) = state.random_corpus_entry()?;
|
||||||
if idx == state.corpus().current_testcase().1 {
|
if idx == state.corpus().current_testcase().1 {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
@ -745,9 +761,9 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let from = rand.below(other_size as u64) as usize;
|
let from = state.rand_mut().below(other_size as u64) as usize;
|
||||||
let len = rand.below(min(other_size - from, size) as u64) as usize;
|
let len = state.rand_mut().below(min(other_size - from, size) as u64) as usize;
|
||||||
let to = rand.below((size - len) as u64) as usize;
|
let to = state.rand_mut().below((size - len) as u64) as usize;
|
||||||
|
|
||||||
buffer_copy(input.bytes_mut(), other.bytes(), from, to, len);
|
buffer_copy(input.bytes_mut(), other.bytes(), from, to, len);
|
||||||
|
|
||||||
@ -773,18 +789,18 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
|
|||||||
/// Splicing mutation from AFL
|
/// Splicing mutation from AFL
|
||||||
pub fn mutation_splice<C, I, M, R, S>(
|
pub fn mutation_splice<C, I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I>,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R>,
|
S: HasRand<R> + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
// We don't want to use the testcase we're already using for splicing
|
// We don't want to use the testcase we're already using for splicing
|
||||||
let (other_testcase, idx) = state.corpus().random_entry(rand)?;
|
let (other_testcase, idx) = state.random_corpus_entry()?;
|
||||||
if idx == state.corpus().current_testcase().1 {
|
if idx == state.corpus().current_testcase().1 {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
@ -805,7 +821,7 @@ where
|
|||||||
counter += 1;
|
counter += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
let split_at = rand.between(first_diff as u64, last_diff as u64) as usize;
|
let split_at = state.rand_mut().between(first_diff as u64, last_diff as u64) as usize;
|
||||||
input
|
input
|
||||||
.bytes_mut()
|
.bytes_mut()
|
||||||
.splice(split_at.., other.bytes()[split_at..].iter().cloned());
|
.splice(split_at.., other.bytes()[split_at..].iter().cloned());
|
||||||
|
@ -1,72 +1,69 @@
|
|||||||
|
use crate::inputs::HasBytesVec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{fmt, default::Default, marker::PhantomData};
|
use core::{fmt, default::Default, marker::PhantomData};
|
||||||
use fmt::Debug;
|
use fmt::Debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inputs::{HasBytesVec, Input},
|
inputs::{Input},
|
||||||
mutators::{Corpus, *},
|
mutators::{Mutator, HasMaxSize, DEFAULT_MAX_SIZE},
|
||||||
state::{HasCorpus, HasMetadata},
|
state::{HasRand, HasCorpus, HasMetadata},
|
||||||
|
corpus::Corpus,
|
||||||
utils::Rand,
|
utils::Rand,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait ScheduledMutator<C, I, R, S>:
|
pub use crate::mutators::mutations::*;
|
||||||
Mutator<C, I, R, S> + ComposedByMutations<C, I, R, S>
|
pub use crate::mutators::token_mutations::*;
|
||||||
|
|
||||||
|
pub trait ScheduledMutator<I, S>: Mutator<I> + ComposedByMutations<I, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
|
||||||
{
|
{
|
||||||
/// Compute the number of iterations used to apply stacked mutations
|
/// Compute the number of iterations used to apply stacked mutations
|
||||||
#[inline]
|
fn iterations(&mut self, state: &mut S, input: &I) -> u64;
|
||||||
fn iterations(&mut self, rand: &mut R, _input: &I) -> u64 {
|
//{
|
||||||
1 << (1 + rand.below(6))
|
// 1 << (1 + state.rand_mut().below(6))
|
||||||
}
|
//}
|
||||||
|
|
||||||
/// Get the next mutation to apply
|
/// Get the next mutation to apply
|
||||||
#[inline]
|
fn schedule(&mut self, mutations_count: usize, state: &mut S, input: &I) -> usize;
|
||||||
fn schedule(&mut self, mutations_count: usize, rand: &mut R, _input: &I) -> usize {
|
//{
|
||||||
debug_assert!(mutations_count > 0);
|
// debug_assert!(mutations_count > 0);
|
||||||
rand.below(mutations_count as u64) as usize
|
// rand.below(mutations_count as u64) as usize
|
||||||
}
|
//}
|
||||||
|
|
||||||
/// New default implementation for mutate
|
/// New default implementation for mutate
|
||||||
/// Implementations must forward mutate() to this method
|
/// Implementations must forward mutate() to this method
|
||||||
fn scheduled_mutate(
|
fn scheduled_mutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
_stage_idx: i32,
|
_stage_idx: i32,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let num = self.iterations(rand, input);
|
let num = self.iterations(state, input);
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let idx = self.schedule(self.mutations_count(), rand, input);
|
let idx = self.schedule(self.mutations_count(), state, input);
|
||||||
self.mutation_by_idx(idx)(self, rand, state, input)?;
|
self.mutation_by_idx(idx)(self, state, input)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct StdScheduledMutator<C, I, R, S>
|
pub struct StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
I: Input,
|
||||||
I: Input,
|
R: Rand,
|
||||||
R: Rand,
|
S: HasRand<R>,{
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
mutations: Vec<MutationFunction<I, Self, S>>,
|
||||||
{
|
|
||||||
mutations: Vec<MutationFunction<I, Self, R, S>>,
|
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S> Debug for StdScheduledMutator<C, I, R, S>
|
impl<I, R, S> Debug for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
S: HasRand<R>,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
@ -79,12 +76,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S> Mutator<C, I, R, S> for StdScheduledMutator<C, I, R, S>
|
impl<I, R, S> Mutator<I> for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
S: HasRand<R>,
|
||||||
{
|
{
|
||||||
fn mutate(
|
fn mutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -93,19 +89,18 @@ where
|
|||||||
input: &mut I,
|
input: &mut I,
|
||||||
_stage_idx: i32,
|
_stage_idx: i32,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.scheduled_mutate(rand, state, input, _stage_idx)
|
self.scheduled_mutate(state, input, _stage_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S> ComposedByMutations<C, I, R, S> for StdScheduledMutator<C, I, R, S>
|
impl<I, R, S> ComposedByMutations<I, S> for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
S: HasRand<R>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, R, S> {
|
fn mutation_by_idx(&self, index: usize) -> MutationFunction<I, Self, S> {
|
||||||
self.mutations[index]
|
self.mutations[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,27 +110,25 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, R, S>) {
|
fn add_mutation(&mut self, mutation: MutationFunction<I, Self, S>) {
|
||||||
self.mutations.push(mutation)
|
self.mutations.push(mutation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S> ScheduledMutator<C, I, R, S> for StdScheduledMutator<C, I, R, S>
|
impl<I, R, S> ScheduledMutator<I, S> for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
S: HasRand<R>,
|
||||||
{
|
{
|
||||||
// Just use the default methods
|
// Just use the default methods
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S> HasMaxSize for StdScheduledMutator<C, I, R, S>
|
impl<I, R, S> HasMaxSize for StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
S: HasRand<R>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn max_size(&self) -> usize {
|
fn max_size(&self) -> usize {
|
||||||
@ -148,12 +141,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S> StdScheduledMutator<C, I, R, S>
|
impl<I, R, S> StdScheduledMutator<I, R, S>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
S: HasRand<R>,
|
||||||
{
|
{
|
||||||
/// Create a new StdScheduledMutator instance without mutations and corpus
|
/// Create a new StdScheduledMutator instance without mutations and corpus
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -164,7 +156,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new StdScheduledMutator instance specifying mutations
|
/// Create a new StdScheduledMutator instance specifying mutations
|
||||||
pub fn with_mutations(mutations: Vec<MutationFunction<I, Self, R, S>>) -> Self {
|
pub fn with_mutations(mutations: Vec<MutationFunction<I, Self, S>>) -> Self {
|
||||||
StdScheduledMutator {
|
StdScheduledMutator {
|
||||||
mutations: mutations,
|
mutations: mutations,
|
||||||
max_size: DEFAULT_MAX_SIZE,
|
max_size: DEFAULT_MAX_SIZE,
|
||||||
@ -172,27 +164,27 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
/// Schedule some selected byte level mutations given a ScheduledMutator type
|
/// Schedule some selected byte level mutations given a ScheduledMutator type
|
||||||
pub struct HavocBytesMutator<SM, C, I, R, S>
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct HavocBytesMutator<C, I, R, S, SM>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
|
C: Corpus<I>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
|
||||||
{
|
{
|
||||||
scheduled: SM,
|
scheduled: SM,
|
||||||
phantom: PhantomData<(C, I, R, S)>,
|
phantom: PhantomData<(I, R, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SM, C, I, R, S> Mutator<C, I, R, S> for HavocBytesMutator<SM, C, I, R, S>
|
impl<C, I, R, S, SM> Mutator<I> for HavocBytesMutator<C, I, R, S, SM>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
|
C: Corpus<I>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
|
||||||
{
|
{
|
||||||
/// Mutate bytes
|
/// Mutate bytes
|
||||||
fn mutate(
|
fn mutate(
|
||||||
@ -202,10 +194,10 @@ where
|
|||||||
input: &mut I,
|
input: &mut I,
|
||||||
stage_idx: i32,
|
stage_idx: i32,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.scheduled.mutate(rand, state, input, stage_idx)?;
|
self.scheduled.mutate(state, input, stage_idx)?;
|
||||||
/*let num = self.scheduled.iterations(rand, input);
|
/*let num = self.scheduled.iterations(state, input);
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let idx = self.scheduled.schedule(14, rand, input);
|
let idx = self.scheduled.schedule(14, state, input);
|
||||||
let mutation = match idx {
|
let mutation = match idx {
|
||||||
0 => mutation_bitflip,
|
0 => mutation_bitflip,
|
||||||
1 => mutation_byteflip,
|
1 => mutation_byteflip,
|
||||||
@ -222,19 +214,19 @@ where
|
|||||||
11 => mutation_dwordinteresting,
|
11 => mutation_dwordinteresting,
|
||||||
_ => mutation_splice,
|
_ => mutation_splice,
|
||||||
};
|
};
|
||||||
mutation(self, rand, state, input)?;
|
mutation(self, state, input)?;
|
||||||
}*/
|
}*/
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SM, C, I, R, S> HasMaxSize for HavocBytesMutator<SM, C, I, R, S>
|
impl<C, I, R, S, SM> HasMaxSize for HavocBytesMutator<C, I, R, S, SM>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
|
C: Corpus<I>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn max_size(&self) -> usize {
|
fn max_size(&self) -> usize {
|
||||||
@ -247,13 +239,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SM, C, I, R, S> HavocBytesMutator<SM, C, I, R, S>
|
impl<C, I, R, S, SM> HavocBytesMutator<C, I, R, S, SM>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<C, I, R, S> + HasMaxSize,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
|
C: Corpus<I>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
|
||||||
{
|
{
|
||||||
/// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap
|
/// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap
|
||||||
pub fn new(mut scheduled: SM) -> Self {
|
pub fn new(mut scheduled: SM) -> Self {
|
||||||
@ -266,16 +258,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S> Default for HavocBytesMutator<StdScheduledMutator<C, I, R, S>, C, I, R, S>
|
impl<C, I, R, S, SM> Default for HavocBytesMutator<C, I, R, S, StdScheduledMutator<I, R, S>>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
SM: ScheduledMutator<I, S> + HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
|
C: Corpus<I>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasCorpus<C, I, R> + HasMetadata,
|
|
||||||
{
|
{
|
||||||
/// Create a new HavocBytesMutator instance wrapping StdScheduledMutator
|
/// Create a new HavocBytesMutator instance wrapping StdScheduledMutator
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut scheduled = StdScheduledMutator::<C, I, R, S>::new();
|
let mut scheduled = StdScheduledMutator::<I, R, S>::new();
|
||||||
scheduled.add_mutation(mutation_bitflip);
|
scheduled.add_mutation(mutation_bitflip);
|
||||||
scheduled.add_mutation(mutation_byteflip);
|
scheduled.add_mutation(mutation_byteflip);
|
||||||
scheduled.add_mutation(mutation_byteinc);
|
scheduled.add_mutation(mutation_byteinc);
|
||||||
@ -317,6 +310,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -390,3 +384,4 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inputs::{HasBytesVec, Input},
|
inputs::{HasBytesVec, Input},
|
||||||
|
state::{HasRand, HasCorpus, HasMetadata},
|
||||||
mutators::*,
|
mutators::*,
|
||||||
utils::Rand,
|
utils::Rand,
|
||||||
Error,
|
Error,
|
||||||
@ -31,15 +32,14 @@ impl TokensMetadata {
|
|||||||
/// Insert a dictionary token
|
/// Insert a dictionary token
|
||||||
pub fn mutation_tokeninsert<I, M, R, S>(
|
pub fn mutation_tokeninsert<I, M, R, S>(
|
||||||
mutator: &mut M,
|
mutator: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
M: HasMaxSize,
|
M: HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasMetadata + HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasMetadata,
|
|
||||||
{
|
{
|
||||||
let meta;
|
let meta;
|
||||||
match state.metadata().get::<TokensMetadata>() {
|
match state.metadata().get::<TokensMetadata>() {
|
||||||
@ -53,10 +53,10 @@ where
|
|||||||
if meta.tokens.len() == 0 {
|
if meta.tokens.len() == 0 {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
let token = &meta.tokens[rand.below(meta.tokens.len() as u64) as usize];
|
let token = &meta.tokens[state.rand_mut().below(meta.tokens.len() as u64) as usize];
|
||||||
|
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = rand.below((size + 1) as u64) as usize;
|
let off = state.rand_mut().below((size + 1) as u64) as usize;
|
||||||
let mut len = token.len();
|
let mut len = token.len();
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
@ -77,14 +77,14 @@ where
|
|||||||
/// Overwrite with a dictionary token
|
/// Overwrite with a dictionary token
|
||||||
pub fn mutation_tokenreplace<I, M, R, S>(
|
pub fn mutation_tokenreplace<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, Error>
|
) -> Result<MutationResult, Error>
|
||||||
where
|
where
|
||||||
|
M: HasMaxSize,
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
|
S: HasMetadata + HasRand<R>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
S: HasMetadata,
|
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
@ -103,9 +103,9 @@ where
|
|||||||
if meta.tokens.len() == 0 {
|
if meta.tokens.len() == 0 {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
let token = &meta.tokens[rand.below(meta.tokens.len() as u64) as usize];
|
let token = &meta.tokens[state.rand_mut().below(meta.tokens.len() as u64) as usize];
|
||||||
|
|
||||||
let off = rand.below(size as u64) as usize;
|
let off = state.rand_mut().below(size as u64) as usize;
|
||||||
|
|
||||||
let mut len = token.len();
|
let mut len = token.len();
|
||||||
if off + len > size {
|
if off + len > size {
|
||||||
|
@ -66,8 +66,8 @@ where
|
|||||||
|
|
||||||
impl<Head, Tail, I> StagesTuple<I> for (Head, Tail)
|
impl<Head, Tail, I> StagesTuple<I> for (Head, Tail)
|
||||||
where
|
where
|
||||||
Head: Stage,
|
Head: Stage<I>,
|
||||||
Tail: StagesTuple + TupleList,
|
Tail: StagesTuple<I> + TupleList,
|
||||||
I: Input
|
I: Input
|
||||||
{
|
{
|
||||||
fn perform_all<E, EM, S>(
|
fn perform_all<E, EM, S>(
|
||||||
|
@ -9,6 +9,7 @@ use crate::{
|
|||||||
stages::Stage,
|
stages::Stage,
|
||||||
state::{HasRand},
|
state::{HasRand},
|
||||||
utils::Rand,
|
utils::Rand,
|
||||||
|
state::HasCorpus,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ where
|
|||||||
fn iterations<S>(&mut self, state: &mut S) -> usize;
|
fn iterations<S>(&mut self, state: &mut S) -> usize;
|
||||||
|
|
||||||
/// Runs this (mutational) stage for the given testcase
|
/// Runs this (mutational) stage for the given testcase
|
||||||
fn perform_mutational<E, EM, S>(
|
fn perform_mutational<E, EM, S, C>(
|
||||||
&self,
|
&self,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
@ -41,13 +42,15 @@ where
|
|||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
E: Executor<I>
|
E: Executor<I>,
|
||||||
|
S: HasCorpus<C, I>,
|
||||||
|
C: Corpus<I>
|
||||||
{
|
{
|
||||||
let num = self.iterations(state);
|
let num = self.iterations(state);
|
||||||
for i in 0..num {
|
for i in 0..num {
|
||||||
let mut input_mut = state
|
let mut input_mut = state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(corpus_idx)
|
.get(corpus_idx)?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.load_input()?
|
.load_input()?
|
||||||
.clone();
|
.clone();
|
||||||
@ -108,7 +111,7 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn perform<E, EM, S>(
|
fn perform<E, EM, S, C>(
|
||||||
&self,
|
&self,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
@ -117,7 +120,9 @@ where
|
|||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
E: Executor<I>
|
E: Executor<I>,
|
||||||
|
S: HasCorpus<C, I>,
|
||||||
|
C: Corpus<I>
|
||||||
{
|
{
|
||||||
self.perform_mutational(executor, state, manager, corpus_idx)
|
self.perform_mutational(executor, state, manager, corpus_idx)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user