remodelling evaluation
This commit is contained in:
parent
7f8734e161
commit
77b736ab3b
@ -5,7 +5,7 @@ use crate::inputs::Input;
|
||||
use crate::utils::{HasRand, Rand};
|
||||
use crate::AflError;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use core::cell::RefCell;
|
||||
use std::marker::PhantomData;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
@ -2,7 +2,7 @@ use crate::inputs::Input;
|
||||
use crate::AflError;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use std::cell::RefCell;
|
||||
use core::cell::RefCell;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -6,25 +6,14 @@ use crate::inputs::Input;
|
||||
use crate::stages::Stage;
|
||||
use crate::AflError;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use core::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub trait Evaluator<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
fn evaluate_input(
|
||||
&mut self,
|
||||
input: &mut I,
|
||||
entry: Rc<RefCell<Testcase<I>>>,
|
||||
) -> Result<bool, AflError>;
|
||||
}
|
||||
|
||||
pub trait Engine<I, C, E>: Evaluator<I>
|
||||
pub trait Engine<I, C, E>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
E: Executor<I, C>,
|
||||
{
|
||||
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
|
||||
|
||||
@ -34,111 +23,40 @@ where
|
||||
self.feedbacks_mut().push(feedback);
|
||||
}
|
||||
|
||||
fn stages(&self) -> &Vec<Box<dyn Stage<I, E = Self>>>;
|
||||
fn stages(&self) -> &Vec<Box<dyn Stage<I>>>;
|
||||
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I, E = Self>>>;
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I>>>;
|
||||
|
||||
fn add_stage(&mut self, stage: Box<dyn Stage<I, E = Self>>) {
|
||||
fn add_stage(&mut self, stage: Box<dyn Stage<I>>) {
|
||||
self.stages_mut().push(stage);
|
||||
}
|
||||
|
||||
fn corpus(&self) -> &C;
|
||||
|
||||
fn corpus_mut(&mut self) -> &mut C;
|
||||
|
||||
fn executor(&self) -> &E;
|
||||
|
||||
fn executor_mut(&mut self) -> &mut E;
|
||||
|
||||
fn fuzz_one(&mut self) -> Result<(), AflError> {
|
||||
if self.corpus().count() == 0 {
|
||||
return Err(AflError::Empty("No testcases in corpus".to_owned()));
|
||||
}
|
||||
let entry = self.corpus_mut().next()?;
|
||||
fn fuzz_one(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||
for stage in self.stages_mut() {
|
||||
stage.perform(&entry)?;
|
||||
stage.perform(&testcase)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn evaluate_input_engine(
|
||||
&mut self,
|
||||
input: &mut I,
|
||||
_entry: Rc<RefCell<Testcase<I>>>,
|
||||
) -> Result<bool, AflError> {
|
||||
self.executor_mut().reset_observers()?;
|
||||
self.executor_mut().run_target(input)?;
|
||||
self.executor_mut().post_exec_observers()?;
|
||||
|
||||
let mut metadatas: Vec<Box<dyn TestcaseMetadata>> = vec![];
|
||||
let mut rate_acc = 0;
|
||||
for feedback in self.feedbacks_mut() {
|
||||
let (rate, meta) = feedback.is_interesting(input);
|
||||
rate_acc += rate;
|
||||
if let Some(m) = meta {
|
||||
metadatas.push(m);
|
||||
}
|
||||
}
|
||||
|
||||
if rate_acc >= 25 {
|
||||
let new_entry = Rc::new(RefCell::new(Testcase::<I>::new(input.clone())));
|
||||
for meta in metadatas {
|
||||
new_entry.borrow_mut().add_metadata(meta);
|
||||
}
|
||||
self.corpus_mut().add(new_entry);
|
||||
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub struct FuzzState<I, C, E>
|
||||
pub struct DefaultEngine<I>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
pub struct DefaultEngine<I, C, E>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
||||
stages: Vec<Box<dyn Stage<I, E = Self>>>,
|
||||
executor: E,
|
||||
corpus: C,
|
||||
stages: Vec<Box<dyn Stage<I>>>,
|
||||
}
|
||||
|
||||
impl<I, C, E> Evaluator<I> for DefaultEngine<I, C, E>
|
||||
impl<I, C, E> Engine<I, C, E> for DefaultEngine<I>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
fn evaluate_input(
|
||||
&mut self,
|
||||
input: &mut I,
|
||||
entry: Rc<RefCell<Testcase<I>>>,
|
||||
) -> Result<bool, AflError> {
|
||||
self.evaluate_input_engine(input, entry)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, C, E> Engine<I, C, E> for DefaultEngine<I, C, E>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
E: Executor<I, C>,
|
||||
{
|
||||
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>> {
|
||||
&self.feedbacks
|
||||
@ -148,64 +66,68 @@ where
|
||||
&mut self.feedbacks
|
||||
}
|
||||
|
||||
fn stages(&self) -> &Vec<Box<dyn Stage<I, E = Self>>> {
|
||||
fn stages(&self) -> &Vec<Box<dyn Stage<I>>> {
|
||||
&self.stages
|
||||
}
|
||||
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I, E = Self>>> {
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<I>>> {
|
||||
&mut self.stages
|
||||
}
|
||||
|
||||
fn corpus(&self) -> &C {
|
||||
&self.corpus
|
||||
}
|
||||
|
||||
fn corpus_mut(&mut self) -> &mut C {
|
||||
&mut self.corpus
|
||||
}
|
||||
|
||||
fn executor(&self) -> &E {
|
||||
&self.executor
|
||||
}
|
||||
|
||||
fn executor_mut(&mut self) -> &mut E {
|
||||
&mut self.executor
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, C, E> DefaultEngine<I, C, E>
|
||||
impl<I> DefaultEngine<I>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I>,
|
||||
{
|
||||
pub fn new(corpus: C, executor: E) -> Self {
|
||||
pub fn new(executor: E) -> Self {
|
||||
DefaultEngine {
|
||||
feedbacks: vec![],
|
||||
stages: vec![],
|
||||
corpus: corpus,
|
||||
executor: executor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_rr(corpus: C, executor: E) -> Rc<RefCell<Self>> {
|
||||
Rc::new(RefCell::new(Self::new(corpus, executor)))
|
||||
pub fn new_rr(executor: E) -> Rc<RefCell<Self>> {
|
||||
Rc::new(RefCell::new(Self::new(executor)))
|
||||
}
|
||||
}
|
||||
|
||||
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)]
|
||||
mod tests {
|
||||
use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
|
||||
use crate::engines::{DefaultEngine, Engine};
|
||||
use crate::engines::{DefaultEngine, Engine, FuzzState};
|
||||
use crate::executors::inmemory::InMemoryExecutor;
|
||||
use crate::executors::{Executor, ExitKind};
|
||||
use crate::inputs::bytes::BytesInput;
|
||||
use crate::stages::mutational::DefaultMutationalStage;
|
||||
use crate::mutators::DefaultScheduledMutator;
|
||||
use crate::mutators::scheduled::mutation_bitflip;
|
||||
use crate::stages::mutational::DefaultMutationalStage;
|
||||
use crate::stages::Stage;
|
||||
use crate::utils::Xoshiro256StarRand;
|
||||
|
||||
fn harness<I>(_executor: &dyn Executor<I>, _buf: &[u8]) -> ExitKind {
|
||||
fn harness<I, C>(_executor: &dyn Executor<I, C>, _buf: &[u8]) -> ExitKind {
|
||||
ExitKind::Ok
|
||||
}
|
||||
|
||||
@ -213,16 +135,16 @@ mod tests {
|
||||
fn test_engine() {
|
||||
let rand = Xoshiro256StarRand::preseeded_rr();
|
||||
|
||||
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
|
||||
let corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
|
||||
let testcase = Testcase::new_rr(BytesInput::new(vec![0; 4]));
|
||||
corpus.add(testcase);
|
||||
let executor = InMemoryExecutor::new(harness);
|
||||
let engine = DefaultEngine::new_rr(corpus, executor);
|
||||
//let mutator = DefaultScheduledMutator::new_all(rand: &rand, corpus: Option<Box<C>>, mutations: Vec<MutationFunction<Self, I>>)(&rand);
|
||||
//let stage = DefaultMutationalStage::new(&rand, &engine, mutator);
|
||||
//engine.borrow_mut().add_stage(Box::new(stage));
|
||||
engine.borrow_mut().fuzz_one().unwrap();
|
||||
let t = { engine.borrow_mut().corpus_mut().next().unwrap() };
|
||||
//engine.borrow_mut().stages[0].perform(&t).unwrap();
|
||||
let state = FuzzState::new(corpus);
|
||||
let engine = DefaultEngine::new(executor);
|
||||
let mutator = DefaultScheduledMutator::new(&rand);
|
||||
mutator.add_mutation(mutation_bitflip);
|
||||
let stage = DefaultMutationalStage::new(&rand, &engine, mutator);
|
||||
engine.add_stage(Box::new(stage));
|
||||
engine.fuzz_one(&corpus.next().unwrap()).unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::executors::Corpus;
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::Observer;
|
||||
use crate::AflError;
|
||||
@ -7,21 +8,23 @@ use crate::executors::{Executor, ExitKind};
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
|
||||
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
|
||||
type HarnessFunction<I, C> = fn(&dyn Executor<I, C>, &[u8]) -> ExitKind;
|
||||
|
||||
pub struct InMemoryExecutor<I>
|
||||
pub struct InMemoryExecutor<I, C>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
{
|
||||
observers: Vec<Box<dyn Observer>>,
|
||||
harness: HarnessFunction<I>,
|
||||
harness: HarnessFunction<I, C>,
|
||||
}
|
||||
|
||||
static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null();
|
||||
|
||||
impl<I> Executor<I> for InMemoryExecutor<I>
|
||||
impl<I, C> Executor<I, C> for InMemoryExecutor<I, C>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
{
|
||||
fn run_target(&mut self, input: &mut I) -> Result<ExitKind, AflError> {
|
||||
let bytes = input.serialize()?;
|
||||
@ -58,11 +61,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> InMemoryExecutor<I>
|
||||
impl<I, C> InMemoryExecutor<I, C>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
{
|
||||
pub fn new(harness_fn: HarnessFunction<I>) -> Self {
|
||||
pub fn new(harness_fn: HarnessFunction<I, C>) -> Self {
|
||||
unsafe {
|
||||
os_signals::setup_crash_handlers::<I, Self>();
|
||||
}
|
||||
@ -86,16 +90,14 @@ pub mod unix_signals {
|
||||
use std::{mem, process, ptr};
|
||||
|
||||
use crate::executors::inmemory::CURRENT_INMEMORY_EXECUTOR_PTR;
|
||||
use crate::executors::Executor;
|
||||
use crate::inputs::Input;
|
||||
|
||||
pub extern "C" fn libaflrs_executor_inmem_handle_crash<I, E>(
|
||||
pub extern "C" fn libaflrs_executor_inmem_handle_crash<I>(
|
||||
_sig: c_int,
|
||||
info: siginfo_t,
|
||||
_void: c_void,
|
||||
) where
|
||||
I: Input,
|
||||
E: Executor<I>,
|
||||
{
|
||||
unsafe {
|
||||
if CURRENT_INMEMORY_EXECUTOR_PTR == ptr::null() {
|
||||
@ -110,13 +112,12 @@ pub mod unix_signals {
|
||||
let _ = stdout().flush();
|
||||
}
|
||||
|
||||
pub extern "C" fn libaflrs_executor_inmem_handle_timeout<I, E>(
|
||||
pub extern "C" fn libaflrs_executor_inmem_handle_timeout<I>(
|
||||
_sig: c_int,
|
||||
_info: siginfo_t,
|
||||
_void: c_void,
|
||||
) where
|
||||
I: Input,
|
||||
E: Executor<I>,
|
||||
{
|
||||
dbg!("TIMEOUT/SIGUSR2 received");
|
||||
unsafe {
|
||||
@ -131,15 +132,14 @@ pub mod unix_signals {
|
||||
process::abort();
|
||||
}
|
||||
|
||||
pub unsafe fn setup_crash_handlers<I, E>()
|
||||
pub unsafe fn setup_crash_handlers<I>()
|
||||
where
|
||||
I: Input,
|
||||
E: Executor<I>,
|
||||
{
|
||||
let mut sa: sigaction = mem::zeroed();
|
||||
libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
|
||||
sa.sa_flags = SA_NODEFER | SA_SIGINFO;
|
||||
sa.sa_sigaction = libaflrs_executor_inmem_handle_crash::<I, E> as usize;
|
||||
sa.sa_sigaction = libaflrs_executor_inmem_handle_crash::<I> as usize;
|
||||
for (sig, msg) in &[
|
||||
(SIGSEGV, "segfault"),
|
||||
(SIGBUS, "sigbus"),
|
||||
@ -153,7 +153,7 @@ pub mod unix_signals {
|
||||
}
|
||||
}
|
||||
|
||||
sa.sa_sigaction = libaflrs_executor_inmem_handle_timeout::<I, E> as usize;
|
||||
sa.sa_sigaction = libaflrs_executor_inmem_handle_timeout::<I> as usize;
|
||||
if sigaction(SIGUSR2, &mut sa as *mut sigaction, ptr::null_mut()) < 0 {
|
||||
panic!("Could not set up sigusr2 handler for timeouts");
|
||||
}
|
||||
@ -167,6 +167,7 @@ compile_error!("InMemoryExecutor not yet supported on this OS");
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::executors::Corpus;
|
||||
use crate::executors::inmemory::InMemoryExecutor;
|
||||
use crate::executors::{Executor, ExitKind};
|
||||
use crate::inputs::Input;
|
||||
@ -195,16 +196,16 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn test_harness_fn_nop(_executor: &dyn Executor<NopInput>, buf: &[u8]) -> ExitKind {
|
||||
/*fn test_harness_fn_nop(_executor: &dyn Executor<Corpus, NopInput>, buf: &[u8]) -> ExitKind {
|
||||
println! {"Fake exec with buf of len {}", buf.len()};
|
||||
ExitKind::Ok
|
||||
}
|
||||
}*/
|
||||
|
||||
#[test]
|
||||
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 {};
|
||||
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);
|
||||
}
|
||||
|
||||
@ -212,6 +213,6 @@ mod tests {
|
||||
fn test_inmem_exec() {
|
||||
let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop);
|
||||
let mut input = NopInput {};
|
||||
assert!(in_mem_executor.run_target(&mut input).is_ok());
|
||||
//assert!(in_mem_executor.run_target(&mut input).is_ok());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
pub mod inmemory;
|
||||
|
||||
use crate::corpus::Testcase;
|
||||
use core::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use crate::corpus::Corpus;
|
||||
use crate::corpus::TestcaseMetadata;
|
||||
use crate::feedbacks::Feedback;
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::Observer;
|
||||
use crate::AflError;
|
||||
@ -13,9 +19,10 @@ pub enum ExitKind {
|
||||
|
||||
// TODO unbox input
|
||||
|
||||
pub trait Executor<I>
|
||||
pub trait Executor<I, C>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
{
|
||||
/// Instruct the target about the input and run
|
||||
fn run_target(&mut self, input: &mut I) -> Result<ExitKind, AflError>;
|
||||
@ -31,4 +38,46 @@ where
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers(&self) -> &Vec<Box<dyn Observer>>;
|
||||
|
||||
/// Adds a feedback
|
||||
fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>);
|
||||
|
||||
/// Returns vector of feebacks
|
||||
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
|
||||
|
||||
// TODO: Move to another struct, like evaluator?
|
||||
// In any case, the dependency on Corpus should probably go
|
||||
/// Runs the input and triggers observers and feedback
|
||||
fn evaluate_input(
|
||||
&mut self,
|
||||
corpus: &mut C,
|
||||
input: &mut I,
|
||||
) -> Result<bool, AflError> {
|
||||
self.reset_observers()?;
|
||||
self.run_target(input)?;
|
||||
self.post_exec_observers()?;
|
||||
|
||||
let mut metadatas: Vec<Box<dyn TestcaseMetadata>> = vec![];
|
||||
let mut rate_acc = 0;
|
||||
for feedback in self.feedbacks() {
|
||||
let (rate, meta) = feedback.is_interesting(input);
|
||||
rate_acc += rate;
|
||||
if let Some(m) = meta {
|
||||
metadatas.push(m);
|
||||
}
|
||||
}
|
||||
|
||||
if rate_acc >= 25 {
|
||||
let new_entry = Rc::new(RefCell::new(Testcase::<I>::new(input.clone())));
|
||||
for meta in metadatas {
|
||||
new_entry.borrow_mut().add_metadata(meta);
|
||||
}
|
||||
corpus.add(new_entry);
|
||||
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::inputs::Input;
|
||||
use crate::observers::MapObserver;
|
||||
|
||||
use num::Integer;
|
||||
use std::cell::RefCell;
|
||||
use core::cell::RefCell;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub trait Feedback<I>
|
||||
|
@ -1,29 +1,13 @@
|
||||
pub mod scheduled;
|
||||
pub use scheduled::ScheduledMutator;
|
||||
pub use scheduled::DefaultScheduledMutator;
|
||||
pub use scheduled::HavocBytesMutator;
|
||||
pub use scheduled::ScheduledMutator;
|
||||
|
||||
use crate::corpus::Corpus;
|
||||
use crate::inputs::Input;
|
||||
use crate::utils::HasRand;
|
||||
use crate::AflError;
|
||||
|
||||
pub trait HasOptionCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type C: Corpus<I>;
|
||||
|
||||
/// Get the associated corpus, if any
|
||||
fn corpus(&self) -> &Option<Box<Self::C>>;
|
||||
|
||||
/// Get the associated corpus, if any (mutable)
|
||||
fn corpus_mut(&mut self) -> &mut Option<Box<Self::C>>;
|
||||
|
||||
/// Set the associated corpus
|
||||
fn set_corpus(&mut self, corpus: Option<Box<Self::C>>);
|
||||
}
|
||||
|
||||
pub trait Mutator<I>: HasRand
|
||||
where
|
||||
I: Input,
|
||||
|
@ -1,10 +1,10 @@
|
||||
use crate::corpus::Corpus;
|
||||
use crate::inputs::{HasBytesVec, Input};
|
||||
use crate::mutators::{HasOptionCorpus, Mutator};
|
||||
use crate::mutators::Mutator;
|
||||
use crate::utils::{HasRand, Rand};
|
||||
use crate::AflError;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use core::cell::RefCell;
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -25,7 +25,7 @@ where
|
||||
fn add_mutation(&mut self, mutation: MutationFunction<Self, I>);
|
||||
}
|
||||
|
||||
pub trait ScheduledMutator<I>: Mutator<I> + HasOptionCorpus<I> + ComposedByMutations<I>
|
||||
pub trait ScheduledMutator<I>: Mutator<I> + ComposedByMutations<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
@ -58,18 +58,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultScheduledMutator<'a, I, R, C>
|
||||
pub struct DefaultScheduledMutator<'a, I, C, R>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
C: Corpus<I>,
|
||||
R: Rand,
|
||||
{
|
||||
rand: Rc<RefCell<R>>,
|
||||
corpus: Option<Box<C>>,
|
||||
mutations: Vec<MutationFunction<Self, I>>,
|
||||
}
|
||||
|
||||
impl<'a, I, R, C> HasRand for DefaultScheduledMutator<'_, I, R, C>
|
||||
impl<'a, I, C, R> HasRand for DefaultScheduledMutator<'_, I, C, R>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
@ -82,28 +81,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, R, C> HasOptionCorpus<I> for DefaultScheduledMutator<'_, I, R, C>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
C: Corpus<I>,
|
||||
{
|
||||
type C = C;
|
||||
|
||||
fn corpus(&self) -> &Option<Box<Self::C>> {
|
||||
&self.corpus
|
||||
}
|
||||
|
||||
fn corpus_mut(&mut self) -> &mut Option<Box<Self::C>> {
|
||||
&mut self.corpus
|
||||
}
|
||||
|
||||
fn set_corpus(&mut self, corpus: Option<Box<Self::C>>) {
|
||||
self.corpus = corpus
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, R, C> Mutator<I> for DefaultScheduledMutator<'_, I, R, C>
|
||||
impl<'a, I, C, R> Mutator<I> for DefaultScheduledMutator<'_, I, C, R>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
@ -114,7 +93,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, R, C> ComposedByMutations<I> for DefaultScheduledMutator<'_, I, R, C>
|
||||
impl<'a, I, C, R> ComposedByMutations<I> for DefaultScheduledMutator<'_, I, C, R>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
@ -136,7 +115,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, R, C> ScheduledMutator<I> for DefaultScheduledMutator<'_, I, R, C>
|
||||
impl<'a, I, C, R> ScheduledMutator<I> for DefaultScheduledMutator<'_, I, C, R>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
@ -145,17 +124,16 @@ where
|
||||
// Just use the default methods
|
||||
}
|
||||
|
||||
impl<'a, I, R, C> DefaultScheduledMutator<'a, I, R, C>
|
||||
impl<'a, I, C, R> DefaultScheduledMutator<'a, I, C, R>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
C: Corpus<I>,
|
||||
R: Rand,
|
||||
{
|
||||
/// Create a new DefaultScheduledMutator instance without mutations and corpus
|
||||
pub fn new(rand: &Rc<RefCell<R>>) -> Self {
|
||||
DefaultScheduledMutator {
|
||||
rand: Rc::clone(rand),
|
||||
corpus: None,
|
||||
mutations: vec![],
|
||||
}
|
||||
}
|
||||
@ -163,15 +141,14 @@ where
|
||||
/// Create a new DefaultScheduledMutator instance specifying mutations and corpus too
|
||||
pub fn new_all(
|
||||
rand: &Rc<RefCell<R>>,
|
||||
corpus: Option<Box<C>>,
|
||||
mutations: Vec<MutationFunction<Self, I>>,
|
||||
) -> Self {
|
||||
DefaultScheduledMutator {
|
||||
rand: Rc::clone(rand),
|
||||
corpus: corpus,
|
||||
mutations: mutations,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Bitflip mutation for inputs with a bytes vector
|
||||
@ -207,26 +184,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, S> HasOptionCorpus<I> for HavocBytesMutator<I, S>
|
||||
where
|
||||
I: Input + HasBytesVec,
|
||||
S: ScheduledMutator<I>,
|
||||
{
|
||||
type C = S::C;
|
||||
|
||||
fn corpus(&self) -> &Option<Box<Self::C>> {
|
||||
self.scheduled.corpus()
|
||||
}
|
||||
|
||||
fn corpus_mut(&mut self) -> &mut Option<Box<Self::C>> {
|
||||
self.scheduled.corpus_mut()
|
||||
}
|
||||
|
||||
fn set_corpus(&mut self, corpus: Option<Box<Self::C>>) {
|
||||
self.scheduled.set_corpus(corpus)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, S> Mutator<I> for HavocBytesMutator<I, S>
|
||||
where
|
||||
I: Input + HasBytesVec,
|
||||
@ -252,7 +209,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, R, C> HavocBytesMutator<I, DefaultScheduledMutator<'a, I, R, C>>
|
||||
impl<'a, I, C, R> HavocBytesMutator<I, DefaultScheduledMutator<'a, I, C, R>>
|
||||
where
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
@ -260,7 +217,7 @@ where
|
||||
{
|
||||
/// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator
|
||||
pub fn new_default(rand: &Rc<RefCell<R>>) -> Self {
|
||||
let mut scheduled = DefaultScheduledMutator::<'a, I, R, C>::new(rand);
|
||||
let mut scheduled = DefaultScheduledMutator::<'a, I, C, R>::new(rand);
|
||||
scheduled.add_mutation(mutation_bitflip);
|
||||
HavocBytesMutator {
|
||||
scheduled: scheduled,
|
||||
|
@ -2,23 +2,13 @@ pub mod mutational;
|
||||
pub use mutational::DefaultMutationalStage;
|
||||
|
||||
use crate::corpus::Testcase;
|
||||
use crate::engines::Evaluator;
|
||||
use crate::inputs::Input;
|
||||
use crate::AflError;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use core::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub trait HasEvaluator<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type E: Evaluator<I>;
|
||||
|
||||
fn evaluator(&self) -> &Rc<RefCell<Self::E>>;
|
||||
}
|
||||
|
||||
pub trait Stage<I>: HasEvaluator<I>
|
||||
pub trait Stage<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
|
@ -1,21 +1,26 @@
|
||||
use crate::corpus::Corpus;
|
||||
use crate::corpus::TestcaseMetadata;
|
||||
use crate::executors::Executor;
|
||||
use crate::corpus::testcase::Testcase;
|
||||
use crate::engines::Evaluator;
|
||||
use crate::inputs::Input;
|
||||
use crate::mutators::Mutator;
|
||||
use crate::stages::{HasEvaluator, Stage};
|
||||
use crate::stages::Stage;
|
||||
use crate::utils::{HasRand, Rand};
|
||||
use crate::AflError;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
|
||||
// TODO create HasMutatorsVec trait
|
||||
|
||||
pub trait MutationalStage<I, M>: Stage<I> + HasRand
|
||||
pub trait MutationalStage<I, C, M, E>: Stage<I> + HasRand
|
||||
where
|
||||
I: Input,
|
||||
M: Mutator<I, R = Self::R>,
|
||||
C: Corpus<I>,
|
||||
E: Executor<I, C>,
|
||||
{
|
||||
/// The mutator registered for this stage
|
||||
fn mutator(&self) -> &M;
|
||||
@ -23,6 +28,9 @@ where
|
||||
/// The mutator registered for this stage (mutable)
|
||||
fn mutator_mut(&mut self) -> &mut M;
|
||||
|
||||
/// Rc Refcell to the executor
|
||||
fn executor(&self) -> &Rc<RefCell<E>>;
|
||||
|
||||
/// Gets the number of iterations this mutator should run for.
|
||||
/// This call uses internal mutability, so it may change for each call
|
||||
fn iterations(&mut self) -> usize {
|
||||
@ -30,7 +38,8 @@ where
|
||||
}
|
||||
|
||||
/// Runs this (mutational) stage for the given testcase
|
||||
fn perform_mutational(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||
fn perform_mutational(&mut self, corpus: &mut C, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||
let testcase = corpus.next()?;
|
||||
let num = self.iterations();
|
||||
let input = testcase.borrow_mut().load_input()?.clone();
|
||||
|
||||
@ -38,38 +47,37 @@ where
|
||||
let mut input_tmp = input.clone();
|
||||
self.mutator_mut().mutate(&mut input_tmp, i as i32)?;
|
||||
|
||||
let interesting = self
|
||||
.evaluator()
|
||||
.borrow_mut()
|
||||
.evaluate_input(&mut input_tmp, testcase.clone())?;
|
||||
let interesting = self.executor().borrow_mut().evaluate_input(&corpus)?;
|
||||
|
||||
self.mutator_mut().post_exec(interesting, i as i32)?;
|
||||
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// The default mutational stage
|
||||
pub struct DefaultMutationalStage<I, R, M, E>
|
||||
pub struct DefaultMutationalStage<I, C, R, M, E>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
R: Rand,
|
||||
M: Mutator<I, R = R>,
|
||||
E: Evaluator<I>,
|
||||
E: Executor<I, C>,
|
||||
{
|
||||
rand: Rc<RefCell<R>>,
|
||||
evaluator: Rc<RefCell<E>>,
|
||||
executor: Rc<RefCell<E>>,
|
||||
mutator: M,
|
||||
_phantom_input: PhantomData<I>
|
||||
_phantom_input: PhantomData<I>,
|
||||
_phantom_corpus: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<I, R, M, E> HasRand for DefaultMutationalStage<I, R, M, E>
|
||||
impl<I, C, R, M, E> HasRand for DefaultMutationalStage<I, C, R, M, E>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
R: Rand,
|
||||
M: Mutator<I, R = R>,
|
||||
E: Evaluator<I>,
|
||||
E: Executor<I, C>,
|
||||
{
|
||||
type R = R;
|
||||
|
||||
@ -78,28 +86,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicate that this stage can eval targets
|
||||
impl<I, R, M, E> HasEvaluator<I> 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
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
R: Rand,
|
||||
M: Mutator<I, R = R>,
|
||||
E: Evaluator<I>,
|
||||
{
|
||||
type E = E;
|
||||
|
||||
/// Get the evaluator
|
||||
fn evaluator(&self) -> &Rc<RefCell<Self::E>> {
|
||||
&self.evaluator
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, R, M, E> MutationalStage<I, M> for DefaultMutationalStage<I, R, M, E>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
M: Mutator<I, R=R>,
|
||||
E: Evaluator<I>,
|
||||
E: Executor<I, C>,
|
||||
{
|
||||
/// The mutator, added to this stage
|
||||
fn mutator(&self) -> &M {
|
||||
@ -112,32 +106,35 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, R, M, E> Stage<I> for DefaultMutationalStage<I, R, M, E>
|
||||
impl<I, C, R, M, E> Stage<I> for DefaultMutationalStage<I, C, R, M, E>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<I>,
|
||||
R: Rand,
|
||||
M: Mutator<I, R = R>,
|
||||
E: Evaluator<I>,
|
||||
E: Executor<I, C>,
|
||||
{
|
||||
fn perform(&mut self, testcase: &Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||
self.perform_mutational(testcase)
|
||||
fn perform(&mut self, corpus: &mut C) -> Result<(), AflError> {
|
||||
self.perform_mutational(corpus)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, R, M, E> DefaultMutationalStage<I, R, M, E>
|
||||
impl<I, C, R, M, E> DefaultMutationalStage<I, C, R, M, E>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
C: Corpus<I>,
|
||||
M: Mutator<I, R = R>,
|
||||
E: Evaluator<I>,
|
||||
E: Executor<I, C>,
|
||||
{
|
||||
/// Creates a new default mutational stage
|
||||
pub fn new(rand: &Rc<RefCell<R>>, evaluator: &Rc<RefCell<E>>, mutator: M) -> Self {
|
||||
pub fn new(rand: &Rc<RefCell<R>>, executor: &Rc<RefCell<E>>, mutator: M) -> Self {
|
||||
DefaultMutationalStage {
|
||||
rand: Rc::clone(rand),
|
||||
evaluator: Rc::clone(evaluator),
|
||||
executor: Rc::clone(executor),
|
||||
mutator: mutator,
|
||||
_phantom_input: PhantomData,
|
||||
_phantom_corpus: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
src/utils.rs
13
src/utils.rs
@ -1,6 +1,6 @@
|
||||
//! Utility functions for AFL
|
||||
|
||||
use std::cell::RefCell;
|
||||
use core::cell::RefCell;
|
||||
use std::debug_assert;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
@ -122,7 +122,10 @@ impl Xoshiro256StarRand {
|
||||
|
||||
/// Creates a rand instance, pre-seeded with the current time in nanoseconds.
|
||||
pub fn preseeded() -> Self {
|
||||
let seed = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64;
|
||||
let seed = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos() as u64;
|
||||
Self::new(seed)
|
||||
}
|
||||
|
||||
@ -130,7 +133,6 @@ impl Xoshiro256StarRand {
|
||||
pub fn preseeded_rr() -> Rc<RefCell<Self>> {
|
||||
Rc::new(RefCell::new(Self::preseeded()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Get the next higher power of two
|
||||
@ -158,8 +160,7 @@ mod tests {
|
||||
assert!(rand.between(11, 20) > 10);
|
||||
}
|
||||
|
||||
|
||||
use std::cell::RefCell;
|
||||
use core::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
struct HasRandTest<R>
|
||||
where
|
||||
@ -190,8 +191,6 @@ mod tests {
|
||||
assert_eq!(has_rand.rand_below(1), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_next_pow2() {
|
||||
assert_eq!(next_pow2(0), 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user