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

View File

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

View File

@ -293,19 +293,10 @@ where
corpus: &mut C,
engine: &mut Engine<EM, E, C, I, R>,
) -> Result<usize, AflError> {
let (testcase, idx) = corpus.next(rand)?;
match testcase.input() {
None => {
// Load from disk.
corpus.load_testcase(idx)?;
}
_ => (),
};
let input = corpus.get(idx).input().as_ref().unwrap();
let (_, idx) = corpus.next(rand)?;
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)?;

View File

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

View File

@ -686,13 +686,13 @@ where
R: Rand,
{
// We don't want to use the testcase we're already using for splicing
let (other_testcase, _) = corpus.random_entry(rand)?.clone();
// TODO: Load let other = Testcase::load_from_disk(other_test)?;
let (other_testcase, idx) = corpus.random_entry(rand)?;
if idx == corpus.current_testcase().1 {
return Ok(MutationResult::Skipped);
}
// println!("Input: {:?}, other input: {:?}", input.bytes(), other.bytes());
let other = match other_testcase.input() {
Some(i) => i,
None => return Ok(MutationResult::Skipped), //TODO
};
let mut other_ref = other_testcase.borrow_mut();
let other = other_ref.load_input()?;
let mut counter = 0;
let (first_diff, last_diff) = loop {

View File

@ -265,7 +265,7 @@ mod tests {
let (testcase, _) = corpus
.next(&mut rand)
.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);
let mut mutator = StdScheduledMutator::new();

View File

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

View File

@ -40,11 +40,11 @@ where
state: &mut State<I, R>,
corpus: &mut C,
engine: &mut Engine<EM, E, C, I, R>,
input: &I,
corpus_idx: usize,
) -> Result<(), AflError> {
let num = self.iterations(rand);
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()
.mutate(rand, corpus, &mut input_mut, i as i32)?;
@ -120,9 +120,9 @@ where
state: &mut State<I, R>,
corpus: &mut C,
engine: &mut Engine<EM, E, C, I, R>,
input: &I,
corpus_idx: usize,
) -> Result<(), AflError> {
self.perform_mutational(rand, state, corpus, engine, input)
self.perform_mutational(rand, state, corpus, engine, corpus_idx)
}
}