crossover

This commit is contained in:
Andrea Fioraldi 2021-02-12 15:47:32 +01:00
parent 43b6776735
commit 6ac715946c
3 changed files with 67 additions and 73 deletions

View File

@ -84,7 +84,7 @@ where
/// Mem move in the own vec /// Mem move in the own vec
#[inline] #[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!(data.len() > 0);
debug_assert!(from + len < data.len()); debug_assert!(from + len < data.len());
debug_assert!(to + 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 /// Mem move between vecs
#[inline] #[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!(dst.len() > 0);
debug_assert!(src.len() > 0); debug_assert!(src.len() > 0);
debug_assert!(from + len < src.len()); 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. /// The compiler does the heavy lifting.
/// see https://stackoverflow.com/a/51732799/1345238 /// see https://stackoverflow.com/a/51732799/1345238
#[inline] #[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()); debug_assert!(from + len <= data.len());
for p in &mut data[from..from + len] { for p in &mut data[from..from + len] {
*p = val *p = val
@ -141,7 +141,7 @@ where
} else { } else {
let bit = rand.below((input.bytes().len() << 3) as u64) as usize; let bit = rand.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;
} }
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
@ -163,7 +163,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64) as usize; let idx = rand.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;
} }
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
@ -185,7 +185,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64) as usize; let idx = rand.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);
*ptr = (*ptr).wrapping_add(1); *ptr = (*ptr).wrapping_add(1);
} }
@ -208,7 +208,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64) as usize; let idx = rand.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);
*ptr = (*ptr).wrapping_sub(1); *ptr = (*ptr).wrapping_sub(1);
} }
@ -231,7 +231,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64) as usize; let idx = rand.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));
} }
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
@ -253,7 +253,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64) as usize; let idx = rand.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) = rand.below(256) as u8;
} }
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
@ -275,7 +275,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64) as usize; let idx = rand.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 + rand.below(ARITH_MAX) as u8;
match rand.below(2) { match rand.below(2) {
@ -302,7 +302,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64 - 1) as usize; let idx = rand.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 + rand.below(ARITH_MAX) as u16;
match rand.below(4) { match rand.below(4) {
@ -331,7 +331,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64 - 3) as usize; let idx = rand.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 + rand.below(ARITH_MAX) as u32;
match rand.below(4) { match rand.below(4) {
@ -360,7 +360,7 @@ where
} else { } else {
let idx = rand.below(input.bytes().len() as u64 - 7) as usize; let idx = rand.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 + rand.below(ARITH_MAX) as u64;
match rand.below(4) { match rand.below(4) {
@ -390,7 +390,7 @@ where
let idx = rand.below(input.bytes().len() as u64) as usize; 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 val = INTERESTING_8[rand.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;
} }
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
@ -413,7 +413,7 @@ where
let idx = rand.below(input.bytes().len() as u64 - 1) as usize; 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 val = INTERESTING_16[rand.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 rand.below(2) == 0 {
*ptr = val; *ptr = val;
@ -441,7 +441,7 @@ where
let idx = rand.below(input.bytes().len() as u64 - 3) as usize; 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 val = INTERESTING_32[rand.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 rand.below(2) == 0 {
*ptr = val; *ptr = val;
@ -495,8 +495,8 @@ where
let len = rand.below(min(16, mutator.max_size() as u64 - 1) + 1) as usize; let len = rand.below(min(16, mutator.max_size() as u64 - 1) + 1) as usize;
input.bytes_mut().resize(size + len, 0); input.bytes_mut().resize(size + len, 0);
//println!("Size {}, off {}, len {}", size, off, len); buffer_self_copy(input.bytes_mut(), 0, 0 + off, len);
self_mem_move(input.bytes_mut(), 0, 0 + off, len);
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
@ -523,9 +523,11 @@ where
let len = rand.below(max(16, mutator.max_size() as u64)) as usize; let len = rand.below(max(16, mutator.max_size() as u64)) as usize;
let val = input.bytes()[rand.below(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); input.bytes_mut().resize(max(size, off + (2 * len) + 1), 0);
self_mem_move(input.bytes_mut(), off, off + len, len); buffer_self_copy(input.bytes_mut(), off, off + len, len);
memset(input.bytes_mut(), off, len, val); buffer_set(input.bytes_mut(), off, len, val);
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
@ -551,9 +553,11 @@ where
let len = rand.below(core::cmp::min(16, mutator.max_size() as u64)) as usize; let len = rand.below(core::cmp::min(16, mutator.max_size() as u64)) as usize;
let val = rand.below(256) as u8; let val = rand.below(256) as u8;
input.bytes_mut().resize(max(size, off + (2 * len) + 1), 0); input.bytes_mut().resize(max(size, off + (2 * len) + 1), 0);
self_mem_move(input.bytes_mut(), off, off + len, len); buffer_self_copy(input.bytes_mut(), off, off + len, len);
memset(input.bytes_mut(), off, len, val); buffer_set(input.bytes_mut(), off, len, val);
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
@ -578,8 +582,10 @@ where
} else { } else {
rand.below(size as u64 - 1) as usize rand.below(size as u64 - 1) as usize
}; };
let end = rand.between(start as u64, size as u64) 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) Ok(MutationResult::Mutated)
} }
@ -604,8 +610,10 @@ where
} else { } else {
rand.below(size as u64 - 1) as usize rand.below(size as u64 - 1) as usize
}; };
let len = rand.below((size - start) as u64) 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) Ok(MutationResult::Mutated)
} }
@ -628,7 +636,8 @@ where
let to = rand.below(input.bytes().len() as u64 - 1) as usize; 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; 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) Ok(MutationResult::Mutated)
} }
@ -652,28 +661,12 @@ where
let len = max(rand.below((size - max(first, second)) as u64) as usize, 1); let len = max(rand.below((size - max(first, second)) as u64) as usize, 1);
let tmp = input.bytes()[first..=first + len].to_vec(); let tmp = input.bytes()[first..=first + len].to_vec();
self_mem_move(input.bytes_mut(), second, first, len); buffer_self_copy(input.bytes_mut(), second, first, len);
mem_move(input.bytes_mut(), &tmp, 0, second, len); buffer_copy(input.bytes_mut(), &tmp, 0, second, len);
Ok(MutationResult::Mutated) 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 /// Crossover insert mutation
pub fn mutation_crossover_insert<C, I, M, R, S>( pub fn mutation_crossover_insert<C, I, M, R, S>(
_: &mut M, _: &mut M,
@ -708,13 +701,13 @@ where
let len = rand.below((other_size - from) as u64) as usize; let len = rand.below((other_size - from) as u64) as usize;
input.bytes_mut().resize(max(size, to + (2 * len) + 1), 0); input.bytes_mut().resize(max(size, to + (2 * len) + 1), 0);
self_mem_move(input.bytes_mut(), to, to + len, len); buffer_self_copy(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) Ok(MutationResult::Mutated)
} }
/// Crossover insert 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, rand: &mut R,
@ -744,16 +737,30 @@ where
} }
let from = rand.below(other_size as u64 -1) as usize; 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 len = rand.below(min(other_size - from, size) as u64) as usize;
let to = rand.below(input.bytes().len() as u64) as usize; let to = rand.below((size - len) as u64 -1) as usize;
input.bytes_mut().resize(size + len, 0); buffer_copy(input.bytes_mut(), other.bytes(), from, to, len);
self_mem_move(input.bytes_mut(), to, to + len, len);
mem_move(input.bytes_mut(), other.bytes(), from, to, len);
Ok(MutationResult::Mutated) 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 /// 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,

View File

@ -309,6 +309,8 @@ where
*/ */
scheduled.add_mutation(mutation_crossover_insert); scheduled.add_mutation(mutation_crossover_insert);
scheduled.add_mutation(mutation_crossover_replace);
//scheduled.add_mutation(mutation_splice);
HavocBytesMutator { HavocBytesMutator {
scheduled: scheduled, scheduled: scheduled,

View File

@ -13,25 +13,7 @@ use alloc::vec::Vec;
use core::any::Any; use core::any::Any;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// Mem move between vecs use mutations::buffer_copy;
#[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,
)
}
}
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct TokensMetadata { pub struct TokensMetadata {
@ -86,7 +68,8 @@ where
} as usize; } as usize;
input.bytes_mut().resize(size + token_len, 0); 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) Ok(MutationResult::Mutated)
} }
@ -119,6 +102,8 @@ where
let token_len = token.len(); let token_len = token.len();
let size = input.bytes().len(); let size = input.bytes().len();
let off = rand.below((mutator.max_size() - token_len) as u64) as usize; 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) Ok(MutationResult::Mutated)
} }