fixed build

This commit is contained in:
Dominik Maier 2020-11-11 02:46:54 +01:00
parent 77b736ab3b
commit a24d1edd80
15 changed files with 130 additions and 158 deletions

View File

@ -1,3 +1,4 @@
extern crate alloc;
pub mod testcase; pub mod testcase;
pub use testcase::{Testcase, TestcaseMetadata}; pub use testcase::{Testcase, TestcaseMetadata};
@ -5,10 +6,10 @@ use crate::inputs::Input;
use crate::utils::{HasRand, Rand}; use crate::utils::{HasRand, Rand};
use crate::AflError; use crate::AflError;
use alloc::rc::Rc;
use core::cell::RefCell; use core::cell::RefCell;
use std::marker::PhantomData; use core::marker::PhantomData;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc;
pub trait HasEntriesVec<I> pub trait HasEntriesVec<I>
where where

View File

@ -1,10 +1,11 @@
extern crate alloc;
use crate::inputs::Input; use crate::inputs::Input;
use crate::AflError; use crate::AflError;
use hashbrown::HashMap; use alloc::rc::Rc;
use core::cell::RefCell; use core::cell::RefCell;
use hashbrown::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc;
// TODO: Give example // TODO: Give example
/// Metadata for a testcase /// Metadata for a testcase

View File

