testcases no longer refcelled
This commit is contained in:
parent
f130e50685
commit
e85582c20b
@ -2,10 +2,10 @@ pub mod testcase;
|
|||||||
pub use testcase::{Testcase, TestcaseMetadata};
|
pub use testcase::{Testcase, TestcaseMetadata};
|
||||||
|
|
||||||
use alloc::borrow::ToOwned;
|
use alloc::borrow::ToOwned;
|
||||||
use alloc::rc::Rc;
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::cell::RefCell;
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@ -18,10 +18,10 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// Get the entries vector field
|
/// Get the entries vector field
|
||||||
fn entries(&self) -> &[Rc<RefCell<Testcase<I>>>];
|
fn entries(&self) -> &[Testcase<I>];
|
||||||
|
|
||||||
/// Get the entries vector field (mutable)
|
/// Get the entries vector field (mutable)
|
||||||
fn entries_mut(&mut self) -> &mut Vec<Rc<RefCell<Testcase<I>>>>;
|
fn entries_mut(&mut self) -> &mut Vec<Testcase<I>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Corpus with all current testcases
|
/// Corpus with all current testcases
|
||||||
@ -36,57 +36,74 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add an entry to the corpus
|
/// Add an entry to the corpus
|
||||||
fn add(&mut self, testcase: Rc<RefCell<Testcase<I>>>) {
|
fn add(&mut self, testcase: Testcase<I>) {
|
||||||
self.entries_mut().push(testcase);
|
self.entries_mut().push(testcase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces the testcase at the given idx
|
||||||
|
fn replace(&mut self, idx: usize, testcase: Testcase<I>) -> Result<(), AflError> {
|
||||||
|
if self.entries_mut().len() < idx {
|
||||||
|
return Err(AflError::KeyNotFound(format!(
|
||||||
|
"Index {} out of bounds",
|
||||||
|
idx
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
self.entries_mut()[idx] = testcase;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get by id
|
||||||
|
fn get(&self, idx: usize) -> &Testcase<I> {
|
||||||
|
&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<Rc<RefCell<Testcase<I>>>> {
|
fn remove(&mut self, entry: &Testcase<I>) -> Option<Testcase<I>> {
|
||||||
let mut i: usize = 0;
|
match self.entries().iter().position(|x| ptr::eq(x, entry)) {
|
||||||
let mut found = false;
|
Some(i) => Some(self.entries_mut().remove(i)),
|
||||||
for x in self.entries() {
|
None => None,
|
||||||
i = i + 1;
|
|
||||||
if &*x.borrow() as *const _ == entry as *const _ {
|
|
||||||
// TODO check if correct
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(self.entries_mut().remove(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a random entry
|
/// Gets a random entry
|
||||||
fn random_entry(&self, rand: &mut R) -> Result<(Rc<RefCell<Testcase<I>>>, usize), AflError> {
|
fn random_entry(&self, rand: &mut R) -> Result<(&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 = rand.below(len as u64) as usize;
|
let id = rand.below(len as u64) as usize;
|
||||||
Ok((self.entries()[id].clone(), id))
|
Ok((self.get(id), id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the testcase for the given idx, with loaded input
|
||||||
|
fn load_testcase(&mut self, idx: usize) -> Result<(), AflError> {
|
||||||
|
let testcase = self.get(idx);
|
||||||
|
// Ensure testcase is loaded
|
||||||
|
match testcase.input() {
|
||||||
|
None => {
|
||||||
|
let new_testcase = match testcase.filename() {
|
||||||
|
Some(filename) => Testcase::load_from_disk(filename)?,
|
||||||
|
None => {
|
||||||
|
return Err(AflError::IllegalState(
|
||||||
|
"Neither input, nor filename specified for testcase".into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.replace(idx, new_testcase)?;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: IntoIter
|
// TODO: IntoIter
|
||||||
/// Gets the next entry
|
/// Gets the next entry
|
||||||
fn next(&mut self, rand: &mut R) -> Result<(Rc<RefCell<Testcase<I>>>, usize), AflError> {
|
fn next(&mut self, rand: &mut R) -> Result<(&Testcase<I>, usize), AflError>;
|
||||||
self.random_entry(rand)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HasCorpus<C, I, R>
|
/// Returns the testacase we currently use
|
||||||
where
|
fn current_testcase(&self) -> (&Testcase<I>, usize);
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
|
||||||
R: Rand,
|
|
||||||
{
|
|
||||||
/// Get the corpus field
|
|
||||||
fn corpus(&self) -> &C;
|
|
||||||
|
|
||||||
/// Get thecorpus field (mutable)
|
|
||||||
fn corpus_mut(&mut self) -> &mut C;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InMemoryCorpus<I, R>
|
pub struct InMemoryCorpus<I, R>
|
||||||
@ -94,7 +111,8 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
entries: Vec<Rc<RefCell<Testcase<I>>>>,
|
entries: Vec<Testcase<I>>,
|
||||||
|
pos: usize,
|
||||||
phantom: PhantomData<R>,
|
phantom: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,10 +121,10 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn entries(&self) -> &[Rc<RefCell<Testcase<I>>>] {
|
fn entries(&self) -> &[Testcase<I>] {
|
||||||
&self.entries
|
&self.entries
|
||||||
}
|
}
|
||||||
fn entries_mut(&mut self) -> &mut Vec<Rc<RefCell<Testcase<I>>>> {
|
fn entries_mut(&mut self) -> &mut Vec<Testcase<I>> {
|
||||||
&mut self.entries
|
&mut self.entries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,7 +134,22 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
// Just use the default implementation
|
/// Gets the next entry
|
||||||
|
fn next(&mut self, rand: &mut R) -> Result<(&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 = rand.below(len as u64) as usize;
|
||||||
|
self.pos = id;
|
||||||
|
Ok((self.get(id), id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the testacase we currently use
|
||||||
|
fn current_testcase(&self) -> (&Testcase<I>, usize) {
|
||||||
|
(self.get(self.pos), self.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, R> InMemoryCorpus<I, R>
|
impl<I, R> InMemoryCorpus<I, R>
|
||||||
@ -127,6 +160,7 @@ where
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
InMemoryCorpus {
|
InMemoryCorpus {
|
||||||
entries: vec![],
|
entries: vec![],
|
||||||
|
pos: 0,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,8 +172,9 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
entries: Vec<Rc<RefCell<Testcase<I>>>>,
|
entries: Vec<Testcase<I>>,
|
||||||
dir_path: PathBuf,
|
dir_path: PathBuf,
|
||||||
|
pos: usize,
|
||||||
phantom: PhantomData<R>,
|
phantom: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,10 +184,10 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn entries(&self) -> &[Rc<RefCell<Testcase<I>>>] {
|
fn entries(&self) -> &[Testcase<I>] {
|
||||||
&self.entries
|
&self.entries
|
||||||
}
|
}
|
||||||
fn entries_mut(&mut self) -> &mut Vec<Rc<RefCell<Testcase<I>>>> {
|
fn entries_mut(&mut self) -> &mut Vec<Testcase<I>> {
|
||||||
&mut self.entries
|
&mut self.entries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,16 +199,35 @@ where
|
|||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
/// Add an entry and save it to disk
|
/// Add an entry and save it to disk
|
||||||
fn add(&mut self, entry: Rc<RefCell<Testcase<I>>>) {
|
fn add(&mut self, mut entry: Testcase<I>) {
|
||||||
if *entry.borrow().filename() == None {
|
match entry.filename() {
|
||||||
|
None => {
|
||||||
// TODO walk entry metadatas to ask for pices of filename (e.g. :havoc in AFL)
|
// TODO walk entry metadatas to ask for pices of filename (e.g. :havoc in AFL)
|
||||||
let filename = self.dir_path.join(format!("id_{}", &self.entries.len()));
|
let filename = self.dir_path.join(format!("id_{}", &self.entries.len()));
|
||||||
let filename_str = filename.to_str().expect("Invalid Path");
|
let filename_str = filename.to_str().expect("Invalid Path");
|
||||||
*entry.borrow_mut().filename_mut() = Some(filename_str.into());
|
entry.set_filename(filename_str.into());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
self.entries.push(entry);
|
self.entries.push(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn current_testcase(&self) -> (&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> {
|
||||||
|
if self.count() == 0 {
|
||||||
|
Err(AflError::Empty("No entries in corpus".to_owned()))
|
||||||
|
} else {
|
||||||
|
let len = { self.entries().len() };
|
||||||
|
let id = rand.below(len as u64) as usize;
|
||||||
|
self.pos = id;
|
||||||
|
Ok((self.get(id), id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO save and remove files, cache, etc..., ATM use just InMemoryCorpus
|
// TODO save and remove files, cache, etc..., ATM use just InMemoryCorpus
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,6 +241,7 @@ where
|
|||||||
OnDiskCorpus {
|
OnDiskCorpus {
|
||||||
dir_path: dir_path,
|
dir_path: dir_path,
|
||||||
entries: vec![],
|
entries: vec![],
|
||||||
|
pos: 0,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,10 +266,10 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
fn entries(&self) -> &[Rc<RefCell<Testcase<I>>>] {
|
fn entries(&self) -> &[Testcase<I>] {
|
||||||
self.corpus.entries()
|
self.corpus.entries()
|
||||||
}
|
}
|
||||||
fn entries_mut(&mut self) -> &mut Vec<Rc<RefCell<Testcase<I>>>> {
|
fn entries_mut(&mut self) -> &mut Vec<Testcase<I>> {
|
||||||
self.corpus.entries_mut()
|
self.corpus.entries_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,22 +285,27 @@ where
|
|||||||
self.corpus.count()
|
self.corpus.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&mut self, entry: Rc<RefCell<Testcase<I>>>) {
|
fn add(&mut self, entry: Testcase<I>) {
|
||||||
self.corpus.add(entry);
|
self.corpus.add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<Rc<RefCell<Testcase<I>>>> {
|
fn remove(&mut self, entry: &Testcase<I>) -> Option<Testcase<I>> {
|
||||||
self.corpus.remove(entry)
|
self.corpus.remove(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a random entry
|
/// Gets a random entry
|
||||||
fn random_entry(&self, rand: &mut R) -> Result<(Rc<RefCell<Testcase<I>>>, usize), AflError> {
|
fn random_entry(&self, rand: &mut R) -> Result<(&Testcase<I>, usize), AflError> {
|
||||||
self.corpus.random_entry(rand)
|
self.corpus.random_entry(rand)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the testacase we currently use
|
||||||
|
fn current_testcase(&self) -> (&Testcase<I>, usize) {
|
||||||
|
(self.get(self.pos - 1), self.pos - 1)
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the next entry
|
/// Gets the next entry
|
||||||
fn next(&mut self, _rand: &mut R) -> Result<(Rc<RefCell<Testcase<I>>>, usize), AflError> {
|
fn next(&mut self, _rand: &mut R) -> Result<(&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()));
|
||||||
@ -255,7 +315,7 @@ where
|
|||||||
self.pos = 1;
|
self.pos = 1;
|
||||||
self.cycles += 1;
|
self.cycles += 1;
|
||||||
}
|
}
|
||||||
Ok((self.corpus.entries()[self.pos - 1].clone(), self.pos - 1))
|
Ok((&self.corpus.entries()[self.pos - 1], self.pos - 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +401,6 @@ mod tests {
|
|||||||
use crate::inputs::bytes::BytesInput;
|
use crate::inputs::bytes::BytesInput;
|
||||||
use crate::utils::StdRand;
|
use crate::utils::StdRand;
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -350,14 +409,12 @@ mod tests {
|
|||||||
let mut q = QueueCorpus::new(OnDiskCorpus::<BytesInput, StdRand>::new(PathBuf::from(
|
let mut q = QueueCorpus::new(OnDiskCorpus::<BytesInput, StdRand>::new(PathBuf::from(
|
||||||
"fancy/path",
|
"fancy/path",
|
||||||
)));
|
)));
|
||||||
let t: Rc<_> =
|
let t = Testcase::with_filename(BytesInput::new(vec![0 as u8; 4]), "fancyfile".into());
|
||||||
Testcase::with_filename(BytesInput::new(vec![0 as u8; 4]), "fancyfile".into()).into();
|
|
||||||
q.add(t);
|
q.add(t);
|
||||||
let filename = q
|
let filename = q
|
||||||
.next(&mut rand)
|
.next(&mut rand)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.borrow()
|
|
||||||
.filename()
|
.filename()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -367,7 +424,6 @@ mod tests {
|
|||||||
q.next(&mut rand)
|
q.next(&mut rand)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.borrow()
|
|
||||||
.filename()
|
.filename()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -51,17 +51,10 @@ impl<I> Testcase<I>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// Make sure to return a valid input instance loading it from disk if not in memory
|
/// Returns this testcase with a loaded input
|
||||||
pub fn load_input(&mut self) -> Result<&I, AflError> {
|
pub fn load_from_disk(filename: &str) -> Result<Self, AflError> {
|
||||||
if self.input.is_none() {
|
let input = I::from_file(filename)?;
|
||||||
let input = I::from_file(
|
Ok(Testcase::new(input))
|
||||||
self.filename
|
|
||||||
.as_ref()
|
|
||||||
.ok_or(AflError::EmptyOptional("filename not specified".into()))?,
|
|
||||||
)?;
|
|
||||||
self.input = Some(input);
|
|
||||||
}
|
|
||||||
Ok(self.input.as_ref().unwrap())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the input, if any
|
/// Get the input, if any
|
||||||
|
@ -8,7 +8,7 @@ use core::fmt::Debug;
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
use crate::corpus::{Corpus, HasCorpus, Testcase};
|
use crate::corpus::{Corpus, Testcase};
|
||||||
use crate::events::{EventManager, LoadInitialEvent, UpdateStatsEvent};
|
use crate::events::{EventManager, LoadInitialEvent, UpdateStatsEvent};
|
||||||
use crate::executors::Executor;
|
use crate::executors::Executor;
|
||||||
use crate::feedbacks::Feedback;
|
use crate::feedbacks::Feedback;
|
||||||
@ -26,7 +26,7 @@ pub trait StateMetadata: Debug {
|
|||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait State<C, E, I, R>: HasCorpus<C, I, R>
|
pub trait State<C, E, I, R>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
@ -111,10 +111,7 @@ where
|
|||||||
fn executor_mut(&mut self) -> &mut E;
|
fn executor_mut(&mut self) -> &mut E;
|
||||||
|
|
||||||
/// Runs the input and triggers observers and feedback
|
/// Runs the input and triggers observers and feedback
|
||||||
fn evaluate_input(
|
fn evaluate_input(&mut self, input: &I) -> Result<u32, AflError> {
|
||||||
&mut self,
|
|
||||||
input: I,
|
|
||||||
) -> Result<(bool, Option<Rc<RefCell<Testcase<I>>>>), AflError> {
|
|
||||||
self.reset_observers()?;
|
self.reset_observers()?;
|
||||||
self.executor_mut().run_target(&input)?;
|
self.executor_mut().run_target(&input)?;
|
||||||
self.set_executions(self.executions() + 1);
|
self.set_executions(self.executions() + 1);
|
||||||
@ -124,29 +121,37 @@ where
|
|||||||
for feedback in self.feedbacks_mut() {
|
for feedback in self.feedbacks_mut() {
|
||||||
fitness += feedback.is_interesting(&input)?;
|
fitness += feedback.is_interesting(&input)?;
|
||||||
}
|
}
|
||||||
|
Ok(fitness)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resets all current feedbacks
|
||||||
|
fn discard_input(&mut self, input: &I) -> Result<(), AflError> {
|
||||||
|
// TODO: This could probably be automatic in the feedback somehow?
|
||||||
|
for feedback in self.feedbacks_mut() {
|
||||||
|
feedback.discard_metadata(input)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new testcase, appending the metadata from each feedback
|
||||||
|
fn input_to_testcase(&mut self, input: I, fitness: u32) -> Result<Testcase<I>, AflError> {
|
||||||
|
let mut testcase = Testcase::new(input);
|
||||||
|
testcase.set_fitness(fitness);
|
||||||
|
for feedback in self.feedbacks_mut() {
|
||||||
|
feedback.append_metadata(&mut testcase)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(testcase)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds this input to the corpus, if it's intersting
|
||||||
|
fn add_input(&mut self, corpus: &mut C, input: I) -> Result<(), AflError> {
|
||||||
|
let fitness = self.evaluate_input(&input)?;
|
||||||
if fitness > 0 {
|
if fitness > 0 {
|
||||||
let testcase: Rc<RefCell<_>> = Testcase::new(input).into();
|
let testcase = self.input_to_testcase(input, fitness)?;
|
||||||
for feedback in self.feedbacks_mut() {
|
corpus.add(testcase);
|
||||||
feedback.append_metadata(testcase.clone())?;
|
|
||||||
}
|
|
||||||
testcase.borrow_mut().set_fitness(fitness);
|
|
||||||
self.corpus_mut().add(testcase.clone());
|
|
||||||
Ok((true, Some(testcase)))
|
|
||||||
} else {
|
} else {
|
||||||
for feedback in self.feedbacks_mut() {
|
self.discard_input(&input)?;
|
||||||
feedback.discard_metadata()?;
|
|
||||||
}
|
|
||||||
Ok((false, None))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_initial_input(&mut self, input: I) -> Result<(), AflError> {
|
|
||||||
// Inefficent clone, but who cares this is done once at init
|
|
||||||
let (_, testcase) = self.evaluate_input(input.clone())?;
|
|
||||||
if testcase.is_none() {
|
|
||||||
let testcase = Testcase::new(input).into();
|
|
||||||
self.corpus_mut().add(testcase);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -155,6 +160,7 @@ where
|
|||||||
pub fn generate_initial_inputs<S, G, C, E, I, R, EM>(
|
pub fn generate_initial_inputs<S, G, C, E, I, R, EM>(
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
corpus: &mut C,
|
||||||
generator: &mut G,
|
generator: &mut G,
|
||||||
events: &mut EM,
|
events: &mut EM,
|
||||||
num: usize,
|
num: usize,
|
||||||
@ -170,7 +176,7 @@ where
|
|||||||
{
|
{
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let input = generator.generate(rand)?;
|
let input = generator.generate(rand)?;
|
||||||
state.load_initial_input(input)?;
|
state.add_input(corpus, input)?;
|
||||||
fire_event!(events, LoadInitialEvent)?;
|
fire_event!(events, LoadInitialEvent)?;
|
||||||
}
|
}
|
||||||
events.process(state)?;
|
events.process(state)?;
|
||||||
@ -190,26 +196,8 @@ where
|
|||||||
// additional_corpuses: HashMap<&'static str, Box<dyn Corpus>>,
|
// additional_corpuses: HashMap<&'static str, Box<dyn Corpus>>,
|
||||||
observers: Vec<Rc<RefCell<dyn Observer>>>,
|
observers: Vec<Rc<RefCell<dyn Observer>>>,
|
||||||
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
||||||
corpus: C,
|
|
||||||
executor: E,
|
executor: E,
|
||||||
phantom: PhantomData<R>,
|
phantom: PhantomData<(C, R)>,
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, E, I, R> HasCorpus<C, I, R> for StdState<C, E, I, R>
|
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
E: Executor<I>,
|
|
||||||
I: Input,
|
|
||||||
R: Rand,
|
|
||||||
{
|
|
||||||
fn corpus(&self) -> &C {
|
|
||||||
&self.corpus
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get thecorpus field (mutable)
|
|
||||||
fn corpus_mut(&mut self) -> &mut C {
|
|
||||||
&mut self.corpus
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, E, I, R> State<C, E, I, R> for StdState<C, E, I, R>
|
impl<C, E, I, R> State<C, E, I, R> for StdState<C, E, I, R>
|
||||||
@ -274,14 +262,13 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
pub fn new(corpus: C, executor: E) -> Self {
|
pub fn new(executor: E) -> Self {
|
||||||
StdState {
|
StdState {
|
||||||
executions: 0,
|
executions: 0,
|
||||||
start_time: current_milliseconds(),
|
start_time: current_milliseconds(),
|
||||||
metadatas: HashMap::default(),
|
metadatas: HashMap::default(),
|
||||||
observers: vec![],
|
observers: vec![],
|
||||||
feedbacks: vec![],
|
feedbacks: vec![],
|
||||||
corpus: corpus,
|
|
||||||
executor: executor,
|
executor: executor,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
@ -309,20 +296,38 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
corpus: &mut C,
|
||||||
events: &mut EM,
|
events: &mut EM,
|
||||||
) -> Result<usize, AflError> {
|
) -> Result<usize, AflError> {
|
||||||
let (testcase, idx) = state.corpus_mut().next(rand)?;
|
let (testcase, idx) = corpus.next(rand)?;
|
||||||
for stage in self.stages_mut() {
|
match testcase.input() {
|
||||||
stage.perform(rand, state, events, testcase.clone())?;
|
None => {
|
||||||
|
// Load from disk.
|
||||||
|
corpus.load_testcase(idx)?;
|
||||||
}
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
let input = corpus.get(idx).input().as_ref().unwrap();
|
||||||
|
|
||||||
|
for stage in self.stages_mut() {
|
||||||
|
stage.perform(rand, state, corpus, events, &input)?;
|
||||||
|
}
|
||||||
|
|
||||||
events.process(state)?;
|
events.process(state)?;
|
||||||
Ok(idx)
|
Ok(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fuzz_loop(&mut self, rand: &mut R, state: &mut S, events: &mut EM) -> Result<(), AflError> {
|
fn fuzz_loop(
|
||||||
|
&mut self,
|
||||||
|
rand: &mut R,
|
||||||
|
state: &mut S,
|
||||||
|
corpus: &mut C,
|
||||||
|
events: &mut EM,
|
||||||
|
) -> Result<(), AflError> {
|
||||||
let mut last = current_milliseconds();
|
let mut last = current_milliseconds();
|
||||||
loop {
|
loop {
|
||||||
self.fuzz_one(rand, state, events)?;
|
self.fuzz_one(rand, state, corpus, events)?;
|
||||||
let cur = current_milliseconds();
|
let cur = current_milliseconds();
|
||||||
if cur - last > 60 * 100 {
|
if cur - last > 60 * 100 {
|
||||||
last = cur;
|
last = cur;
|
||||||
@ -414,7 +419,7 @@ mod tests {
|
|||||||
corpus.add(testcase);
|
corpus.add(testcase);
|
||||||
|
|
||||||
let executor = InMemoryExecutor::<BytesInput>::new(harness);
|
let executor = InMemoryExecutor::<BytesInput>::new(harness);
|
||||||
let mut state = StdState::new(corpus, executor);
|
let mut state = StdState::new(executor);
|
||||||
|
|
||||||
let mut events_manager = LoggerEventManager::new(stderr());
|
let mut events_manager = LoggerEventManager::new(stderr());
|
||||||
|
|
||||||
@ -428,7 +433,7 @@ mod tests {
|
|||||||
|
|
||||||
for i in 0..1000 {
|
for i in 0..1000 {
|
||||||
engine
|
engine
|
||||||
.fuzz_one(&mut rand, &mut state, &mut events_manager)
|
.fuzz_one(&mut rand, &mut state, &mut corpus, &mut events_manager)
|
||||||
.expect(&format!("Error in iter {}", i));
|
.expect(&format!("Error in iter {}", i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ pub mod shmem_translated;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use crate::events::llmp::LLMP;
|
pub use crate::events::llmp::LLMP;
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
|
||||||
use core::cell::RefCell;
|
|
||||||
//use core::any::TypeId;
|
//use core::any::TypeId;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
@ -87,7 +85,7 @@ pub struct NewTestcaseEvent<I>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
testcase: Rc<RefCell<Testcase<I>>>,
|
testcase: Testcase<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> Event for NewTestcaseEvent<I>
|
impl<I> Event for NewTestcaseEvent<I>
|
||||||
@ -103,11 +101,11 @@ impl<I> NewTestcaseEvent<I>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
pub fn new(testcase: Rc<RefCell<Testcase<I>>>) -> Self {
|
pub fn new(testcase: Testcase<I>) -> Self {
|
||||||
NewTestcaseEvent { testcase: testcase }
|
NewTestcaseEvent { testcase: testcase }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn testcase(&self) -> &Rc<RefCell<Testcase<I>>> {
|
pub fn testcase(&self) -> &Testcase<I> {
|
||||||
&self.testcase
|
&self.testcase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,10 +168,10 @@ where
|
|||||||
for event in &self.events {
|
for event in &self.events {
|
||||||
writeln!(
|
writeln!(
|
||||||
&mut self.writer,
|
&mut self.writer,
|
||||||
"#{}\t[{}] corp: {} exec/s: {}",
|
"#{}\t[{}] exec/s: {}",
|
||||||
state.executions(),
|
state.executions(),
|
||||||
event,
|
event,
|
||||||
state.corpus().entries().len(),
|
//TODO: Count corpus.entries().len(),
|
||||||
state.executions_over_seconds()
|
state.executions_over_seconds()
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,12 @@ where
|
|||||||
fn is_interesting(&mut self, input: &I) -> Result<u32, AflError>;
|
fn is_interesting(&mut self, input: &I) -> Result<u32, AflError>;
|
||||||
|
|
||||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||||
fn append_metadata(&mut self, _testcase: Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
fn append_metadata(&mut self, _testcase: &mut Testcase<I>) -> Result<(), AflError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
||||||
fn discard_metadata(&mut self) -> Result<(), AflError> {
|
fn discard_metadata(&mut self, _input: &I) -> Result<(), AflError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,16 +230,16 @@ where
|
|||||||
Ok(interesting)
|
Ok(interesting)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_metadata(&mut self, testcase: Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
fn append_metadata(&mut self, testcase: &mut Testcase<I>) -> Result<(), AflError> {
|
||||||
let meta = Box::new(MapNoveltiesMetadata::new(core::mem::take(
|
let meta = Box::new(MapNoveltiesMetadata::new(core::mem::take(
|
||||||
&mut self.novelties,
|
&mut self.novelties,
|
||||||
)));
|
)));
|
||||||
testcase.borrow_mut().add_metadata(meta);
|
testcase.add_metadata(meta);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
||||||
fn discard_metadata(&mut self) -> Result<(), AflError> {
|
fn discard_metadata(&mut self, _input: &I) -> Result<(), AflError> {
|
||||||
self.novelties.clear();
|
self.novelties.clear();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,7 @@ pub use scheduled::HavocBytesMutator;
|
|||||||
pub use scheduled::ScheduledMutator;
|
pub use scheduled::ScheduledMutator;
|
||||||
pub use scheduled::StdScheduledMutator;
|
pub use scheduled::StdScheduledMutator;
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
|
||||||
use core::cell::RefCell;
|
|
||||||
|
|
||||||
use crate::corpus::Corpus;
|
use crate::corpus::Corpus;
|
||||||
use crate::corpus::Testcase;
|
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::utils::Rand;
|
use crate::utils::Rand;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
@ -23,7 +19,7 @@ where
|
|||||||
fn mutate(
|
fn mutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
corpus: &mut C,
|
corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
stage_idx: i32,
|
stage_idx: i32,
|
||||||
) -> Result<(), AflError>;
|
) -> Result<(), AflError>;
|
||||||
@ -31,8 +27,8 @@ where
|
|||||||
/// Post-process given the outcome of the execution
|
/// Post-process given the outcome of the execution
|
||||||
fn post_exec(
|
fn post_exec(
|
||||||
&mut self,
|
&mut self,
|
||||||
_is_interesting: bool,
|
_is_interesting: u32,
|
||||||
_new_testcase: Option<Rc<RefCell<Testcase<I>>>>,
|
_input: &I,
|
||||||
_stage_idx: i32,
|
_stage_idx: i32,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -15,7 +15,7 @@ pub enum MutationResult {
|
|||||||
// TODO maybe the mutator arg is not needed
|
// TODO maybe the mutator arg is not needed
|
||||||
/// The generic function type that identifies mutations
|
/// The generic function type that identifies mutations
|
||||||
type MutationFunction<M, C, I, R> =
|
type MutationFunction<M, C, I, R> =
|
||||||
fn(&mut M, &mut R, &mut C, &mut I) -> Result<MutationResult, AflError>;
|
fn(&mut M, &mut R, &C, &mut I) -> Result<MutationResult, AflError>;
|
||||||
|
|
||||||
pub trait ComposedByMutations<C, I, R>
|
pub trait ComposedByMutations<C, I, R>
|
||||||
where
|
where
|
||||||
@ -66,7 +66,7 @@ where
|
|||||||
fn scheduled_mutate(
|
fn scheduled_mutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
corpus: &mut C,
|
corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
_stage_idx: i32,
|
_stage_idx: i32,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
@ -96,7 +96,7 @@ where
|
|||||||
fn mutate(
|
fn mutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
corpus: &mut C,
|
corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
_stage_idx: i32,
|
_stage_idx: i32,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
@ -155,7 +155,7 @@ where
|
|||||||
pub fn mutation_bitflip<M, C, I, R>(
|
pub fn mutation_bitflip<M, C, I, R>(
|
||||||
_mutator: &mut M,
|
_mutator: &mut M,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
_corpus: &mut C,
|
_corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
@ -179,7 +179,7 @@ where
|
|||||||
pub fn mutation_byteflip<M, C, I, R>(
|
pub fn mutation_byteflip<M, C, I, R>(
|
||||||
_mutator: &mut M,
|
_mutator: &mut M,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
_corpus: &mut C,
|
_corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
@ -203,7 +203,7 @@ where
|
|||||||
pub fn mutation_byteinc<M, C, I, R>(
|
pub fn mutation_byteinc<M, C, I, R>(
|
||||||
_mutator: &mut M,
|
_mutator: &mut M,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
_corpus: &mut C,
|
_corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
@ -227,7 +227,7 @@ where
|
|||||||
pub fn mutation_bytedec<M, C, I, R>(
|
pub fn mutation_bytedec<M, C, I, R>(
|
||||||
_mutator: &mut M,
|
_mutator: &mut M,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
_corpus: &mut C,
|
_corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
@ -251,7 +251,7 @@ where
|
|||||||
pub fn mutation_byteneg<M, C, I, R>(
|
pub fn mutation_byteneg<M, C, I, R>(
|
||||||
_mutator: &mut M,
|
_mutator: &mut M,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
_corpus: &mut C,
|
_corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
@ -292,7 +292,7 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
|
|||||||
pub fn mutation_splice<M, C, I, R>(
|
pub fn mutation_splice<M, C, I, R>(
|
||||||
_mutator: &mut M,
|
_mutator: &mut M,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
corpus: &mut C,
|
corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
@ -301,17 +301,15 @@ where
|
|||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
// We don't want to use the testcase we're already using for splicing
|
// TODO: Don't reuse the current testcase!
|
||||||
let (other_rr, _) = corpus.random_entry(rand)?.clone();
|
// (We don't want to use the testcase we're already using for splicing)
|
||||||
let mut other_testcase = match other_rr.try_borrow_mut() {
|
let (other_testcase, _) = corpus.random_entry(rand)?;
|
||||||
Ok(x) => x,
|
// TODO: let other = other_testcase.load_input()?;
|
||||||
Err(_) => {
|
|
||||||
return Ok(MutationResult::Skipped);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let other = other_testcase.load_input()?;
|
|
||||||
// println!("Input: {:?}, other input: {:?}", input.bytes(), other.bytes());
|
// 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 counter = 0;
|
let mut counter = 0;
|
||||||
let (first_diff, last_diff) = loop {
|
let (first_diff, last_diff) = loop {
|
||||||
@ -362,7 +360,7 @@ where
|
|||||||
fn mutate(
|
fn mutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
corpus: &mut C,
|
corpus: &C,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
stage_idx: i32,
|
stage_idx: i32,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
@ -380,7 +378,7 @@ where
|
|||||||
/// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap
|
/// Create a new HavocBytesMutator instance given a ScheduledMutator to wrap
|
||||||
pub fn new(mut scheduled: SM) -> Self {
|
pub fn new(mut scheduled: SM) -> Self {
|
||||||
scheduled.add_mutation(mutation_bitflip);
|
scheduled.add_mutation(mutation_bitflip);
|
||||||
//scheduled.add_mutation(mutation_splice);
|
scheduled.add_mutation(mutation_splice);
|
||||||
HavocBytesMutator {
|
HavocBytesMutator {
|
||||||
scheduled: scheduled,
|
scheduled: scheduled,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
@ -432,13 +430,15 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::inputs::BytesInput;
|
use crate::inputs::BytesInput;
|
||||||
use crate::mutators::scheduled::{mutation_splice, StdScheduledMutator};
|
use crate::mutators::scheduled::StdScheduledMutator;
|
||||||
use crate::utils::{Rand, XKCDRand};
|
use crate::utils::{Rand, XKCDRand};
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{Corpus, InMemoryCorpus, Testcase},
|
corpus::{Corpus, InMemoryCorpus, Testcase},
|
||||||
inputs::HasBytesVec,
|
inputs::HasBytesVec,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::mutation_splice;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mut_splice() {
|
fn test_mut_splice() {
|
||||||
// With the current impl, seed of 1 will result in a split at pos 2.
|
// With the current impl, seed of 1 will result in a split at pos 2.
|
||||||
@ -447,11 +447,10 @@ 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
|
let (testcase, _) = corpus
|
||||||
.next(&mut rand)
|
.next(&mut rand)
|
||||||
.expect("Corpus did not contain entries");
|
.expect("Corpus did not contain entries");
|
||||||
let mut testcase = testcase_rr.borrow_mut();
|
let mut input = testcase.input().as_ref().unwrap().clone();
|
||||||
let mut input = testcase.load_input().expect("No input in testcase").clone();
|
|
||||||
|
|
||||||
rand.set_seed(5);
|
rand.set_seed(5);
|
||||||
let mut mutator = StdScheduledMutator::new();
|
let mut mutator = StdScheduledMutator::new();
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
pub mod mutational;
|
pub mod mutational;
|
||||||
pub use mutational::StdMutationalStage;
|
pub use mutational::StdMutationalStage;
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
|
||||||
use core::cell::RefCell;
|
|
||||||
|
|
||||||
use crate::corpus::testcase::Testcase;
|
|
||||||
use crate::corpus::Corpus;
|
use crate::corpus::Corpus;
|
||||||
use crate::engines::State;
|
use crate::engines::State;
|
||||||
use crate::events::EventManager;
|
use crate::events::EventManager;
|
||||||
@ -27,7 +23,8 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
corpus: &C,
|
||||||
events: &mut EM,
|
events: &mut EM,
|
||||||
testcase: Rc<RefCell<Testcase<I>>>,
|
input: &I,
|
||||||
) -> Result<(), AflError>;
|
) -> Result<(), AflError>;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
use alloc::rc::Rc;
|
|
||||||
use core::cell::RefCell;
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::corpus::testcase::Testcase;
|
|
||||||
use crate::engines::State;
|
use crate::engines::State;
|
||||||
use crate::events::{EventManager, NewTestcaseEvent};
|
use crate::events::EventManager;
|
||||||
use crate::executors::Executor;
|
use crate::executors::Executor;
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::mutators::Mutator;
|
use crate::mutators::Mutator;
|
||||||
use crate::stages::Corpus;
|
use crate::stages::Corpus;
|
||||||
use crate::stages::Stage;
|
use crate::stages::Stage;
|
||||||
use crate::utils::Rand;
|
use crate::utils::Rand;
|
||||||
use crate::{fire_event, AflError};
|
use crate::AflError;
|
||||||
|
use crate::{events::NewTestcaseEvent, fire_event};
|
||||||
|
|
||||||
// TODO multi mutators stage
|
// TODO multi mutators stage
|
||||||
|
|
||||||
@ -42,22 +40,27 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
corpus: &C,
|
||||||
events: &mut EM,
|
events: &mut EM,
|
||||||
testcase: Rc<RefCell<Testcase<I>>>,
|
input: &I,
|
||||||
) -> 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 = testcase.borrow_mut().load_input()?.clone();
|
let mut input_mut = input.clone();
|
||||||
self.mutator_mut()
|
self.mutator_mut()
|
||||||
.mutate(rand, state.corpus_mut(), &mut input, i as i32)?;
|
.mutate(rand, corpus, &mut input_mut, i as i32)?;
|
||||||
|
|
||||||
let (interesting, new_testcase) = state.evaluate_input(input)?;
|
let interesting = state.evaluate_input(&input_mut)?;
|
||||||
|
|
||||||
self.mutator_mut()
|
self.mutator_mut()
|
||||||
.post_exec(interesting, new_testcase.clone(), i as i32)?;
|
.post_exec(interesting, &input_mut, i as i32)?;
|
||||||
|
|
||||||
if !new_testcase.is_none() {
|
if interesting > 0 {
|
||||||
fire_event!(events, NewTestcaseEvent<I>, new_testcase.unwrap())?;
|
let new_testcase = state.input_to_testcase(input_mut, interesting)?;
|
||||||
|
fire_event!(events, NewTestcaseEvent<I>, new_testcase)?;
|
||||||
|
//state.corpus_mut().add(new_testcase); // TODO: Probably no longer needed, once events work
|
||||||
|
} else {
|
||||||
|
state.discard_input(&input_mut)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -115,10 +118,11 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
corpus: &C,
|
||||||
events: &mut EM,
|
events: &mut EM,
|
||||||
testcase: Rc<RefCell<Testcase<I>>>,
|
input: &I,
|
||||||
) -> Result<(), AflError> {
|
) -> Result<(), AflError> {
|
||||||
self.perform_mutational(rand, state, events, testcase)
|
self.perform_mutational(rand, state, corpus, events, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user