From c4180f0f47b95573f487c3773af7ffe479046561 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Sat, 21 Nov 2020 11:30:13 +0100 Subject: [PATCH] fix splicing --- .gitignore | 5 +++++ fuzzers/libfuzzer/src/lib.rs | 3 ++- src/corpus/mod.rs | 14 ++++++++------ src/engines/mod.rs | 6 +++--- src/mutators/scheduled.rs | 25 ++++++++++++++----------- 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 3c5a9684eb..79b87e41b8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,10 @@ Cargo.lock *.o *.a *.so +*.out +*.elf +*.bin +*.dll +*.exe .vscode diff --git a/fuzzers/libfuzzer/src/lib.rs b/fuzzers/libfuzzer/src/lib.rs index 6ff33bed49..9a4645e871 100644 --- a/fuzzers/libfuzzer/src/lib.rs +++ b/fuzzers/libfuzzer/src/lib.rs @@ -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"); } diff --git a/src/corpus/mod.rs b/src/corpus/mod.rs index e16b00c0c1..abf1a844a2 100644 --- a/src/corpus/mod.rs +++ b/src/corpus/mod.rs @@ -58,19 +58,19 @@ where } /// Gets a random entry - fn random_entry(&self) -> Result>>, AflError> { + fn random_entry(&self) -> Result<(Rc>>, 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>>, AflError> { + fn next(&mut self) -> Result<(Rc>>, usize), AflError> { self.random_entry() } } @@ -260,12 +260,12 @@ where } /// Gets a random entry - fn random_entry(&self) -> Result>>, AflError> { + fn random_entry(&self) -> Result<(Rc>>, usize), AflError> { self.corpus.random_entry() } /// Gets the next entry - fn next(&mut self) -> Result>>, AflError> { + fn next(&mut self) -> Result<(Rc>>, 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() diff --git a/src/engines/mod.rs b/src/engines/mod.rs index d05eb759fc..adb10f40b9 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -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 { + let (testcase, idx) = state.corpus_mut().next()?; for stage in self.stages_mut() { stage.perform(testcase.clone(), state)?; } - Ok(()) + Ok(idx) } } diff --git a/src/mutators/scheduled.rs b/src/mutators/scheduled.rs index 8d88d6ef3e..91b3122bc6 100644 --- a/src/mutators/scheduled.rs +++ b/src/mutators/scheduled.rs @@ -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 = fn(&mut M, &mut C, &mut I) -> Result<(), AflError>; +type MutationFunction = fn(&mut M, &mut C, &mut I) -> Result; pub trait ComposedByMutations where @@ -159,7 +164,7 @@ pub fn mutation_bitflip( mutator: &mut M, _corpus: &mut C, input: &mut I, -) -> Result<(), AflError> +) -> Result where C: Corpus, 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( mutator: &mut M, corpus: &mut C, input: &mut I, -) -> Result<(), AflError> +) -> Result where C: Corpus, 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();