diff --git a/afl/src/mutators/mutations.rs b/afl/src/mutators/mutations.rs index 69626770d8..40fc47785e 100644 --- a/afl/src/mutators/mutations.rs +++ b/afl/src/mutators/mutations.rs @@ -84,7 +84,7 @@ where /// Mem move in the own vec #[inline] -fn self_mem_move(data: &mut [u8], from: usize, to: usize, len: usize) { +pub fn buffer_self_copy(data: &mut [u8], from: usize, to: usize, len: usize) { debug_assert!(data.len() > 0); debug_assert!(from + len < data.len()); debug_assert!(to + len < data.len()); @@ -96,7 +96,7 @@ fn self_mem_move(data: &mut [u8], from: usize, to: usize, len: usize) { /// Mem move between vecs #[inline] -fn mem_move(dst: &mut [u8], src: &[u8], from: usize, to: usize, len: usize) { +pub fn buffer_copy(dst: &mut [u8], src: &[u8], from: usize, to: usize, len: usize) { debug_assert!(dst.len() > 0); debug_assert!(src.len() > 0); debug_assert!(from + len < src.len()); @@ -114,11 +114,11 @@ fn mem_move(dst: &mut [u8], src: &[u8], from: usize, to: usize, len: usize) { } } -/// A simple memset. +/// A simple buffer_set. /// The compiler does the heavy lifting. /// see https://stackoverflow.com/a/51732799/1345238 #[inline] -fn memset(data: &mut [u8], from: usize, len: usize, val: u8) { +fn buffer_set(data: &mut [u8], from: usize, len: usize, val: u8) { debug_assert!(from + len <= data.len()); for p in &mut data[from..from + len] { *p = val @@ -141,7 +141,7 @@ where } else { let bit = rand.below((input.bytes().len() << 3) as u64) as usize; unsafe { - // moar speed, no bound check + // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(bit >> 3) ^= (128 >> (bit & 7)) as u8; } Ok(MutationResult::Mutated) @@ -163,7 +163,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64) as usize; unsafe { - // moar speed, no bound check + // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(idx) ^= 0xff; } Ok(MutationResult::Mutated) @@ -185,7 +185,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64) as usize; unsafe { - // moar speed, no bound check + // Moar speed, no bound check let ptr = input.bytes_mut().get_unchecked_mut(idx); *ptr = (*ptr).wrapping_add(1); } @@ -208,7 +208,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64) as usize; unsafe { - // moar speed, no bound check + // Moar speed, no bound check let ptr = input.bytes_mut().get_unchecked_mut(idx); *ptr = (*ptr).wrapping_sub(1); } @@ -231,7 +231,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64) as usize; unsafe { - // moar speed, no bound check + // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(idx) = !(*input.bytes().get_unchecked(idx)); } Ok(MutationResult::Mutated) @@ -253,7 +253,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64) as usize; unsafe { - // moar speed, no bound check + // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(idx) = rand.below(256) as u8; } Ok(MutationResult::Mutated) @@ -275,7 +275,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64) as usize; unsafe { - // moar speed, no bound check + // 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) { @@ -302,7 +302,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64 - 1) as usize; 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 num = 1 + rand.below(ARITH_MAX) as u16; match rand.below(4) { @@ -331,7 +331,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64 - 3) as usize; 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 num = 1 + rand.below(ARITH_MAX) as u32; match rand.below(4) { @@ -360,7 +360,7 @@ where } else { let idx = rand.below(input.bytes().len() as u64 - 7) as usize; 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 num = 1 + rand.below(ARITH_MAX) as u64; match rand.below(4) { @@ -390,7 +390,7 @@ where 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; unsafe { - // moar speed, no bound check + // Moar speed, no bound check *input.bytes_mut().get_unchecked_mut(idx) = val; } Ok(MutationResult::Mutated) @@ -413,7 +413,7 @@ where 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; 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; if rand.below(2) == 0 { *ptr = val; @@ -441,7 +441,7 @@ where 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; 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; if rand.below(2) == 0 { *ptr = val; @@ -495,8 +495,8 @@ where let len = rand.below(min(16, mutator.max_size() as u64 - 1) + 1) as usize; input.bytes_mut().resize(size + len, 0); - //println!("Size {}, off {}, len {}", size, off, len); - self_mem_move(input.bytes_mut(), 0, 0 + off, len); + buffer_self_copy(input.bytes_mut(), 0, 0 + off, len); + Ok(MutationResult::Mutated) } @@ -523,9 +523,11 @@ where let len = rand.below(max(16, mutator.max_size() as u64)) as usize; let val = input.bytes()[rand.below(size as u64) as usize]; + input.bytes_mut().resize(max(size, off + (2 * len) + 1), 0); - self_mem_move(input.bytes_mut(), off, off + len, len); - memset(input.bytes_mut(), off, len, val); + buffer_self_copy(input.bytes_mut(), off, off + len, len); + buffer_set(input.bytes_mut(), off, len, val); + Ok(MutationResult::Mutated) } @@ -551,9 +553,11 @@ where let len = rand.below(core::cmp::min(16, mutator.max_size() as u64)) as usize; let val = rand.below(256) as u8; + input.bytes_mut().resize(max(size, off + (2 * len) + 1), 0); - self_mem_move(input.bytes_mut(), off, off + len, len); - memset(input.bytes_mut(), off, len, val); + buffer_self_copy(input.bytes_mut(), off, off + len, len); + buffer_set(input.bytes_mut(), off, len, val); + Ok(MutationResult::Mutated) } @@ -578,8 +582,10 @@ where } else { rand.below(size as u64 - 1) as usize }; + let end = rand.between(start as u64, size as u64) as usize; - memset(input.bytes_mut(), start, end - start, val); + buffer_set(input.bytes_mut(), start, end - start, val); + Ok(MutationResult::Mutated) } @@ -604,8 +610,10 @@ where } else { rand.below(size as u64 - 1) as usize }; + let len = rand.below((size - start) as u64) as usize; - memset(input.bytes_mut(), start, len, val); + buffer_set(input.bytes_mut(), start, len, val); + Ok(MutationResult::Mutated) } @@ -628,7 +636,8 @@ where let to = rand.below(input.bytes().len() as u64 - 1) as usize; let len = rand.below((size - core::cmp::max(from, to)) as u64) as usize; - self_mem_move(input.bytes_mut(), from, to, len); + buffer_self_copy(input.bytes_mut(), from, to, len); + Ok(MutationResult::Mutated) } @@ -652,28 +661,12 @@ where let len = max(rand.below((size - max(first, second)) as u64) as usize, 1); let tmp = input.bytes()[first..=first + len].to_vec(); - self_mem_move(input.bytes_mut(), second, first, len); - mem_move(input.bytes_mut(), &tmp, 0, second, len); + buffer_self_copy(input.bytes_mut(), second, first, len); + buffer_copy(input.bytes_mut(), &tmp, 0, second, len); Ok(MutationResult::Mutated) } -/// Returns the first and last diff position between the given vectors, stopping at the min len -fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) { - let mut first_diff: i64 = -1; - let mut last_diff: i64 = -1; - for (i, (this_el, other_el)) in this.iter().zip(other.iter()).enumerate() { - if this_el != other_el { - if first_diff < 0 { - first_diff = i as i64; - } - last_diff = i as i64; - } - } - - (first_diff, last_diff) -} - /// Crossover insert mutation pub fn mutation_crossover_insert( _: &mut M, @@ -708,13 +701,13 @@ where let len = rand.below((other_size - from) as u64) as usize; input.bytes_mut().resize(max(size, to + (2 * len) + 1), 0); - self_mem_move(input.bytes_mut(), to, to + len, len); - mem_move(input.bytes_mut(), other.bytes(), from, to, len); + buffer_self_copy(input.bytes_mut(), to, to + len, len); + buffer_copy(input.bytes_mut(), other.bytes(), from, to, len); Ok(MutationResult::Mutated) } -/// Crossover insert mutation +/// Crossover replace mutation pub fn mutation_crossover_replace( _: &mut M, rand: &mut R, @@ -744,16 +737,30 @@ where } let from = rand.below(other_size as u64 -1) as usize; - let len = rand.below(core::cmp::min(other_size - from, size) as u64) as usize; - let to = rand.below(input.bytes().len() 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 -1) as usize; - input.bytes_mut().resize(size + len, 0); - self_mem_move(input.bytes_mut(), to, to + len, len); - mem_move(input.bytes_mut(), other.bytes(), from, to, len); + buffer_copy(input.bytes_mut(), other.bytes(), from, to, len); Ok(MutationResult::Mutated) } +/// Returns the first and last diff position between the given vectors, stopping at the min len +fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) { + let mut first_diff: i64 = -1; + let mut last_diff: i64 = -1; + for (i, (this_el, other_el)) in this.iter().zip(other.iter()).enumerate() { + if this_el != other_el { + if first_diff < 0 { + first_diff = i as i64; + } + last_diff = i as i64; + } + } + + (first_diff, last_diff) +} + /// Splicing mutation from AFL pub fn mutation_splice( _: &mut M, diff --git a/afl/src/mutators/scheduled.rs b/afl/src/mutators/scheduled.rs index 74e170dd30..f154d70899 100644 --- a/afl/src/mutators/scheduled.rs +++ b/afl/src/mutators/scheduled.rs @@ -309,6 +309,8 @@ where */ scheduled.add_mutation(mutation_crossover_insert); + scheduled.add_mutation(mutation_crossover_replace); + //scheduled.add_mutation(mutation_splice); HavocBytesMutator { scheduled: scheduled, diff --git a/afl/src/mutators/token_mutations.rs b/afl/src/mutators/token_mutations.rs index d762d07ff5..f1fe11c17a 100644 --- a/afl/src/mutators/token_mutations.rs +++ b/afl/src/mutators/token_mutations.rs @@ -13,25 +13,7 @@ use alloc::vec::Vec; use core::any::Any; use serde::{Deserialize, Serialize}; -/// Mem move between vecs -#[inline] -fn mem_move(dst: &mut [u8], src: &[u8], from: usize, to: usize, len: usize) { - debug_assert!(dst.len() > 0); - debug_assert!(src.len() > 0); - debug_assert!(from + len < src.len()); - debug_assert!(to + len < dst.len()); - let dst_ptr = dst.as_mut_ptr(); - let src_ptr = src.as_ptr(); - if len != 0 { - unsafe { - core::ptr::copy( - src_ptr.offset(from as isize), - dst_ptr.offset(to as isize), - len, - ) - } - } -} +use mutations::buffer_copy; #[derive(Serialize, Deserialize)] pub struct TokensMetadata { @@ -86,7 +68,8 @@ where } as usize; input.bytes_mut().resize(size + token_len, 0); - mem_move(input.bytes_mut(), token, 0, off, size); + buffer_copy(input.bytes_mut(), token, 0, off, size); + Ok(MutationResult::Mutated) } @@ -119,6 +102,8 @@ where let token_len = token.len(); let size = input.bytes().len(); let off = rand.below((mutator.max_size() - token_len) as u64) as usize; - mem_move(input.bytes_mut(), token, 0, off, size); + + buffer_copy(input.bytes_mut(), token, 0, off, size); + Ok(MutationResult::Mutated) }