fixed splicing mutator

This commit is contained in:
Dominik Maier 2020-11-11 14:18:59 +01:00
parent 47ca9e3f6b
commit d0f2507ab4
3 changed files with 93 additions and 31 deletions

View File

@ -38,6 +38,11 @@ where
self.entries_mut().push(entry); self.entries_mut().push(entry);
} }
/// Add an input to the corpus
fn add_input(&mut self, input: I) {
self.add(Testcase::new_rr(input));
}
/// Removes an entry from the corpus, returning it if it was present. /// Removes an entry from the corpus, returning it if it was present.
fn remove(&mut self, entry: &Testcase<I>) -> Option<Rc<RefCell<Testcase<I>>>> { fn remove(&mut self, entry: &Testcase<I>) -> Option<Rc<RefCell<Testcase<I>>>> {
let mut i: usize = 0; let mut i: usize = 0;

View File

@ -162,7 +162,7 @@ pub fn mutation_bitflip<C, M, I>(
) -> Result<(), AflError> ) -> Result<(), AflError>
where where
C: Corpus<I>, C: Corpus<I>,
M: Mutator<C, I>, M: HasRand,
I: Input + HasBytesVec, I: Input + HasBytesVec,
{ {
let bit = mutator.rand_below(input.bytes().len() as u64) as usize; let bit = mutator.rand_below(input.bytes().len() as u64) as usize;
@ -194,10 +194,28 @@ pub fn mutation_splice<C, M, I>(
) -> Result<(), AflError> ) -> Result<(), AflError>
where where
C: Corpus<I>, C: Corpus<I>,
M: Mutator<C, I>, M: HasRand,
I: Input + HasBytesVec, I: Input + HasBytesVec,
{ {
let other_rr = corpus.random_entry()?; let mut retry_count = 0;
// We don't want to use the testcase we're already using for splicing
let other_rr = loop {
let mut found = false;
let other_rr = corpus.random_entry()?.clone();
match other_rr.try_borrow_mut() {
Ok(_) => found = true,
Err(_) => {
if retry_count == 20 {
return Err(AflError::Empty("No suitable testcase found for splicing".to_owned()));
}
retry_count += 1;
},
};
if found {
break other_rr;
}
};
// This should work now, as we successfully try_borrow_mut'd before.
let mut other_testcase = other_rr.borrow_mut(); let mut other_testcase = other_rr.borrow_mut();
let other = other_testcase.load_input()?; let other = other_testcase.load_input()?;
@ -215,11 +233,12 @@ where
let split_at = mutator.rand_between(first_diff as u64, last_diff as u64) as usize; let split_at = mutator.rand_between(first_diff as u64, last_diff as u64) as usize;
Err(AflError::NotImplemented(format!("TODO: fix Splice (would split at {})", split_at))) let _: Vec<_> = input
.bytes_mut()
.splice(split_at.., other.bytes()[split_at..].iter().cloned())
.collect();
//input.bytes_mut().splice(split_at.., other.bytes()[split_at..]).collect(); Ok(())
//Ok(())
} }
/// Schedule some selected byte level mutations given a ScheduledMutator type /// Schedule some selected byte level mutations given a ScheduledMutator type
@ -292,3 +311,29 @@ where
} }
} }
} }
#[cfg(test)]
mod tests {
use crate::corpus::{Corpus, InMemoryCorpus};
use crate::inputs::BytesInput;
use crate::mutators::scheduled::mutation_splice;
use crate::utils::{Xoshiro256StarRand, DefaultHasRand};
#[test]
fn test_mut_splice() {
let rand = &Xoshiro256StarRand::new_rr(0);
let mut has_rand = DefaultHasRand::new(&rand);
let mut corpus = InMemoryCorpus::new(&rand);
corpus.add_input(BytesInput::new(vec!['a' as u8, 'b' as u8, 'c' as u8]));
corpus.add_input(BytesInput::new(vec!['d' as u8, 'e' as u8, 'f' as u8]));
let testcase_rr = corpus.next().expect("Corpus did not contain entries");
let mut testcase = testcase_rr.borrow_mut();
let mut input = testcase.load_input().expect("No input in testcase").clone();
mutation_splice(&mut has_rand, &mut corpus, &mut input).unwrap()
// TODO: Finish testcase
}
}

View File

@ -136,6 +136,40 @@ impl Xoshiro256StarRand {
} }
} }
/// A very basic HasRand
pub struct DefaultHasRand<R>
where
R: Rand,
{
rand: Rc<RefCell<R>>,
}
/// A very basic HasRand
impl<R> HasRand for DefaultHasRand<R>
where
R: Rand,
{
type R = R;
/// Get the rand rc refcell
fn rand(&self) -> &Rc<RefCell<R>> {
&self.rand
}
}
/// A very basic HasRand
impl<R> DefaultHasRand<R>
where
R: Rand,
{
/// Create a new DefaultHasRand, cloning the refcell
pub fn new(rand: &Rc<RefCell<R>>) -> Self {
Self {
rand: Rc::clone(rand),
}
}
}
/// Get the next higher power of two /// Get the next higher power of two
pub fn next_pow2(val: u64) -> u64 { pub fn next_pow2(val: u64) -> u64 {
let mut out = val.wrapping_sub(1); let mut out = val.wrapping_sub(1);
@ -149,7 +183,7 @@ pub fn next_pow2(val: u64) -> u64 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::utils::{next_pow2, HasRand, Rand, Xoshiro256StarRand}; use crate::utils::{next_pow2, DefaultHasRand, HasRand, Rand, Xoshiro256StarRand};
#[test] #[test]
fn test_rand() { fn test_rand() {
@ -161,32 +195,10 @@ mod tests {
assert!(rand.between(11, 20) > 10); assert!(rand.between(11, 20) > 10);
} }
use alloc::rc::Rc;
use core::cell::RefCell;
struct HasRandTest<R>
where
R: Rand,
{
rand: Rc<RefCell<R>>,
}
impl<R> HasRand for HasRandTest<R>
where
R: Rand,
{
type R = R;
fn rand(&self) -> &Rc<RefCell<R>> {
&self.rand
}
}
#[test] #[test]
fn test_has_rand() { fn test_has_rand() {
let rand = Xoshiro256StarRand::preseeded_rr(); let rand = Xoshiro256StarRand::preseeded_rr();
let has_rand = HasRandTest { let has_rand = DefaultHasRand::new(&rand);
rand: Rc::clone(&rand),
};
assert!(has_rand.rand_below(100) < 100); assert!(has_rand.rand_below(100) < 100);
assert_eq!(has_rand.rand_below(1), 0); assert_eq!(has_rand.rand_below(1), 0);