broken engine

This commit is contained in:
Andrea Fioraldi 2020-11-05 13:04:42 +01:00
parent 34d51ee5e0
commit 5e51f8f143
8 changed files with 196 additions and 41 deletions

View File

@ -56,14 +56,14 @@ where
}
/// Gets a random entry
fn random_entry(&mut self) -> Result<&Rc<RefCell<Testcase<I>>>, AflError> {
fn random_entry(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
let len = { self.entries().len() };
let id = self.rand_mut().below(len as u64) as usize;
Ok(self.entries_mut().get_mut(id).unwrap())
Ok(self.entries()[id].clone())
}
/// Gets the next entry (random by default)
fn get(&mut self) -> Result<&Rc<RefCell<Testcase<I>>>, AflError> {
fn get(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
self.random_entry()
}
}
@ -257,12 +257,12 @@ where
}
/// Gets a random entry
fn random_entry(&mut self) -> Result<&Rc<RefCell<Testcase<I>>>, AflError> {
fn random_entry(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
self.corpus.random_entry()
}
/// Gets the next entry
fn get(&mut self) -> Result<&Rc<RefCell<Testcase<I>>>, AflError> {
fn get(&mut self) -> Result<Rc<RefCell<Testcase<I>>>, AflError> {
if self.corpus.count() == 0 {
return Err(AflError::Empty("Testcases".to_string()));
}
@ -271,7 +271,7 @@ where
self.cycles = self.cycles + 1;
self.pos = 0;
}
Ok(self.corpus.entries_mut().get_mut(self.pos).unwrap())
Ok(self.corpus.entries()[self.pos].clone())
}
}

View File

@ -82,6 +82,11 @@ where
&mut self.metadatas
}
/// Add a metadata
pub fn add_metadata(&mut self, name: String, meta: Box<dyn TestcaseMetadata>) {
self.metadatas.insert(name, meta);
}
/// Create a new DefaultTestcase instace given an input
pub fn new(input: I) -> Self {
Testcase {

View File

@ -1,6 +1,6 @@
use std::time;
use crate::engines::Engine;
use crate::engines::Evaluator;
use crate::executors::Executor;
use crate::feedbacks::Feedback;
use crate::inputs::Input;

View File

@ -1,16 +1,160 @@
pub mod aflengine;
use crate::corpus::testcase::Testcase;
use crate::corpus::Corpus;
use crate::executors::Executor;
use crate::feedbacks::Feedback;
use crate::inputs::Input;
use crate::stages::Stage;
use crate::AflError;
use std::cell::RefCell;
use std::rc::Rc;
pub trait Engine<'a, I>
pub trait Evaluator<I>
where
I: Input,
{
fn execute(&mut self, input: &mut I, entry: Rc<RefCell<Testcase<I>>>)
-> Result<bool, AflError>;
fn evaluate_input(
&mut self,
input: &mut I,
entry: Rc<RefCell<Testcase<I>>>,
) -> Result<bool, AflError>;
}
pub trait Engine<'a, I, C, E>: Evaluator<I>
where
I: Input,
C: Corpus<I>,
E: Executor<I>,
{
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>;
fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>) {
self.feedbacks_mut().push(feedback);
}
fn stages(&self) -> &Vec<Box<dyn Stage<'a, I, E = Self>>>;
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<'a, I, E = Self>>>;
fn add_stage(&mut self, stage: Box<dyn Stage<'a, I, E = Self>>) {
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> {
let entry = self.corpus_mut().get()?;
for stage in self.stages_mut() {
stage.perform(entry.clone())?;
}
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().place_input(Box::new(input))?;
self.executor_mut().run_target()?;
self.executor_mut().post_exec_observers()?;
}
// TODO new method for this shit
let mut new_entry: Option<Rc<RefCell<Testcase<I>>>> = None; // lazy init
let mut rate_acc = 0;
for feedback in self.feedbacks_mut() {
let (rate, meta) = feedback.is_interesting(self.executor_mut());
rate_acc += rate;
if let Some(m) = meta {
//if new_entry.is_none() {
new_entry = Some(Rc::new(RefCell::new(Testcase::<I>::new(input.clone()))));
//}
new_entry
.unwrap()
.borrow_mut()
.add_metadata("test".to_string(), m);
}
}
Ok(true)
}
}
pub struct DefaultEngine<'a, I, C, E>
where
I: Input,
C: Corpus<I>,
E: Executor<I>,
{
feedbacks: Vec<Box<dyn Feedback<I>>>,
stages: Vec<Box<dyn Stage<'a, I, E = Self>>>,
executor: &'a mut E,
corpus: &'a mut C,
}
impl<'a, I, C, E> Evaluator<I> for DefaultEngine<'a, I, C, E>
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<'a, I, C, E> Engine<'a, I, C, E> for DefaultEngine<'a, I, C, E>
where
I: Input,
C: Corpus<I>,
E: Executor<I>,
{
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 stages(&self) -> &Vec<Box<dyn Stage<'a, I, E = Self>>> {
&self.stages
}
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<'a, I, E = Self>>> {
&mut self.stages
}
fn corpus(&self) -> &C {
self.corpus
}
fn corpus_mut(&mut self) -> &mut C {
self.corpus
}
fn executor(&self) -> &E {
self.executor
}
fn executor_mut(&mut self) -> &mut E {
self.executor
}
}

View File