@ -1,19 +1,16 @@
use crate::corpus::testcase::{Testcase, TestcaseMetadata}; extern crate alloc;
use crate::corpus::Corpus; use crate::corpus::testcase::Testcase;
use crate::executors::Executor;
use crate::feedbacks::Feedback; use crate::feedbacks::Feedback;
use crate::inputs::Input; use crate::inputs::Input;
use crate::stages::Stage; use crate::stages::Stage;
use crate::AflError; use crate::AflError;
use alloc::rc::Rc;
use core::cell::RefCell; use core::cell::RefCell;
use std::rc::Rc;
pub trait Engine<I, C, E> pub trait Engine<I>
where where
I: Input, I: Input,
C: Corpus<I>,
E: Executor<I, C>,
{ {
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>; fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
@ -31,17 +28,12 @@ where
self.stages_mut().push(stage); self.stages_mut().push(stage);
} }
fn executor(&self) -> &E;
fn executor_mut(&mut self) -> &mut E;
fn fuzz_one(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> { fn fuzz_one(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
for stage in self.stages_mut() { for stage in self.stages_mut() {
stage.perform(&testcase)?; stage.perform(&testcase)?;
} }
Ok(()) Ok(())
} }
} }
pub struct DefaultEngine<I> pub struct DefaultEngine<I>
@ -52,11 +44,9 @@ where
stages: Vec<Box<dyn Stage<I>>>, stages: Vec<Box<dyn Stage<I>>>,
} }
impl<I, C, E> Engine<I, C, E> for DefaultEngine<I> impl<I> Engine<I> for DefaultEngine<I>
where where
I: Input, I: Input,
C: Corpus<I>,
E: Executor<I, C>,
{ {
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>> { fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>> {
&self.feedbacks &self.feedbacks
@ -73,61 +63,39 @@ where
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I>>> { fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I>>> {
&mut self.stages &mut self.stages
} }
} }
impl<I> DefaultEngine<I> impl<I> DefaultEngine<I>
where where
I: Input, I: Input,
{ {
pub fn new(executor: E) -> Self { pub fn new() -> Self {
DefaultEngine { DefaultEngine {
feedbacks: vec![], feedbacks: vec![],
stages: vec![], stages: vec![],
} }
} }
pub fn new_rr(executor: E) -> Rc<RefCell<Self>> { pub fn new_rr() -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self::new(executor))) Rc::new(RefCell::new(Self::new()))
} }
} }
pub struct FuzzState<I, C>
where
I: Input,
C: Corpus<I>,
{
corpus: C,
current_input: Option<I>,
}
impl<I, C> FuzzState<I, C>
where
I: Input,
C: Corpus<I>,
{
pub fn new(corpus: C) -> Self {
Self{corpus: corpus, current_input: None}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::corpus::{Corpus, InMemoryCorpus, Testcase}; use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
use crate::engines::{DefaultEngine, Engine, FuzzState}; use crate::engines::{DefaultEngine, Engine};
use crate::executors::inmemory::InMemoryExecutor; use crate::executors::inmemory::InMemoryExecutor;
use crate::executors::{Executor, ExitKind}; use crate::executors::{Executor, ExitKind};
use crate::inputs::bytes::BytesInput; use crate::inputs::bytes::BytesInput;
use crate::mutators::DefaultScheduledMutator; use crate::mutators::scheduled::{
use crate::mutators::scheduled::mutation_bitflip; mutation_bitflip, ComposedByMutations, DefaultScheduledMutator,
};
use crate::stages::mutational::DefaultMutationalStage; use crate::stages::mutational::DefaultMutationalStage;
use crate::stages::Stage;
use crate::utils::Xoshiro256StarRand; use crate::utils::Xoshiro256StarRand;
fn harness<I, C>(_executor: &dyn Executor<I, C>, _buf: &[u8]) -> ExitKind { fn harness<I>(_executor: &dyn Executor<I>, _buf: &[u8]) -> ExitKind {
ExitKind::Ok ExitKind::Ok
} }
@ -135,15 +103,14 @@ mod tests {
fn test_engine() { fn test_engine() {
let rand = Xoshiro256StarRand::preseeded_rr(); let rand = Xoshiro256StarRand::preseeded_rr();
let corpus = InMemoryCorpus::<BytesInput, _>::new(&rand); let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
let testcase = Testcase::new_rr(BytesInput::new(vec![0; 4])); let testcase = Testcase::new_rr(BytesInput::new(vec![0; 4]));
corpus.add(testcase); corpus.add(testcase);
let executor = InMemoryExecutor::new(harness); let executor = InMemoryExecutor::new_rr(harness);
let state = FuzzState::new(corpus); let mut engine = DefaultEngine::new();
let engine = DefaultEngine::new(executor); let mut mutator = DefaultScheduledMutator::new(&rand);
let mutator = DefaultScheduledMutator::new(&rand);
mutator.add_mutation(mutation_bitflip); mutator.add_mutation(mutation_bitflip);
let stage = DefaultMutationalStage::new(&rand, &engine, mutator); let stage = DefaultMutationalStage::new(&rand, &executor, mutator);
engine.add_stage(Box::new(stage)); engine.add_stage(Box::new(stage));
engine.fuzz_one(&corpus.next().unwrap()).unwrap(); engine.fuzz_one(&corpus.next().unwrap()).unwrap();
} }

View File

@ -1,32 +1,34 @@
use crate::executors::Corpus; extern crate alloc;
use crate::feedbacks::Feedback;
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::Observer; use crate::observers::Observer;
use crate::AflError; use crate::AflError;
use alloc::rc::Rc;
use core::cell::RefCell;
use crate::executors::{Executor, ExitKind}; use crate::executors::{Executor, ExitKind};
use std::os::raw::c_void; use std::os::raw::c_void;
use std::ptr; use std::ptr;
type HarnessFunction<I, C> = fn(&dyn Executor<I, C>, &[u8]) -> ExitKind; type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
pub struct InMemoryExecutor<I, C> pub struct InMemoryExecutor<I>
where where
I: Input, I: Input,
C: Corpus<I>,
{ {
observers: Vec<Box<dyn Observer>>, observers: Vec<Box<dyn Observer>>,
harness: HarnessFunction<I, C>, harness: HarnessFunction<I>,
feedbacks: Vec<Box<dyn Feedback<I>>>,
} }
static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null(); static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null();
impl<I, C> Executor<I, C> for InMemoryExecutor<I, C> impl<I> Executor<I> for InMemoryExecutor<I>
where where
I: Input, I: Input,
C: Corpus<I>,
{ {
fn run_target(&mut self, input: &mut I) -> Result<ExitKind, AflError> { fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> {
let bytes = input.serialize()?; let bytes = input.serialize()?;
unsafe { unsafe {
CURRENT_INMEMORY_EXECUTOR_PTR = self as *const InMemoryExecutor<I> as *const c_void; CURRENT_INMEMORY_EXECUTOR_PTR = self as *const InMemoryExecutor<I> as *const c_void;
@ -59,22 +61,38 @@ where
fn observers(&self) -> &Vec<Box<dyn Observer>> { fn observers(&self) -> &Vec<Box<dyn Observer>> {
&self.observers &self.observers
} }
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>> {
&self.feedbacks
}
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>> {
&mut self.feedbacks
}
fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>) {
self.feedbacks_mut().push(feedback);
}
} }
impl<I, C> InMemoryExecutor<I, C> impl<I> InMemoryExecutor<I>
where where
I: Input, I: Input,
C: Corpus<I>,
{ {
pub fn new(harness_fn: HarnessFunction<I, C>) -> Self { pub fn new(harness_fn: HarnessFunction<I>) -> Self {
unsafe { unsafe {
os_signals::setup_crash_handlers::<I, Self>(); os_signals::setup_crash_handlers::<I>();
} }
InMemoryExecutor { InMemoryExecutor {
observers: vec![], observers: vec![],
feedbacks: vec![],
harness: harness_fn, harness: harness_fn,
} }
} }
pub fn new_rr(harness_fn: HarnessFunction<I>) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self::new(harness_fn)))
}
} }
#[cfg(unix)] #[cfg(unix)]
@ -167,8 +185,7 @@ compile_error!("InMemoryExecutor not yet supported on this OS");
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::executors::Corpus; use crate::executors::inmemory::InMemoryExecutor;
use crate::executors::inmemory::InMemoryExecutor;
use crate::executors::{Executor, ExitKind}; use crate::executors::{Executor, ExitKind};
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::Observer; use crate::observers::Observer;
@ -196,16 +213,16 @@ use crate::executors::inmemory::InMemoryExecutor;
} }
} }
/*fn test_harness_fn_nop(_executor: &dyn Executor<Corpus, NopInput>, buf: &[u8]) -> ExitKind { fn test_harness_fn_nop(_executor: &dyn Executor<NopInput>, buf: &[u8]) -> ExitKind {
println! {"Fake exec with buf of len {}", buf.len()}; println! {"Fake exec with buf of len {}", buf.len()};
ExitKind::Ok ExitKind::Ok
}*/ }
#[test] #[test]
fn test_inmem_post_exec() { fn test_inmem_post_exec() {
//let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop); let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop);
let nopserver = Nopserver {}; let nopserver = Nopserver {};
//in_mem_executor.add_observer(Box::new(nopserver)); in_mem_executor.add_observer(Box::new(nopserver));
assert_eq!(in_mem_executor.post_exec_observers().is_err(), true); assert_eq!(in_mem_executor.post_exec_observers().is_err(), true);
} }
@ -213,6 +230,6 @@ use crate::executors::inmemory::InMemoryExecutor;
fn test_inmem_exec() { fn test_inmem_exec() {
let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop); let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop);
let mut input = NopInput {}; let mut input = NopInput {};
//assert!(in_mem_executor.run_target(&mut input).is_ok()); assert!(in_mem_executor.run_target(&mut input).is_ok());
} }
} }

