testcase refcell

This commit is contained in:
Andrea Fioraldi 2020-12-09 11:58:57 +01:00
parent 2c299a1518
commit 016f2f30a5
8 changed files with 50 additions and 55 deletions

View File

@ -4,6 +4,7 @@ pub use testcase::{Testcase, TestcaseMetadata};
use alloc::borrow::ToOwned; use alloc::borrow::ToOwned;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::cell::RefCell;
use core::ptr; use core::ptr;
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -18,10 +19,10 @@ where
I: Input, I: Input,
{ {
/// Get the entries vector field /// Get the entries vector field
fn entries(&self) -> &[Testcase<I>]; fn entries(&self) -> &[RefCell<Testcase<I>>];
/// Get the entries vector field (mutable) /// Get the entries vector field (mutable)
fn entries_mut(&mut self) -> &mut Vec<Testcase<I>>; fn entries_mut(&mut self) -> &mut Vec<RefCell<Testcase<I>>>;
} }
/// Corpus with all current testcases /// Corpus with all current testcases
@ -37,7 +38,7 @@ where
/// Add an entry to the corpus and return its index /// Add an entry to the corpus and return its index
fn add(&mut self, testcase: Testcase<I>) -> usize { fn add(&mut self, testcase: Testcase<I>) -> usize {
self.entries_mut().push(testcase); self.entries_mut().push(RefCell::new(testcase));
self.entries().len() - 1 self.entries().len() - 1
} }
@ -49,25 +50,25 @@ where
idx idx
))); )));
} }
self.entries_mut()[idx] = testcase; self.entries_mut()[idx] = RefCell::new(testcase);
Ok(()) Ok(())
} }
/// Get by id /// Get by id
fn get(&self, idx: usize) -> &Testcase<I> { fn get(&self, idx: usize) -> &RefCell<Testcase<I>> {
&self.entries()[idx] &self.entries()[idx]
} }
/// 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<Testcase<I>> { fn remove(&mut self, entry: &Testcase<I>) -> Option<Testcase<I>> {
match self.entries().iter().position(|x| ptr::eq(x, entry)) { match self.entries().iter().position(|x| ptr::eq(x.as_ptr(), entry)) {
Some(i) => Some(self.entries_mut().remove(i)), Some(i) => Some(self.entries_mut().remove(i).into_inner()),
None => None, None => None,
} }
} }
/// Gets a random entry /// Gets a random entry
fn random_entry(&self, rand: &mut R) -> Result<(&Testcase<I>, usize), AflError> { fn random_entry(&self, rand: &mut R) -> Result<(&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 {
@ -78,7 +79,7 @@ where
} }
/// Returns the testcase for the given idx, with loaded input /// Returns the testcase for the given idx, with loaded input
fn load_testcase(&mut self, idx: usize) -> Result<(), AflError> { /*fn load_testcase(&mut self, idx: usize) -> Result<(), AflError> {
let testcase = self.get(idx); let testcase = self.get(idx);
// Ensure testcase is loaded // Ensure testcase is loaded
match testcase.input() { match testcase.input() {
@ -97,14 +98,14 @@ where
_ => (), _ => (),
} }
Ok(()) Ok(())
} }*/
// TODO: IntoIter // TODO: IntoIter
/// Gets the next entry /// Gets the next entry
fn next(&mut self, rand: &mut R) -> Result<(&Testcase<I>, usize), AflError>; fn next(&mut self, rand: &mut R) -> Result<(&RefCell<Testcase<I>>, usize), AflError>;
/// Returns the testacase we currently use /// Returns the testacase we currently use
fn current_testcase(&self) -> (&Testcase<I>, usize); fn current_testcase(&self) -> (&RefCell<Testcase<I>>, usize);
} }
pub struct InMemoryCorpus<I, R> pub struct InMemoryCorpus<I, R>
@ -112,7 +113,7 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
entries: Vec<Testcase<I>>, entries: Vec<RefCell<Testcase<I>>>,
pos: usize, pos: usize,
phantom: PhantomData<R>, phantom: PhantomData<R>,
} }
@ -122,10 +123,10 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
fn entries(&self) -> &[Testcase<I>] { fn entries(&self) -> &[RefCell<Testcase<I>>] {
&self.entries &self.entries
} }
fn entries_mut(&mut self) -> &mut Vec<Testcase<I>> { fn entries_mut(&mut self) -> &mut Vec<RefCell<Testcase<I>>> {
&mut self.entries &mut self.entries
} }
} }
@ -136,7 +137,7 @@ where
R: Rand, R: Rand,
{ {
/// Gets the next entry /// Gets the next entry
fn next(&mut self, rand: &mut R) -> Result<(&Testcase<I>, usize), AflError> { fn next(&mut self, rand: &mut R) -> Result<(&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 {
@ -148,7 +149,7 @@ where
} }
/// Returns the testacase we currently use /// Returns the testacase we currently use
fn current_testcase(&self) -> (&Testcase<I>, usize) { fn current_testcase(&self) -> (&RefCell<Testcase<I>>, usize) {
(self.get(self.pos), self.pos) (self.get(self.pos), self.pos)
} }
} }
@ -173,7 +174,7 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
entries: Vec<Testcase<I>>, entries: Vec<RefCell<Testcase<I>>>,
dir_path: PathBuf, dir_path: PathBuf,
pos: usize, pos: usize,
phantom: PhantomData<R>, phantom: PhantomData<R>,
@ -185,10 +186,10 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
fn entries(&self) -> &[Testcase<I>] { fn entries(&self) -> &[RefCell<Testcase<I>>] {
&self.entries &self.entries
} }
fn entries_mut(&mut self) -> &mut Vec<Testcase<I>> { fn entries_mut(&mut self) -> &mut Vec<RefCell<Testcase<I>>> {
&mut self.entries &mut self.entries
} }
} }
@ -210,16 +211,16 @@ where
} }
_ => {} _ => {}
} }
self.entries.push(entry); self.entries.push(RefCell::new(entry));
self.entries.len() - 1 self.entries.len() - 1
} }
fn current_testcase(&self) -> (&Testcase<I>, usize) { fn current_testcase(&self) -> (&RefCell<Testcase<I>>, usize) {
(self.get(self.pos), self.pos) (self.get(self.pos), self.pos)
} }
/// Gets the next entry /// Gets the next entry
fn next(&mut self, rand: &mut R) -> Result<(&Testcase<I>, usize), AflError> { fn next(&mut self, rand: &mut R) -> Result<(&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 {
@ -268,10 +269,10 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
fn entries(&self) -> &[Testcase<I>] { fn entries(&self) -> &[RefCell<Testcase<I>>] {
self.corpus.entries() self.corpus.entries()
} }
fn entries_mut(&mut self) -> &mut Vec<Testcase<I>> { fn entries_mut(&mut self) -> &mut Vec<RefCell<Testcase<I>>> {
self.corpus.entries_mut() self.corpus.entries_mut()
} }
} }
@ -297,17 +298,17 @@ where
} }
/// Gets a random entry /// Gets a random entry
fn random_entry(&self, rand: &mut R) -> Result<(&Testcase<I>, usize), AflError> { fn random_entry(&self, rand: &mut R) -> Result<(&RefCell<Testcase<I>>, usize), AflError> {
self.corpus.random_entry(rand) self.corpus.random_entry(rand)
} }
/// Returns the testacase we currently use /// Returns the testacase we currently use
fn current_testcase(&self) -> (&Testcase<I>, usize) { fn current_testcase(&self) -> (&RefCell<Testcase<I>>, usize) {
(self.get(self.pos - 1), self.pos - 1) (self.get(self.pos - 1), self.pos - 1)
} }
/// Gets the next entry /// Gets the next entry
fn next(&mut self, _rand: &mut R) -> Result<(&Testcase<I>, usize), AflError> { fn next(&mut self, _rand: &mut R) -> Result<(&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()));
@ -417,6 +418,7 @@ mod tests {
.next(&mut rand) .next(&mut rand)
.unwrap() .unwrap()
.0 .0
.borrow()
.filename() .filename()
.as_ref() .as_ref()
.unwrap() .unwrap()
@ -426,6 +428,7 @@ mod tests {
q.next(&mut rand) q.next(&mut rand)
.unwrap() .unwrap()
.0 .0
.borrow()
.filename() .filename()
.as_ref() .as_ref()
.unwrap() .unwrap()

View File

@ -75,9 +75,11 @@ where
I: Input, I: Input,
{ {
/// Returns this testcase with a loaded input /// Returns this testcase with a loaded input
pub fn load_from_disk(filename: &str) -> Result<Self, AflError> { pub fn load_input(&mut self) -> Result<&I, AflError> {
let input = I::from_file(filename)?; if self.input.is_none() {
Ok(Testcase::new(input)) self.input = Some(I::from_file(self.filename.as_ref().unwrap())?);
}
Ok(self.input.as_ref().unwrap())
} }
/// Get the input, if any /// Get the input, if any

View File

@ -293,19 +293,10 @@ where
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<EM, E, C, I, R>, engine: &mut Engine<EM, E, C, I, R>,
) -> Result<usize, AflError> { ) -> Result<usize, AflError> {
let (testcase, idx) = corpus.next(rand)?; let (_, idx) = corpus.next(rand)?;
match testcase.input() {
None => {
// Load from disk.
corpus.load_testcase(idx)?;
}
_ => (),
};
let input = corpus.get(idx).input().as_ref().unwrap();
for stage in self.stages_mut() { for stage in self.stages_mut() {
stage.perform(rand, state, corpus, engine, &input)?; stage.perform(rand, state, corpus, engine, idx)?;
} }
engine.events_manager_mut().process(state, corpus)?; engine.events_manager_mut().process(state, corpus)?;

View File

@ -4,7 +4,6 @@ use core::ptr;
use crate::executors::{Executor, ExitKind}; use crate::executors::{Executor, ExitKind};
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::observer_serde::NamedSerdeAnyMap; use crate::observers::observer_serde::NamedSerdeAnyMap;
use crate::observers::Observer;
use crate::AflError; use crate::AflError;
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind; type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;

View File

@ -686,13 +686,13 @@ where
R: Rand, R: Rand,
{ {
// 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_testcase, _) = corpus.random_entry(rand)?.clone(); let (other_testcase, idx) = corpus.random_entry(rand)?;
// TODO: Load let other = Testcase::load_from_disk(other_test)?; if idx == corpus.current_testcase().1 {
return Ok(MutationResult::Skipped);
}
// println!("Input: {:?}, other input: {:?}", input.bytes(), other.bytes()); // println!("Input: {:?}, other input: {:?}", input.bytes(), other.bytes());
let other = match other_testcase.input() { let mut other_ref = other_testcase.borrow_mut();
Some(i) => i, let other = other_ref.load_input()?;
None => return Ok(MutationResult::Skipped), //TODO
};
let mut counter = 0; let mut counter = 0;
let (first_diff, last_diff) = loop { let (first_diff, last_diff) = loop {

View File

@ -265,7 +265,7 @@ mod tests {
let (testcase, _) = corpus let (testcase, _) = corpus
.next(&mut rand) .next(&mut rand)
.expect("Corpus did not contain entries"); .expect("Corpus did not contain entries");
let mut input = testcase.input().as_ref().unwrap().clone(); let mut input = testcase.borrow_mut().load_input().unwrap().clone();
rand.set_seed(5); rand.set_seed(5);
let mut mutator = StdScheduledMutator::new(); let mut mutator = StdScheduledMutator::new();

View File

@ -24,6 +24,6 @@ where
state: &mut State<I, R>, state: &mut State<I, R>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<EM, E, C, I, R>, engine: &mut Engine<EM, E, C, I, R>,
input: &I, corpus_idx: usize,
) -> Result<(), AflError>; ) -> Result<(), AflError>;
} }

View File

@ -40,11 +40,11 @@ where
state: &mut State<I, R>, state: &mut State<I, R>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<EM, E, C, I, R>, engine: &mut Engine<EM, E, C, I, R>,
input: &I, corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
let num = self.iterations(rand); let num = self.iterations(rand);
for i in 0..num { for i in 0..num {
let mut input_mut = input.clone(); let mut input_mut = corpus.get(corpus_idx).borrow_mut().load_input()?.clone();
self.mutator_mut() self.mutator_mut()
.mutate(rand, corpus, &mut input_mut, i as i32)?; .mutate(rand, corpus, &mut input_mut, i as i32)?;
@ -120,9 +120,9 @@ where
state: &mut State<I, R>, state: &mut State<I, R>,
corpus: &mut C, corpus: &mut C,
engine: &mut Engine<EM, E, C, I, R>, engine: &mut Engine<EM, E, C, I, R>,
input: &I, corpus_idx: usize,
) -> Result<(), AflError> { ) -> Result<(), AflError> {
self.perform_mutational(rand, state, corpus, engine, input) self.perform_mutational(rand, state, corpus, engine, corpus_idx)
} }
} }