@ -193,7 +193,6 @@ mod tests {
use crate::inputs::Input;
use crate::observers::Observer;
use crate::AflError;
use std::any::Any;
#[derive(Clone)]
struct NopInput {}

View File

@ -1,6 +1,6 @@
extern crate num;
use crate::corpus::Testcase;
use crate::corpus::{Testcase, TestcaseMetadata};
use crate::executors::Executor;
use crate::inputs::Input;
use crate::observers::MapObserver;
@ -14,9 +14,13 @@ where
I: Input,
{
/// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55)
fn is_interesting(&mut self, executor: &dyn Executor<I>, entry: &Testcase<I>) -> u8;
fn is_interesting(
&mut self,
executor: &dyn Executor<I>,
) -> (u32, Option<Box<dyn TestcaseMetadata>>);
}
/// A Reducer function is used to aggregate values for the novelty search
pub trait Reducer<T>
where
T: Integer + Copy + 'static,
@ -86,7 +90,10 @@ where
O: MapObserver<T>,
I: Input,
{
fn is_interesting(&mut self, _executor: &dyn Executor<I>, _entry: &Testcase<I>) -> u8 {
fn is_interesting(
&mut self,
_executor: &dyn Executor<I>,
) -> (u32, Option<Box<dyn TestcaseMetadata>>) {
let mut interesting = 0;
// TODO: impl. correctly, optimize
@ -101,11 +108,11 @@ where
*history = reduced;
interesting += 25;
if interesting >= 250 {
return 255;
return (255, None);
}
}
}
interesting
(interesting, None)
}
}

View File

@ -1,25 +1,25 @@
pub mod mutational;
use crate::corpus::Testcase;
use crate::engines::Engine;
use crate::engines::Evaluator;
use crate::inputs::Input;
use crate::AflError;
use std::cell::RefCell;
use std::rc::Rc;
pub trait HasEngine<'a, I>
pub trait HasEvaluator<I>
where
I: Input,
{
type E: Engine<'a, I>;
type E: Evaluator<I>;
fn engine(&self) -> &Self::E;
fn eval(&self) -> &Self::E;
fn engine_mut(&mut self) -> &mut Self::E;
fn eval_mut(&mut self) -> &mut Self::E;
}
pub trait Stage<'a, I>: HasEngine<'a, I>
pub trait Stage<'a, I>: HasEvaluator<I>
where
I: Input,
{

View File

@ -1,8 +1,8 @@
use crate::corpus::testcase::Testcase;
use crate::engines::Engine;
use crate::engines::Evaluator;
use crate::inputs::Input;
use crate::mutators::Mutator;
use crate::stages::{HasEngine, Stage};
use crate::stages::{HasEvaluator, Stage};
use crate::utils::{HasRand, Rand};
use crate::AflError;
@ -36,7 +36,7 @@ where
m.mutate(&mut input, i as i32)?;
}
let interesting = self.engine_mut().execute(&mut input, entry.clone())?;
let interesting = self.eval_mut().evaluate_input(&mut input, entry.clone())?;
for m in self.mutators_mut() {
m.post_exec(interesting, i as i32)?;
@ -52,10 +52,10 @@ pub struct DefaultMutationalStage<'a, I, R, E>
where
I: Input,
R: Rand,
E: Engine<'a, I>,
E: Evaluator<I>,
{
rand: &'a mut R,
engine: &'a mut E,
eval: &'a mut E,
mutators: Vec<Box<dyn Mutator<I, R = R>>>,
}
@ -63,7 +63,7 @@ impl<'a, I, R, E> HasRand for DefaultMutationalStage<'a, I, R, E>
where
I: Input,
R: Rand,
E: Engine<'a, I>,
E: Evaluator<I>,
{
type R = R;
@ -75,20 +75,20 @@ where
}
}
impl<'a, I, R, E> HasEngine<'a, I> for DefaultMutationalStage<'a, I, R, E>
impl<'a, I, R, E> HasEvaluator<I> for DefaultMutationalStage<'a, I, R, E>
where
I: Input,
R: Rand,
E: Engine<'a, I>,
E: Evaluator<I>,
{
type E = E;
fn engine(&self) -> &Self::E {
self.engine
fn eval(&self) -> &Self::E {
self.eval
}
fn engine_mut(&mut self) -> &mut Self::E {
self.engine
fn eval_mut(&mut self) -> &mut Self::E {
self.eval
}
}
@ -96,7 +96,7 @@ impl<'a, I, R, E> MutationalStage<'a, I> for DefaultMutationalStage<'a, I, R, E>
where
I: Input,
R: Rand,
E: Engine<'a, I>,
E: Evaluator<I>,
{
fn mutators(&self) -> &Vec<Box<dyn Mutator<I, R = Self::R>>> {
&self.mutators
@ -111,7 +111,7 @@ impl<'a, I, R, E> Stage<'a, I> for DefaultMutationalStage<'a, I, R, E>
where
I: Input,
R: Rand,
E: Engine<'a, I>,
E: Evaluator<I>,
{
fn perform(&mut self, entry: Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
self.perform_mutational(entry)
@ -122,12 +122,12 @@ impl<'a, I, R, E> DefaultMutationalStage<'a, I, R, E>
where
I: Input,
R: Rand,
E: Engine<'a, I>,
E: Evaluator<I>,
{
pub fn new(rand: &'a mut R, engine: &'a mut E) -> Self {
pub fn new(rand: &'a mut R, eval: &'a mut E) -> Self {
DefaultMutationalStage {
rand: rand,
engine: engine,
eval: eval,
mutators: vec![],
}
}