View File

@ -1,14 +1,14 @@
extern crate alloc;
pub mod inmemory; pub mod inmemory;
use crate::corpus::Testcase; use crate::corpus::Testcase;
use core::cell::RefCell;
use std::rc::Rc;
use crate::corpus::Corpus;
use crate::corpus::TestcaseMetadata; use crate::corpus::TestcaseMetadata;
use crate::feedbacks::Feedback; use crate::feedbacks::Feedback;
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::Observer; use crate::observers::Observer;
use crate::AflError; use crate::AflError;
use alloc::rc::Rc;
use core::cell::RefCell;
pub enum ExitKind { pub enum ExitKind {
Ok, Ok,
@ -19,13 +19,12 @@ pub enum ExitKind {
// TODO unbox input // TODO unbox input
pub trait Executor<I, C> pub trait Executor<I>
where where
I: Input, I: Input,
C: Corpus<I>,
{ {
/// Instruct the target about the input and run /// Instruct the target about the input and run
fn run_target(&mut self, input: &mut I) -> Result<ExitKind, AflError>; fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError>;
/// Reset the state of all the observes linked to this executor /// Reset the state of all the observes linked to this executor
fn reset_observers(&mut self) -> Result<(), AflError>; fn reset_observers(&mut self) -> Result<(), AflError>;
@ -45,21 +44,20 @@ where
/// Returns vector of feebacks /// Returns vector of feebacks
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>; fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
/// Returns vector of feebacks (mutable)
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>;
// TODO: Move to another struct, like evaluator? // TODO: Move to another struct, like evaluator?
// In any case, the dependency on Corpus should probably go // In any case, the dependency on Corpus should probably go
/// 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<bool, AflError> {
&mut self,
corpus: &mut C,
input: &mut I,
) -> Result<bool, AflError> {
self.reset_observers()?; self.reset_observers()?;
self.run_target(input)?; self.run_target(input)?;
self.post_exec_observers()?; self.post_exec_observers()?;
let mut metadatas: Vec<Box<dyn TestcaseMetadata>> = vec![]; let mut metadatas: Vec<Box<dyn TestcaseMetadata>> = vec![];
let mut rate_acc = 0; let mut rate_acc = 0;
for feedback in self.feedbacks() { for feedback in self.feedbacks_mut() {
let (rate, meta) = feedback.is_interesting(input); let (rate, meta) = feedback.is_interesting(input);
rate_acc += rate; rate_acc += rate;
if let Some(m) = meta { if let Some(m) = meta {
@ -72,12 +70,11 @@ where
for meta in metadatas { for meta in metadatas {
new_entry.borrow_mut().add_metadata(meta); new_entry.borrow_mut().add_metadata(meta);
} }
corpus.add(new_entry); //TODO corpus.add(new_entry);
Ok(true) Ok(true)
} else { } else {
Ok(false) Ok(false)
} }
} }
} }

View File

@ -1,12 +1,13 @@
extern crate alloc;
extern crate num; extern crate num;
use crate::corpus::TestcaseMetadata; use crate::corpus::TestcaseMetadata;
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::MapObserver; use crate::observers::MapObserver;
use num::Integer;
use core::cell::RefCell; use core::cell::RefCell;
use std::marker::PhantomData; use core::marker::PhantomData;
use num::Integer;
pub trait Feedback<I> pub trait Feedback<I>
where where

View File

@ -1,3 +1,4 @@
extern crate alloc;
use crate::inputs::{HasBytesVec, HasTargetBytes, Input}; use crate::inputs::{HasBytesVec, HasTargetBytes, Input};
use crate::AflError; use crate::AflError;

View File

@ -1,3 +1,4 @@
extern crate alloc;
pub mod bytes; pub mod bytes;
pub use bytes::BytesInput; pub use bytes::BytesInput;

View File

@ -1,3 +1,4 @@
extern crate alloc;
use std::io; use std::io;
use thiserror::Error; use thiserror::Error;

View File

@ -1,9 +1,10 @@
extern crate alloc;
pub mod scheduled; pub mod scheduled;
pub use scheduled::ComposedByMutations;
pub use scheduled::DefaultScheduledMutator; pub use scheduled::DefaultScheduledMutator;
pub use scheduled::HavocBytesMutator; pub use scheduled::HavocBytesMutator;
pub use scheduled::ScheduledMutator; pub use scheduled::ScheduledMutator;
use crate::corpus::Corpus;
use crate::inputs::Input; use crate::inputs::Input;
use crate::utils::HasRand; use crate::utils::HasRand;
use crate::AflError; use crate::AflError;

View File

@ -1,12 +1,12 @@
use crate::corpus::Corpus; extern crate alloc;
use crate::inputs::{HasBytesVec, Input}; use crate::inputs::{HasBytesVec, Input};
use crate::mutators::Mutator; use crate::mutators::Mutator;
use crate::utils::{HasRand, Rand}; use crate::utils::{HasRand, Rand};
use crate::AflError; use crate::AflError;
use alloc::rc::Rc;
use core::cell::RefCell; use core::cell::RefCell;
use std::marker::PhantomData; use core::marker::PhantomData;
use std::rc::Rc;
/// The generic function type that identifies mutations /// The generic function type that identifies mutations
type MutationFunction<M, I> = fn(&mut M, &mut I) -> Result<(), AflError>; type MutationFunction<M, I> = fn(&mut M, &mut I) -> Result<(), AflError>;
@ -58,21 +58,19 @@ where
} }
} }
pub struct DefaultScheduledMutator<'a, I, C, R> pub struct DefaultScheduledMutator<'a, I, R>
where where
I: Input, I: Input,
C: Corpus<I>,
R: Rand, R: Rand,
{ {
rand: Rc<RefCell<R>>, rand: Rc<RefCell<R>>,
mutations: Vec<MutationFunction<Self, I>>, mutations: Vec<MutationFunction<Self, I>>,
} }
impl<'a, I, C, R> HasRand for DefaultScheduledMutator<'_, I, C, R> impl<'a, I, R> HasRand for DefaultScheduledMutator<'_, I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
C: Corpus<I>,
{ {
type R = R; type R = R;
@ -81,23 +79,20 @@ where
} }
} }
impl<'a, I, R> Mutator<I> for DefaultScheduledMutator<'_, I, R>
impl<'a, I, C, R> Mutator<I> for DefaultScheduledMutator<'_, I, C, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
C: Corpus<I>,
{ {
fn mutate(&mut self, input: &mut I, _stage_idx: i32) -> Result<(), AflError> { fn mutate(&mut self, input: &mut I, _stage_idx: i32) -> Result<(), AflError> {
self.scheduled_mutate(input, _stage_idx) self.scheduled_mutate(input, _stage_idx)
} }
} }
impl<'a, I, C, R> ComposedByMutations<I> for DefaultScheduledMutator<'_, I, C, R> impl<'a, I, R> ComposedByMutations<I> for DefaultScheduledMutator<'_, I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
C: Corpus<I>,
{ {
fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<Self, I>, AflError> { fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<Self, I>, AflError> {
if index >= self.mutations.len() { if index >= self.mutations.len() {
@ -115,19 +110,17 @@ where
} }
} }
impl<'a, I, C, R> ScheduledMutator<I> for DefaultScheduledMutator<'_, I, C, R> impl<'a, I, R> ScheduledMutator<I> for DefaultScheduledMutator<'_, I, R>
where where
I: Input, I: Input,
R: Rand, R: Rand,
C: Corpus<I>,
{ {
// Just use the default methods // Just use the default methods
} }
impl<'a, I, C, R> DefaultScheduledMutator<'a, I, C, R> impl<'a, I, R> DefaultScheduledMutator<'a, I, R>
where where
I: Input, I: Input,
C: Corpus<I>,
R: Rand, R: Rand,
{ {
/// Create a new DefaultScheduledMutator instance without mutations and corpus /// Create a new DefaultScheduledMutator instance without mutations and corpus
@ -139,16 +132,12 @@ where
} }
/// Create a new DefaultScheduledMutator instance specifying mutations and corpus too /// Create a new DefaultScheduledMutator instance specifying mutations and corpus too
pub fn new_all( pub fn new_all(rand: &Rc<RefCell<R>>, mutations: Vec<MutationFunction<Self, I>>) -> Self {
rand: &Rc<RefCell<R>>,
mutations: Vec<MutationFunction<Self, I>>,
) -> Self {
DefaultScheduledMutator { DefaultScheduledMutator {
rand: Rc::clone(rand), rand: Rc::clone(rand),
mutations: mutations, mutations: mutations,
} }
} }
} }
/// Bitflip mutation for inputs with a bytes vector /// Bitflip mutation for inputs with a bytes vector
@ -209,15 +198,14 @@ where
} }
} }
impl<'a, I, C, R> HavocBytesMutator<I, DefaultScheduledMutator<'a, I, C, R>> impl<'a, I, R> HavocBytesMutator<I, DefaultScheduledMutator<'a, I, R>>
where where
I: Input + HasBytesVec, I: Input + HasBytesVec,
R: Rand, R: Rand,
C: Corpus<I>,
{ {
/// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator /// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator
pub fn new_default(rand: &Rc<RefCell<R>>) -> Self { pub fn new_default(rand: &Rc<RefCell<R>>) -> Self {
let mut scheduled = DefaultScheduledMutator::<'a, I, C, R>::new(rand); let mut scheduled = DefaultScheduledMutator::<'a, I, R>::new(rand);
scheduled.add_mutation(mutation_bitflip); scheduled.add_mutation(mutation_bitflip);
HavocBytesMutator { HavocBytesMutator {
scheduled: scheduled, scheduled: scheduled,

View File

@ -1,3 +1,4 @@
extern crate alloc;
extern crate num; extern crate num;
use num::Integer; use num::Integer;

View File

@ -1,3 +1,4 @@
extern crate alloc;
pub mod mutational; pub mod mutational;
pub use mutational::DefaultMutationalStage; pub use mutational::DefaultMutationalStage;
@ -5,8 +6,8 @@ use crate::corpus::Testcase;
use crate::inputs::Input; use crate::inputs::Input;
use crate::AflError; use crate::AflError;
use alloc::rc::Rc;
use core::cell::RefCell; use core::cell::RefCell;
use std::rc::Rc;
pub trait Stage<I> pub trait Stage<I>
where where

View File

@ -1,26 +1,23 @@
use crate::corpus::Corpus; extern crate alloc;
use crate::corpus::TestcaseMetadata;
use crate::executors::Executor;
use crate::corpus::testcase::Testcase; use crate::corpus::testcase::Testcase;
use crate::engines::Evaluator; use crate::executors::Executor;
use crate::inputs::Input; use crate::inputs::Input;
use crate::mutators::Mutator; use crate::mutators::Mutator;
use crate::stages::Stage; use crate::stages::Stage;
use crate::utils::{HasRand, Rand}; use crate::utils::{HasRand, Rand};
use crate::AflError; use crate::AflError;
use std::cell::RefCell; use alloc::rc::Rc;
use std::marker::PhantomData; use core::cell::RefCell;
use std::rc::Rc; use core::marker::PhantomData;
// TODO create HasMutatorsVec trait // TODO create HasMutatorsVec trait
pub trait MutationalStage<I, C, M, E>: Stage<I> + HasRand pub trait MutationalStage<I, M, E>: Stage<I> + HasRand
where where
I: Input, I: Input,
M: Mutator<I, R = Self::R>, M: Mutator<I, R = Self::R>,
C: Corpus<I>, E: Executor<I>,
E: Executor<I, C>,
{ {
/// The mutator registered for this stage /// The mutator registered for this stage
fn mutator(&self) -> &M; fn mutator(&self) -> &M;
@ -37,9 +34,9 @@ where
1 + self.rand_below(128) as usize 1 + self.rand_below(128) as usize
} }
// TODO: We need a way to get testcases for splicing
/// Runs this (mutational) stage for the given testcase /// Runs this (mutational) stage for the given testcase
fn perform_mutational(&mut self, corpus: &mut C, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> { fn perform_mutational(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
let testcase = corpus.next()?;
let num = self.iterations(); let num = self.iterations();
let input = testcase.borrow_mut().load_input()?.clone(); let input = testcase.borrow_mut().load_input()?.clone();
@ -47,7 +44,7 @@ where
let mut input_tmp = input.clone(); let mut input_tmp = input.clone();
self.mutator_mut().mutate(&mut input_tmp, i as i32)?; self.mutator_mut().mutate(&mut input_tmp, i as i32)?;
let interesting = self.executor().borrow_mut().evaluate_input(&corpus)?; let interesting = self.executor().borrow_mut().evaluate_input(&input_tmp)?;
self.mutator_mut().post_exec(interesting, i as i32)?; self.mutator_mut().post_exec(interesting, i as i32)?;
} }
@ -56,28 +53,25 @@ where
} }
/// The default mutational stage /// The default mutational stage
pub struct DefaultMutationalStage<I, C, R, M, E> pub struct DefaultMutationalStage<I, R, M, E>
where where
I: Input, I: Input,
C: Corpus<I>,
R: Rand, R: Rand,
M: Mutator<I, R = R>, M: Mutator<I, R = R>,
E: Executor<I, C>, E: Executor<I>,
{ {
rand: Rc<RefCell<R>>, rand: Rc<RefCell<R>>,
executor: Rc<RefCell<E>>, executor: Rc<RefCell<E>>,
mutator: M, mutator: M,
_phantom_input: PhantomData<I>, _phantom_input: PhantomData<I>,
_phantom_corpus: PhantomData<C>,
} }
impl<I, C, R, M, E> HasRand for DefaultMutationalStage<I, C, R, M, E> impl<I, R, M, E> HasRand for DefaultMutationalStage<I, R, M, E>
where where
I: Input, I: Input,
C: Corpus<I>,
R: Rand, R: Rand,
M: Mutator<I, R = R>, M: Mutator<I, R = R>,
E: Executor<I, C>, E: Executor<I>,
{ {
type R = R; type R = R;
@ -86,14 +80,12 @@ where
} }
} }
impl<I, R, M, E> MutationalStage<I, M, E> for DefaultMutationalStage<I, R, M, E>
impl<I, C, R, M, E> MutationalStage<I, C, M, E> for DefaultMutationalStage<I, C, R, M, E>
where where
I: Input, I: Input,
C: Corpus<I>,
R: Rand, R: Rand,
M: Mutator<I, R = R>, M: Mutator<I, R = R>,
E: Executor<I, C>, E: Executor<I>,
{ {
/// The mutator, added to this stage /// The mutator, added to this stage
fn mutator(&self) -> &M { fn mutator(&self) -> &M {
@ -104,28 +96,30 @@ where
fn mutator_mut(&mut self) -> &mut M { fn mutator_mut(&mut self) -> &mut M {
&mut self.mutator &mut self.mutator
} }
}
impl<I, C, R, M, E> Stage<I> for DefaultMutationalStage<I, C, R, M, E> fn executor(&self) -> &Rc<RefCell<E>> {
where &self.executor
I: Input,
C: Corpus<I>,
R: Rand,
M: Mutator<I, R = R>,
E: Executor<I, C>,
{
fn perform(&mut self, corpus: &mut C) -> Result<(), AflError> {
self.perform_mutational(corpus)
} }
} }
impl<I, C, R, M, E> DefaultMutationalStage<I, C, R, M, E> impl<I, R, M, E> Stage<I> for DefaultMutationalStage<I, R, M, E>
where where
I: Input, I: Input,
R: Rand, R: Rand,
C: Corpus<I>,
M: Mutator<I, R = R>, M: Mutator<I, R = R>,
E: Executor<I, C>, E: Executor<I>,
{
fn perform(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
self.perform_mutational(testcase)
}
}
impl<I, R, M, E> DefaultMutationalStage<I, R, M, E>
where
I: Input,
R: Rand,
M: Mutator<I, R = R>,
E: Executor<I>,
{ {
/// Creates a new default mutational stage /// Creates a new default mutational stage
pub fn new(rand: &Rc<RefCell<R>>, executor: &Rc<RefCell<E>>, mutator: M) -> Self { pub fn new(rand: &Rc<RefCell<R>>, executor: &Rc<RefCell<E>>, mutator: M) -> Self {
@ -134,7 +128,6 @@ where
executor: Rc::clone(executor), executor: Rc::clone(executor),
mutator: mutator, mutator: mutator,
_phantom_input: PhantomData, _phantom_input: PhantomData,
_phantom_corpus: PhantomData,
} }
} }
} }

View File

@ -1,9 +1,10 @@
//! Utility functions for AFL //! Utility functions for AFL
extern crate alloc;
use alloc::rc::Rc;
use core::cell::RefCell; use core::cell::RefCell;
use std::debug_assert; use std::debug_assert;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use xxhash_rust::xxh3::xxh3_64_with_seed; use xxhash_rust::xxh3::xxh3_64_with_seed;
@ -160,8 +161,8 @@ mod tests {
assert!(rand.between(11, 20) > 10); assert!(rand.between(11, 20) > 10);
} }
use alloc::rc::Rc;
use core::cell::RefCell; use core::cell::RefCell;
use std::rc::Rc;
struct HasRandTest<R> struct HasRandTest<R>
where where
R: Rand, R: Rand,