fix splicing
This commit is contained in:
parent
a4690046b3
commit
c4180f0f47
5
.gitignore
vendored
5
.gitignore
vendored
@ -4,5 +4,10 @@ Cargo.lock
|
|||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.so
|
*.so
|
||||||
|
*.out
|
||||||
|
*.elf
|
||||||
|
*.bin
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
.vscode
|
.vscode
|
||||||
|
@ -59,9 +59,10 @@ pub extern "C" fn afl_libfuzzer_main() {
|
|||||||
|
|
||||||
for i in 0..1000 {
|
for i in 0..1000 {
|
||||||
println!("Fuzzer corpus iteration #{}", i);
|
println!("Fuzzer corpus iteration #{}", i);
|
||||||
engine
|
let idx = engine
|
||||||
.fuzz_one(&mut state)
|
.fuzz_one(&mut state)
|
||||||
.expect(&format!("Error in iter {}", i));
|
.expect(&format!("Error in iter {}", i));
|
||||||
|
println!("Fuzzed entry #{}", idx);
|
||||||
}
|
}
|
||||||
println!("OK");
|
println!("OK");
|
||||||
}
|
}
|
||||||
|
@ -58,19 +58,19 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a random entry
|
/// 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 {
|
if self.count() == 0 {
|
||||||
Err(AflError::Empty("No entries in corpus".to_owned()))
|
Err(AflError::Empty("No entries in corpus".to_owned()))
|
||||||
} else {
|
} else {
|
||||||
let len = { self.entries().len() };
|
let len = { self.entries().len() };
|
||||||
let id = self.rand_below(len as u64) as usize;
|
let id = self.rand_below(len as u64) as usize;
|
||||||
Ok(self.entries()[id].clone())
|
Ok((self.entries()[id].clone(), id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: IntoIter
|
// TODO: IntoIter
|
||||||
/// Gets the next 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.random_entry()
|
self.random_entry()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,12 +260,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a random entry
|
/// 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()
|
self.corpus.random_entry()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the next 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;
|
self.pos += 1;
|
||||||
if self.corpus.count() == 0 {
|
if self.corpus.count() == 0 {
|
||||||
return Err(AflError::Empty("Corpus".to_owned()));
|
return Err(AflError::Empty("Corpus".to_owned()));
|
||||||
@ -275,7 +275,7 @@ where
|
|||||||
self.pos = 1;
|
self.pos = 1;
|
||||||
self.cycles += 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
|
let filename = q
|
||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.0
|
||||||
.borrow()
|
.borrow()
|
||||||
.filename()
|
.filename()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -382,6 +383,7 @@ mod tests {
|
|||||||
filename,
|
filename,
|
||||||
q.next()
|
q.next()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.0
|
||||||
.borrow()
|
.borrow()
|
||||||
.filename()
|
.filename()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -177,12 +177,12 @@ where
|
|||||||
self.stages_mut().push(stage);
|
self.stages_mut().push(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fuzz_one(&mut self, state: &mut S) -> Result<(), AflError> {
|
fn fuzz_one(&mut self, state: &mut S) -> Result<usize, AflError> {
|
||||||
let testcase = state.corpus_mut().next()?;
|
let (testcase, idx) = state.corpus_mut().next()?;
|
||||||
for stage in self.stages_mut() {
|
for stage in self.stages_mut() {
|
||||||
stage.perform(testcase.clone(), state)?;
|
stage.perform(testcase.clone(), state)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,13 @@ use alloc::vec::Vec;
|
|||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
pub enum MutationResult {
|
||||||
|
Mutated,
|
||||||
|
Skipped,
|
||||||
|
}
|
||||||
|
|
||||||
/// The generic function type that identifies mutations
|
/// 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>
|
pub trait ComposedByMutations<C, I>
|
||||||
where
|
where
|
||||||
@ -159,7 +164,7 @@ pub fn mutation_bitflip<C, M, I>(
|
|||||||
mutator: &mut M,
|
mutator: &mut M,
|
||||||
_corpus: &mut C,
|
_corpus: &mut C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<(), AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
M: HasRand,
|
M: HasRand,
|
||||||
@ -167,7 +172,7 @@ where
|
|||||||
{
|
{
|
||||||
let bit = mutator.rand_below((input.bytes().len() * 8) as u64) as usize;
|
let bit = mutator.rand_below((input.bytes().len() * 8) as u64) as usize;
|
||||||
input.bytes_mut()[bit >> 3] ^= (128 >> (bit & 7)) as u8;
|
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
|
/// 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,
|
mutator: &mut M,
|
||||||
corpus: &mut C,
|
corpus: &mut C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<(), AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
M: HasRand,
|
M: HasRand,
|
||||||
@ -201,14 +206,12 @@ where
|
|||||||
// We don't want to use the testcase we're already using for splicing
|
// We don't want to use the testcase we're already using for splicing
|
||||||
let other_rr = loop {
|
let other_rr = loop {
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
let other_rr = corpus.random_entry()?.clone();
|
let (other_rr, _) = corpus.random_entry()?.clone();
|
||||||
match other_rr.try_borrow_mut() {
|
match other_rr.try_borrow_mut() {
|
||||||
Ok(_) => found = true,
|
Ok(_) => found = true,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
if retry_count == 20 {
|
if retry_count == 20 {
|
||||||
return Err(AflError::Empty(
|
return Ok(MutationResult::Skipped);
|
||||||
"No suitable testcase found for splicing".into(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
retry_count += 1;
|
retry_count += 1;
|
||||||
}
|
}
|
||||||
@ -230,7 +233,7 @@ where
|
|||||||
break (f, l);
|
break (f, l);
|
||||||
}
|
}
|
||||||
if counter == 20 {
|
if counter == 20 {
|
||||||
return Err(AflError::Empty("No valid diff found".into()));
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
counter += 1;
|
counter += 1;
|
||||||
};
|
};
|
||||||
@ -246,7 +249,7 @@ where
|
|||||||
|
|
||||||
// println!("Splice result: {:?}, input is now: {:?}", split_result, input.bytes());
|
// println!("Splice result: {:?}, input is now: {:?}", split_result, input.bytes());
|
||||||
|
|
||||||
Ok(())
|
Ok(MutationResult::Mutated)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule some selected byte level mutations given a ScheduledMutator type
|
/// 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!['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());
|
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 testcase = testcase_rr.borrow_mut();
|
||||||
let mut input = testcase.load_input().expect("No input in testcase").clone();
|
let mut input = testcase.load_input().expect("No input in testcase").clone();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user