crossover insert mutation (fast splicing)

This commit is contained in:
Andrea Fioraldi 2021-02-12 14:45:43 +01:00
parent 02fb44b5cc
commit 43b6776735
2 changed files with 85 additions and 9 deletions

View File

@ -654,6 +654,7 @@ where
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); self_mem_move(input.bytes_mut(), second, first, len);
mem_move(input.bytes_mut(), &tmp, 0, second, len); mem_move(input.bytes_mut(), &tmp, 0, second, len);
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }
@ -673,7 +674,87 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
(first_diff, last_diff) (first_diff, last_diff)
} }
/// Splicing mutator /// Crossover insert mutation
pub fn mutation_crossover_insert<C, I, M, R, S>(
_: &mut M,
rand: &mut R,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, AflError>
where
C: Corpus<I, R>,
I: Input + HasBytesVec,
R: Rand,
S: HasCorpus<C, I, R>,
{
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)?;
if idx == state.corpus().current_testcase().1 {
return Ok(MutationResult::Skipped);
}
let mut other_ref = other_testcase.borrow_mut();
let other = other_ref.load_input()?;
let other_size = other.bytes().len();
if other_size < 2 {
return Ok(MutationResult::Skipped);
}
let from = rand.below(other_size as u64 -1) as usize;
let to = rand.below(size as u64 -1) as usize;
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);
Ok(MutationResult::Mutated)
}
/// Crossover insert mutation
pub fn mutation_crossover_replace<C, I, M, R, S>(
_: &mut M,
rand: &mut R,
state: &mut S,
input: &mut I,
) -> Result<MutationResult, AflError>
where
C: Corpus<I, R>,
I: Input + HasBytesVec,
R: Rand,
S: HasCorpus<C, I, R>,
{
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)?;
if idx == state.corpus().current_testcase().1 {
return Ok(MutationResult::Skipped);
}
let mut other_ref = other_testcase.borrow_mut();
let other = other_ref.load_input()?;
let other_size = other.bytes().len();
if other_size < 2 {
return Ok(MutationResult::Skipped);
}
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;
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);
Ok(MutationResult::Mutated)
}
/// 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, rand: &mut R,
@ -691,14 +772,14 @@ where
if idx == state.corpus().current_testcase().1 { if idx == state.corpus().current_testcase().1 {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
} }
// println!("Input: {:?}, other input: {:?}", input.bytes(), other.bytes());
let mut other_ref = other_testcase.borrow_mut(); let mut other_ref = other_testcase.borrow_mut();
let other = other_ref.load_input()?; let other = other_ref.load_input()?;
let mut counter = 0; let mut counter = 0;
let (first_diff, last_diff) = loop { let (first_diff, last_diff) = loop {
let (f, l) = locate_diffs(input.bytes(), other.bytes()); let (f, l) = locate_diffs(input.bytes(), other.bytes());
// println!("Diffs were between {} and {}", f, l);
if f != l && f >= 0 && l >= 2 { if f != l && f >= 0 && l >= 2 {
break (f, l); break (f, l);
} }
@ -709,15 +790,10 @@ where
}; };
let split_at = rand.between(first_diff as u64, last_diff as u64) as usize; let split_at = rand.between(first_diff as u64, last_diff as u64) as usize;
// println!("Splicing at {}", split_at);
input input
.bytes_mut() .bytes_mut()
.splice(split_at.., other.bytes()[split_at..].iter().cloned()); .splice(split_at.., other.bytes()[split_at..].iter().cloned());
// println!("Splice result: {:?}, input is now: {:?}", split_result, input.bytes());
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }

View File

@ -308,7 +308,7 @@ where
scheduled.add_mutation(mutation_tokenreplace); scheduled.add_mutation(mutation_tokenreplace);
*/ */
scheduled.add_mutation(mutation_splice); scheduled.add_mutation(mutation_crossover_insert);
HavocBytesMutator { HavocBytesMutator {
scheduled: scheduled, scheduled: scheduled,