From 95281dbfef22416284193ce016a48f2aa5d8d8a0 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 12:15:09 +0100 Subject: [PATCH] mutations --- libafl/src/fuzzer.rs | 108 +++++--- libafl/src/mutators/mutations.rs | 328 +++++++++++++------------ libafl/src/mutators/scheduled.rs | 147 ++++++----- libafl/src/mutators/token_mutations.rs | 16 +- libafl/src/stages/mod.rs | 4 +- libafl/src/stages/mutational.rs | 15 +- 6 files changed, 335 insertions(+), 283 deletions(-) diff --git a/libafl/src/fuzzer.rs b/libafl/src/fuzzer.rs index 50cc535425..e6abc6a7a8 100644 --- a/libafl/src/fuzzer.rs +++ b/libafl/src/fuzzer.rs @@ -1,26 +1,28 @@ use core::{marker::PhantomData}; use crate::{ - corpus::{CorpusScheduler}, + corpus::{CorpusScheduler, Corpus}, events::{Event, EventManager}, executors::{Executor}, inputs::Input, stages::StagesTuple, - utils::{current_milliseconds, current_time}, + state::{HasRand, HasCorpus}, + utils::{Rand, current_milliseconds, current_time}, Error }; /// Holds a set of stages -pub trait HasStages +pub trait HasStages where - ST: StagesTuple, + ST: StagesTuple, + I: Input { fn stages(&self) -> &ST; fn stages_mut(&mut self) -> &mut ST; } -/// Holds a set of stages +/// Holds a scheduler pub trait HasCorpusScheduler where CS: CorpusScheduler, @@ -31,7 +33,7 @@ where } /// The main fuzzer trait. -pub trait Fuzzer: HasCorpusScheduler + HasStages +pub trait Fuzzer: HasCorpusScheduler + HasStages where CS: CorpusScheduler, ST: StagesTuple, @@ -45,16 +47,7 @@ where ) -> Result where EM: EventManager, - E: Executor, - { - let idx = self.scheduler().next(state)?; - - self.stages() - .perform_all(executor, state, manager, idx)?; - - manager.process(state, executor)?; - Ok(idx) - } + E: Executor; fn fuzz_loop( &mut self, @@ -64,25 +57,7 @@ where ) -> Result where EM: EventManager, - E: Executor, - { - 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, - }, - )? - } - } - } + E: Executor; } /// Your default fuzzer instance, for everyday use. @@ -97,7 +72,7 @@ where stages: ST, } -impl HasStages for StdFuzzer +impl HasStages for StdFuzzer where CS: CorpusScheduler, ST: StagesTuple, @@ -127,6 +102,67 @@ where } } +impl Fuzzer for StdFuzzer +where + CS: CorpusScheduler, + ST: StagesTuple, + I: Input +{ + fn fuzz_one( + &mut self, + executor: &mut E, + state: &mut S, + manager: &mut EM, + ) -> Result + where + EM: EventManager, + E: Executor, + S: HasCorpus + HasRand, + C: Corpus, + 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( + &mut self, + executor: &mut E, + state: &mut S, + manager: &mut EM, + ) -> Result + where + EM: EventManager, + E: Executor, + S: HasCorpus + HasRand, + C: Corpus, + 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 StdFuzzer where CS: CorpusScheduler, diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index fc1368deb0..19f72ebeae 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -1,7 +1,8 @@ use crate::{ inputs::{HasBytesVec, Input}, - mutators::Corpus, + corpus::Corpus, mutators::*, + state::{HasRand, HasCorpus}, utils::Rand, Error, }; @@ -15,42 +16,6 @@ use std::{ 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. /// If the mutation got skipped, the target /// will not be executed with the returned input. @@ -62,24 +27,21 @@ pub enum MutationResult { // TODO maybe the mutator arg is not needed /// The generic function type that identifies mutations -pub type MutationFunction = - fn(&mut M, &mut R, &mut S, &mut I) -> Result; +pub type MutationFunction = + fn(&mut M, &mut S, &mut I) -> Result; -pub trait ComposedByMutations +pub trait ComposedByMutations where - C: Corpus, I: Input, - R: Rand, - S: HasCorpus + HasMetadata, { /// Get a mutation by index - fn mutation_by_idx(&self, index: usize) -> MutationFunction; + fn mutation_by_idx(&self, index: usize) -> MutationFunction; /// Get the number of mutations fn mutations_count(&self) -> usize; /// Add a mutation - fn add_mutation(&mut self, mutation: MutationFunction); + fn add_mutation(&mut self, mutation: MutationFunction); } /// 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 pub fn mutation_bitflip( _: &mut M, - rand: &mut R, - _: &mut S, + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, - R: Rand, + S: HasRand, + R: Rand { if input.bytes().len() == 0 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(bit >> 3) ^= (128 >> (bit & 7)) as u8; @@ -150,18 +149,19 @@ where pub fn mutation_byteflip( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() == 0 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(idx) ^= 0xff; @@ -172,18 +172,19 @@ where pub fn mutation_byteinc( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() == 0 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check let ptr = input.bytes_mut().get_unchecked_mut(idx); @@ -195,18 +196,19 @@ where pub fn mutation_bytedec( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() == 0 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check let ptr = input.bytes_mut().get_unchecked_mut(idx); @@ -218,18 +220,19 @@ where pub fn mutation_byteneg( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() == 0 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(idx) = !(*input.bytes().get_unchecked(idx)); @@ -240,21 +243,22 @@ where pub fn mutation_byterand( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() == 0 { Ok(MutationResult::Skipped) } 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 { // 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) } @@ -262,23 +266,24 @@ where pub fn mutation_byteadd( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() == 0 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut u8; - let num = 1 + rand.below(ARITH_MAX) as u8; - match rand.below(2) { + let num = 1 + state.rand_mut().below(ARITH_MAX) as u8; + match state.rand_mut().below(2) { 0 => *ptr = (*ptr).wrapping_add(num), _ => *ptr = (*ptr).wrapping_sub(num), }; @@ -289,23 +294,24 @@ where pub fn mutation_wordadd( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() < 2 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u16; - let num = 1 + rand.below(ARITH_MAX) as u16; - match rand.below(4) { + let num = 1 + state.rand_mut().below(ARITH_MAX) as u16; + match state.rand_mut().below(4) { 0 => *ptr = (*ptr).wrapping_add(num), 1 => *ptr = (*ptr).wrapping_sub(num), 2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(), @@ -318,23 +324,24 @@ where pub fn mutation_dwordadd( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() < 4 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u32; - let num = 1 + rand.below(ARITH_MAX) as u32; - match rand.below(4) { + let num = 1 + state.rand_mut().below(ARITH_MAX) as u32; + match state.rand_mut().below(4) { 0 => *ptr = (*ptr).wrapping_add(num), 1 => *ptr = (*ptr).wrapping_sub(num), 2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(), @@ -347,23 +354,24 @@ where pub fn mutation_qwordadd( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() < 8 { Ok(MutationResult::Skipped) } 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 { // Moar speed, no bound check let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u64; - let num = 1 + rand.below(ARITH_MAX) as u64; - match rand.below(4) { + let num = 1 + state.rand_mut().below(ARITH_MAX) as u64; + match state.rand_mut().below(4) { 0 => *ptr = (*ptr).wrapping_add(num), 1 => *ptr = (*ptr).wrapping_sub(num), 2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(), @@ -376,19 +384,20 @@ where pub fn mutation_byteinteresting( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() == 0 { Ok(MutationResult::Skipped) } else { - let idx = rand.below(input.bytes().len() as u64) as usize; - let val = INTERESTING_8[rand.below(INTERESTING_8.len() as u64) as usize] as u8; + let idx = state.rand_mut().below(input.bytes().len() as u64) as usize; + let val = INTERESTING_8[state.rand_mut().below(INTERESTING_8.len() as u64) as usize] as u8; unsafe { // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(idx) = val; @@ -399,23 +408,24 @@ where pub fn mutation_wordinteresting( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() < 2 { Ok(MutationResult::Skipped) } else { - let idx = rand.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 idx = state.rand_mut().below(input.bytes().len() as u64 - 1) as usize; + let val = INTERESTING_16[state.rand_mut().below(INTERESTING_8.len() as u64) as usize] as u16; unsafe { // Moar speed, no bound check 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; } else { *ptr = val.swap_bytes(); @@ -427,23 +437,24 @@ where pub fn mutation_dwordinteresting( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { if input.bytes().len() < 4 { Ok(MutationResult::Skipped) } else { - let idx = rand.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 idx = state.rand_mut().below(input.bytes().len() as u64 - 3) as usize; + let val = INTERESTING_32[state.rand_mut().below(INTERESTING_8.len() as u64) as usize] as u32; unsafe { // Moar speed, no bound check 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; } else { *ptr = val.swap_bytes(); @@ -455,12 +466,13 @@ where pub fn mutation_bytesdelete( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { let size = input.bytes().len(); @@ -468,8 +480,8 @@ where return Ok(MutationResult::Skipped); } - let off = rand.below(size as u64) as usize; - let len = rand.below((size - off) as u64) as usize; + let off = state.rand_mut().below(size as u64) as usize; + let len = state.rand_mut().below((size - off) as u64) as usize; input.bytes_mut().drain(off..off + len); Ok(MutationResult::Mutated) @@ -478,18 +490,18 @@ where pub fn mutation_bytesexpand( // TODO: max_size instead of mutator? mutator: &mut M, - rand: &mut R, - _: &mut S, + state: &mut S, input: &mut I, ) -> Result where M: HasMaxSize, I: Input + HasBytesVec, + S: HasRand, R: Rand, { let size = input.bytes().len(); - let off = rand.below((size + 1) as u64) as usize; - let mut len = 1 + rand.below(16) as usize; + let off = state.rand_mut().below((size + 1) as u64) as usize; + let mut len = 1 + state.rand_mut().below(16) as usize; if size + len > mutator.max_size() { if mutator.max_size() > size { @@ -507,18 +519,18 @@ where pub fn mutation_bytesinsert( mutator: &mut M, - rand: &mut R, - _: &mut S, + state: &mut S, input: &mut I, ) -> Result where M: HasMaxSize, I: Input + HasBytesVec, + S: HasRand, R: Rand, { let size = input.bytes().len(); - let off = rand.below((size + 1) as u64) as usize; - let mut len = 1 + rand.below(16) as usize; + let off = state.rand_mut().below((size + 1) as u64) as usize; + let mut len = 1 + state.rand_mut().below(16) as usize; if size + len > mutator.max_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); buffer_self_copy(input.bytes_mut(), off, off + len, size - off); @@ -539,18 +551,19 @@ where pub fn mutation_bytesrandinsert( mutator: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where M: HasMaxSize, I: Input + HasBytesVec, + S: HasRand, R: Rand, { let size = input.bytes().len(); - let off = rand.below((size + 1) as u64) as usize; - let mut len = 1 + rand.below(16) as usize; + let off = state.rand_mut().below((size + 1) as u64) as usize; + let mut len = 1 + state.rand_mut().below(16) as usize; if size + len > mutator.max_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); buffer_self_copy(input.bytes_mut(), off, off + len, size - off); @@ -571,22 +584,23 @@ where pub fn mutation_bytesset( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { let size = input.bytes().len(); if size == 0 { return Ok(MutationResult::Skipped); } - let off = rand.below(size as u64) as usize; - let len = 1 + rand.below(min(16, size - off) as u64) as usize; + let off = state.rand_mut().below(size 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); @@ -595,22 +609,23 @@ where pub fn mutation_bytesrandset( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { let size = input.bytes().len(); if size == 0 { return Ok(MutationResult::Skipped); } - let off = rand.below(size as u64) as usize; - let len = 1 + rand.below(min(16, size - off) as u64) as usize; + let off = state.rand_mut().below(size 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); @@ -619,12 +634,13 @@ where pub fn mutation_bytescopy( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { let size = input.bytes().len(); @@ -632,9 +648,9 @@ where return Ok(MutationResult::Skipped); } - let from = rand.below(input.bytes().len() as u64) as usize; - let to = rand.below(input.bytes().len() as u64) as usize; - let len = 1 + rand.below((size - max(from, to)) as u64) as usize; + let from = state.rand_mut().below(input.bytes().len() as u64) as usize; + let to = state.rand_mut().below(input.bytes().len() 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); @@ -643,12 +659,13 @@ where pub fn mutation_bytesswap( _: &mut M, - rand: &mut R, - _: &mut S, + + state: &mut S, input: &mut I, ) -> Result where I: Input + HasBytesVec, + S: HasRand, R: Rand, { let size = input.bytes().len(); @@ -656,9 +673,9 @@ where return Ok(MutationResult::Skipped); } - let first = rand.below(input.bytes().len() as u64) as usize; - let second = rand.below(input.bytes().len() as u64) as usize; - let len = 1 + rand.below((size - max(first, second)) as u64) as usize; + let first = state.rand_mut().below(input.bytes().len() as u64) as usize; + let second = state.rand_mut().below(input.bytes().len() 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(); buffer_self_copy(input.bytes_mut(), second, first, len); @@ -670,21 +687,20 @@ where /// Crossover insert mutation pub fn mutation_crossover_insert( mutator: &mut M, - rand: &mut R, state: &mut S, input: &mut I, ) -> Result where M: HasMaxSize, - C: Corpus, + C: Corpus, I: Input + HasBytesVec, R: Rand, - S: HasCorpus, + S: HasRand + HasCorpus, { let size = input.bytes().len(); // 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 { return Ok(MutationResult::Skipped); } @@ -697,9 +713,9 @@ where return Ok(MutationResult::Skipped); } - let from = rand.below(other_size as u64) as usize; - let to = rand.below(size as u64) as usize; - let mut len = rand.below((other_size - from) as u64) as usize; + let from = state.rand_mut().below(other_size as u64) as usize; + let to = state.rand_mut().below(size 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 mutator.max_size() > size { @@ -719,20 +735,20 @@ where /// Crossover replace mutation pub fn mutation_crossover_replace( _: &mut M, - rand: &mut R, + state: &mut S, input: &mut I, ) -> Result where - C: Corpus, + C: Corpus, I: Input + HasBytesVec, R: Rand, - S: HasCorpus, + S: HasRand + HasCorpus, { let size = input.bytes().len(); // 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 { return Ok(MutationResult::Skipped); } @@ -745,9 +761,9 @@ where return Ok(MutationResult::Skipped); } - let from = rand.below(other_size as u64) as usize; - let len = rand.below(min(other_size - from, size) as u64) as usize; - let to = rand.below((size - len) as u64) as usize; + let from = state.rand_mut().below(other_size as u64) as usize; + let len = state.rand_mut().below(min(other_size - from, size) 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); @@ -773,18 +789,18 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) { /// Splicing mutation from AFL pub fn mutation_splice( _: &mut M, - rand: &mut R, + state: &mut S, input: &mut I, ) -> Result where - C: Corpus, + C: Corpus, I: Input + HasBytesVec, R: Rand, - S: HasCorpus, + S: HasRand + HasCorpus, { // 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 { return Ok(MutationResult::Skipped); } @@ -805,7 +821,7 @@ where 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 .bytes_mut() .splice(split_at.., other.bytes()[split_at..].iter().cloned()); diff --git a/libafl/src/mutators/scheduled.rs b/libafl/src/mutators/scheduled.rs index 993f8b11d1..29cf4ef807 100644 --- a/libafl/src/mutators/scheduled.rs +++ b/libafl/src/mutators/scheduled.rs @@ -1,72 +1,69 @@ +use crate::inputs::HasBytesVec; use alloc::vec::Vec; use core::{fmt, default::Default, marker::PhantomData}; use fmt::Debug; use crate::{ - inputs::{HasBytesVec, Input}, - mutators::{Corpus, *}, - state::{HasCorpus, HasMetadata}, + inputs::{Input}, + mutators::{Mutator, HasMaxSize, DEFAULT_MAX_SIZE}, + state::{HasRand, HasCorpus, HasMetadata}, + corpus::Corpus, utils::Rand, Error, }; -pub trait ScheduledMutator: - Mutator + ComposedByMutations +pub use crate::mutators::mutations::*; +pub use crate::mutators::token_mutations::*; + +pub trait ScheduledMutator: Mutator + ComposedByMutations where - C: Corpus, I: Input, - R: Rand, - S: HasCorpus + HasMetadata, { /// Compute the number of iterations used to apply stacked mutations - #[inline] - fn iterations(&mut self, rand: &mut R, _input: &I) -> u64 { - 1 << (1 + rand.below(6)) - } + fn iterations(&mut self, state: &mut S, input: &I) -> u64; + //{ + // 1 << (1 + state.rand_mut().below(6)) + //} /// Get the next mutation to apply - #[inline] - fn schedule(&mut self, mutations_count: usize, rand: &mut R, _input: &I) -> usize { - debug_assert!(mutations_count > 0); - rand.below(mutations_count as u64) as usize - } + fn schedule(&mut self, mutations_count: usize, state: &mut S, input: &I) -> usize; + //{ + // debug_assert!(mutations_count > 0); + // rand.below(mutations_count as u64) as usize + //} /// New default implementation for mutate /// Implementations must forward mutate() to this method fn scheduled_mutate( &mut self, - rand: &mut R, state: &mut S, input: &mut I, _stage_idx: i32, ) -> Result<(), Error> { - let num = self.iterations(rand, input); + let num = self.iterations(state, input); for _ in 0..num { - let idx = self.schedule(self.mutations_count(), rand, input); - self.mutation_by_idx(idx)(self, rand, state, input)?; + let idx = self.schedule(self.mutations_count(), state, input); + self.mutation_by_idx(idx)(self, state, input)?; } Ok(()) } } #[derive(Clone)] -pub struct StdScheduledMutator +pub struct StdScheduledMutator where - C: Corpus, - I: Input, - R: Rand, - S: HasCorpus + HasMetadata, -{ - mutations: Vec>, +I: Input, +R: Rand, +S: HasRand,{ + mutations: Vec>, max_size: usize, } -impl Debug for StdScheduledMutator +impl Debug for StdScheduledMutator where - C: Corpus, I: Input, R: Rand, - S: HasCorpus + HasMetadata, + S: HasRand, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -79,12 +76,11 @@ where } } -impl Mutator for StdScheduledMutator +impl Mutator for StdScheduledMutator where - C: Corpus, I: Input, R: Rand, - S: HasCorpus + HasMetadata, + S: HasRand, { fn mutate( &mut self, @@ -93,19 +89,18 @@ where input: &mut I, _stage_idx: i32, ) -> Result<(), Error> { - self.scheduled_mutate(rand, state, input, _stage_idx) + self.scheduled_mutate(state, input, _stage_idx) } } -impl ComposedByMutations for StdScheduledMutator +impl ComposedByMutations for StdScheduledMutator where - C: Corpus, I: Input, R: Rand, - S: HasCorpus + HasMetadata, + S: HasRand, { #[inline] - fn mutation_by_idx(&self, index: usize) -> MutationFunction { + fn mutation_by_idx(&self, index: usize) -> MutationFunction { self.mutations[index] } @@ -115,27 +110,25 @@ where } #[inline] - fn add_mutation(&mut self, mutation: MutationFunction) { + fn add_mutation(&mut self, mutation: MutationFunction) { self.mutations.push(mutation) } } -impl ScheduledMutator for StdScheduledMutator +impl ScheduledMutator for StdScheduledMutator where - C: Corpus, I: Input, R: Rand, - S: HasCorpus + HasMetadata, + S: HasRand, { // Just use the default methods } -impl HasMaxSize for StdScheduledMutator +impl HasMaxSize for StdScheduledMutator where - C: Corpus, I: Input, R: Rand, - S: HasCorpus + HasMetadata, + S: HasRand, { #[inline] fn max_size(&self) -> usize { @@ -148,12 +141,11 @@ where } } -impl StdScheduledMutator +impl StdScheduledMutator where - C: Corpus, I: Input, R: Rand, - S: HasCorpus + HasMetadata, + S: HasRand, { /// Create a new StdScheduledMutator instance without mutations and corpus pub fn new() -> Self { @@ -164,7 +156,7 @@ where } /// Create a new StdScheduledMutator instance specifying mutations - pub fn with_mutations(mutations: Vec>) -> Self { + pub fn with_mutations(mutations: Vec>) -> Self { StdScheduledMutator { mutations: mutations, max_size: DEFAULT_MAX_SIZE, @@ -172,27 +164,27 @@ where } } -#[derive(Clone, Debug)] /// Schedule some selected byte level mutations given a ScheduledMutator type -pub struct HavocBytesMutator +#[derive(Clone, Debug)] +pub struct HavocBytesMutator where - SM: ScheduledMutator + HasMaxSize, - C: Corpus, + SM: ScheduledMutator + HasMaxSize, I: Input + HasBytesVec, + S: HasRand + HasCorpus + HasMetadata, + C: Corpus, R: Rand, - S: HasCorpus + HasMetadata, { scheduled: SM, - phantom: PhantomData<(C, I, R, S)>, + phantom: PhantomData<(I, R, S)>, } -impl Mutator for HavocBytesMutator +impl Mutator for HavocBytesMutator where - SM: ScheduledMutator + HasMaxSize, - C: Corpus, + SM: ScheduledMutator + HasMaxSize, I: Input + HasBytesVec, + S: HasRand + HasCorpus + HasMetadata, + C: Corpus, R: Rand, - S: HasCorpus + HasMetadata, { /// Mutate bytes fn mutate( @@ -202,10 +194,10 @@ where input: &mut I, stage_idx: i32, ) -> Result<(), Error> { - self.scheduled.mutate(rand, state, input, stage_idx)?; - /*let num = self.scheduled.iterations(rand, input); + self.scheduled.mutate(state, input, stage_idx)?; + /*let num = self.scheduled.iterations(state, input); for _ in 0..num { - let idx = self.scheduled.schedule(14, rand, input); + let idx = self.scheduled.schedule(14, state, input); let mutation = match idx { 0 => mutation_bitflip, 1 => mutation_byteflip, @@ -222,19 +214,19 @@ where 11 => mutation_dwordinteresting, _ => mutation_splice, }; - mutation(self, rand, state, input)?; + mutation(self, state, input)?; }*/ Ok(()) } } -impl HasMaxSize for HavocBytesMutator +impl HasMaxSize for HavocBytesMutator where - SM: ScheduledMutator + HasMaxSize, - C: Corpus, + SM: ScheduledMutator + HasMaxSize, I: Input + HasBytesVec, + S: HasRand + HasCorpus + HasMetadata, + C: Corpus, R: Rand, - S: HasCorpus + HasMetadata, { #[inline] fn max_size(&self) -> usize { @@ -247,13 +239,13 @@ where } } -impl HavocBytesMutator +impl HavocBytesMutator where - SM: ScheduledMutator + HasMaxSize, - C: Corpus, + SM: ScheduledMutator + HasMaxSize, I: Input + HasBytesVec, + S: HasRand + HasCorpus + HasMetadata, + C: Corpus, R: Rand, - S: HasCorpus + HasMetadata, { /// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap pub fn new(mut scheduled: SM) -> Self { @@ -266,16 +258,17 @@ where } } -impl Default for HavocBytesMutator, C, I, R, S> +impl Default for HavocBytesMutator> where - C: Corpus, + SM: ScheduledMutator + HasMaxSize, I: Input + HasBytesVec, + S: HasRand + HasCorpus + HasMetadata, + C: Corpus, R: Rand, - S: HasCorpus + HasMetadata, { /// Create a new HavocBytesMutator instance wrapping StdScheduledMutator fn default() -> Self { - let mut scheduled = StdScheduledMutator::::new(); + let mut scheduled = StdScheduledMutator::::new(); scheduled.add_mutation(mutation_bitflip); scheduled.add_mutation(mutation_byteflip); scheduled.add_mutation(mutation_byteinc); @@ -317,6 +310,7 @@ where } } +/* #[cfg(test)] mod tests { use crate::{ @@ -390,3 +384,4 @@ mod tests { } } } +*/ \ No newline at end of file diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index a075fdaa4e..597f7c3d80 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -3,6 +3,7 @@ use crate::{ inputs::{HasBytesVec, Input}, + state::{HasRand, HasCorpus, HasMetadata}, mutators::*, utils::Rand, Error, @@ -31,15 +32,14 @@ impl TokensMetadata { /// Insert a dictionary token pub fn mutation_tokeninsert( mutator: &mut M, - rand: &mut R, state: &mut S, input: &mut I, ) -> Result where M: HasMaxSize, I: Input + HasBytesVec, + S: HasMetadata + HasRand, R: Rand, - S: HasMetadata, { let meta; match state.metadata().get::() { @@ -53,10 +53,10 @@ where if meta.tokens.len() == 0 { 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 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(); if size + len > mutator.max_size() { @@ -77,14 +77,14 @@ where /// Overwrite with a dictionary token pub fn mutation_tokenreplace( _: &mut M, - rand: &mut R, state: &mut S, input: &mut I, ) -> Result where + M: HasMaxSize, I: Input + HasBytesVec, + S: HasMetadata + HasRand, R: Rand, - S: HasMetadata, { let size = input.bytes().len(); if size == 0 { @@ -103,9 +103,9 @@ where if meta.tokens.len() == 0 { 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(); if off + len > size { diff --git a/libafl/src/stages/mod.rs b/libafl/src/stages/mod.rs index 805e4e7ca9..dda5bb1ed0 100644 --- a/libafl/src/stages/mod.rs +++ b/libafl/src/stages/mod.rs @@ -66,8 +66,8 @@ where impl StagesTuple for (Head, Tail) where - Head: Stage, - Tail: StagesTuple + TupleList, + Head: Stage, + Tail: StagesTuple + TupleList, I: Input { fn perform_all( diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 7255e957bc..73f78765df 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -9,6 +9,7 @@ use crate::{ stages::Stage, state::{HasRand}, utils::Rand, + state::HasCorpus, Error, }; @@ -32,7 +33,7 @@ where fn iterations(&mut self, state: &mut S) -> usize; /// Runs this (mutational) stage for the given testcase - fn perform_mutational( + fn perform_mutational( &self, executor: &mut E, state: &mut S, @@ -41,13 +42,15 @@ where ) -> Result<(), Error> where EM: EventManager, - E: Executor + E: Executor, + S: HasCorpus, + C: Corpus { let num = self.iterations(state); for i in 0..num { let mut input_mut = state .corpus() - .get(corpus_idx) + .get(corpus_idx)? .borrow_mut() .load_input()? .clone(); @@ -108,7 +111,7 @@ where I: Input, { #[inline] - fn perform( + fn perform( &self, executor: &mut E, state: &mut S, @@ -117,7 +120,9 @@ where ) -> Result<(), Error> where EM: EventManager, - E: Executor + E: Executor, + S: HasCorpus, + C: Corpus { self.perform_mutational(executor, state, manager, corpus_idx) }