fix splicing

This commit is contained in:
Andrea Fioraldi 2020-11-21 11:30:13 +01:00
parent a4690046b3
commit c4180f0f47
5 changed files with 32 additions and 21 deletions

5
.gitignore vendored
View File

@ -4,5 +4,10 @@ Cargo.lock
*.o
*.a
*.so
*.out
*.elf
*.bin
*.dll
*.exe
.vscode

View File

@ -59,9 +59,10 @@ pub extern "C" fn afl_libfuzzer_main() {
for i in 0..1000 {
println!("Fuzzer corpus iteration #{}", i);
engine
let idx = engine
.fuzz_one(&mut state)
.expect(&format!("Error in iter {}", i));
println!("Fuzzed entry #{}", idx);
}
println!("OK");
}

View File

@ -58,19 +58,19 @@ where
}
/// Gets a random entry
fn random_entry(&self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
fn random_entry(&self) -> Result<(Rc<RefCell<Testcase<I>>>, usize), AflError> {
if self.count() == 0 {
Err(AflError::Empty("No entries in corpus".to_owned()))
} else {
let len = { self.entries().len() };
let id = self.rand_below(len as u64) as usize;
Ok(self.entries()[id].clone())
Ok((self.entries()[id].clone(), id))
}
}
// TODO: IntoIter
/// Gets the next entry
fn next(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
fn next(&mut self) -> Result<(Rc<RefCell<Testcase<I>>>, usize), AflError> {
self.random_entry()
}
}
@ -260,12 +260,12 @@ where
}
/// Gets a random entry
fn random_entry(&self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
fn random_entry(&self) -> Result<(Rc<RefCell<Testcase<I>>>, usize), AflError> {
self.corpus.random_entry()
}
/// Gets the next entry
fn next(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
fn next(&mut self) -> Result<(Rc<RefCell<Testcase<I>>>, usize), AflError> {
self.pos += 1;
if self.corpus.count() == 0 {
return Err(AflError::Empty("Corpus".to_owned()));
@ -275,7 +275,7 @@ where
self.pos = 1;
self.cycles += 1;
}
Ok(self.corpus.entries()[self.pos - 1].clone())
Ok((self.corpus.entries()[self.pos - 1].clone(), self.pos - 1))
}
}
@ -373,6 +373,7 @@ mod tests {
let filename = q
.next()
.unwrap()
.0
.borrow()
.filename()
.as_ref()
@ -382,6 +383,7 @@ mod tests {
filename,
q.next()
.unwrap()
.0
.borrow()
.filename()
.as_ref()

View File

@ -177,12 +177,12 @@ where
self.stages_mut().push(stage);
}
fn fuzz_one(&mut self, state: &mut S) -> Result<(), AflError> {
let testcase = state.corpus_mut().next()?;
fn fuzz_one(&mut self, state: &mut S) -> Result<usize, AflError> {
let (testcase, idx) = state.corpus_mut().next()?;
for stage in self.stages_mut() {
stage.perform(testcase.clone(), state)?;
}
Ok(())
Ok(idx)
}
}

View File

@ -9,8 +9,13 @@ use alloc::vec::Vec;
use core::cell::RefCell;
use core::marker::PhantomData;
pub enum MutationResult {
Mutated,
Skipped,
}
/// The generic function type that identifies mutations
type MutationFunction<C, M, I> = fn(&mut M, &mut C, &mut I) -> Result<(), AflError>;
type MutationFunction<C, M, I> = fn(&mut M, &mut C, &mut I) -> Result<MutationResult, AflError>;
pub trait ComposedByMutations<C, I>
where
@ -159,7 +164,7 @@ pub fn mutation_bitflip<C, M, I>(
mutator: &mut M,
_corpus: &mut C,
input: &mut I,
) -> Result<(), AflError>
) -> Result<MutationResult, AflError>
where
C: Corpus<I>,
M: HasRand,
@ -167,7 +172,7 @@ where
{
let bit = mutator.rand_below((input.bytes().len() * 8) as u64) as usize;
input.bytes_mut()[bit >> 3] ^= (128 >> (bit & 7)) as u8;
Ok(())
Ok(MutationResult::Mutated)
}
/// Returns the first and last diff position between the given vectors, stopping at the min len
@ -191,7 +196,7 @@ pub fn mutation_splice<C, M, I>(
mutator: &mut M,
corpus: &mut C,
input: &mut I,
) -> Result<(), AflError>
) -> Result<MutationResult, AflError>
where
C: Corpus<I>,
M: HasRand,
@ -201,14 +206,12 @@ where
// 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();
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".into(),
));
return Ok(MutationResult::Skipped);
}
retry_count += 1;
}
@ -230,7 +233,7 @@ where
break (f, l);
}
if counter == 20 {
return Err(AflError::Empty("No valid diff found".into()));
return Ok(MutationResult::Skipped);
}
counter += 1;
};
@ -246,7 +249,7 @@ where
// println!("Splice result: {:?}, input is now: {:?}", split_result, input.bytes());
Ok(())
Ok(MutationResult::Mutated)
}
/// Schedule some selected byte level mutations given a ScheduledMutator type
@ -342,7 +345,7 @@ mod tests {
corpus.add(Testcase::new(vec!['a' as u8, 'b' as u8, 'c' as u8]).into());
corpus.add(Testcase::new(vec!['d' as u8, 'e' as u8, 'f' as u8]).into());
let testcase_rr = corpus.next().expect("Corpus did not contain entries");
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();