crossover insert mutation (fast splicing)
This commit is contained in:
parent
02fb44b5cc
commit
43b6776735
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user