From 9c30a4266716894ae2f6bf02f5f515d9486c3b96 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 29 Oct 2020 14:27:51 +0100 Subject: [PATCH] map feedback, todo reducer traits --- src/executors/mod.rs | 11 +++++++++ src/feedbacks/mod.rs | 55 +++++++++++++++++++++++++++++--------------- src/observers/mod.rs | 23 +++++++++++------- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/executors/mod.rs b/src/executors/mod.rs index 49fb4fffc6..738e8c51e7 100644 --- a/src/executors/mod.rs +++ b/src/executors/mod.rs @@ -21,6 +21,8 @@ pub trait Executor { fn post_exec_observers(&mut self) -> Result<(), AflError>; fn add_observer(&mut self, observer: Box); + + fn get_observers(&self) -> &Vec>; } // TODO abstract classes? how? @@ -161,6 +163,10 @@ impl Executor for InMemoryExecutor { fn add_observer(&mut self, observer: Box) { self.base.observers.push(observer); } + + fn get_observers(&self) -> &Vec> { + &self.base.observers + } } impl InMemoryExecutor { @@ -177,6 +183,7 @@ impl InMemoryExecutor { #[cfg(test)] mod tests { + use std::any::Any; use crate::executors::{Executor, ExitKind, InMemoryExecutor}; use crate::inputs::Input; use crate::observers::Observer; @@ -201,6 +208,10 @@ mod tests { fn post_exec(&mut self) -> Result<(), AflError> { Err(AflError::Unknown) } + + fn as_any(&self) -> &dyn Any { + self + } } fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { diff --git a/src/feedbacks/mod.rs b/src/feedbacks/mod.rs index 2266de71fa..93b266f717 100644 --- a/src/feedbacks/mod.rs +++ b/src/feedbacks/mod.rs @@ -11,34 +11,53 @@ pub trait Feedback { fn is_interesting(&mut self, executor: &dyn Executor, entry: &dyn Testcase) -> u8; } -pub struct CovFeedback<'a, MapT: Integer + Copy> { - virgin_bits: Vec, - smo: &'a MapObserver<'a, MapT>, +pub trait Reducer { + fn reduce(first: T, second: T) -> T; } -impl<'a, MapT: Integer + Copy> Feedback for CovFeedback<'a, MapT> { - fn is_interesting(&mut self, _executor: &dyn Executor, _entry: &dyn Testcase) -> u8 { +pub trait MaxReducer { + fn reduce(first: T, second: T) -> T { + if first > second { first } else { second } + } +} + +pub trait MinReducer { + fn reduce(first: T, second: T) -> T { + if first < second { first } else { second } + } +} + +pub struct MapFeedback { + virgin_map: Vec, +} + +impl<'a, MapT: Integer + Copy + 'static, ReducerT: Reducer> Feedback for MapFeedback { + fn is_interesting(&mut self, executor: &dyn Executor, entry: &dyn Testcase) -> u8 { let mut interesting = 0; - // TODO: impl. correctly, optimize - for (virgin, map) in self.virgin_bits.iter_mut().zip(self.smo.get_map().iter()) { - if virgin != map { - *virgin = *map; - if interesting < 250 { - interesting += 25 + for observer in executor.get_observers() { + if let Some(o) = observer.as_any().downcast_ref::>() { + // TODO: impl. correctly, optimize + for (virgin, map) in self.virgin_map.iter_mut().zip(o.get_map().iter()) { + let reduced = ReducerT::reduce(*virgin, *map); + if *virgin != reduced { + *virgin = reduced; + if interesting < 250 { + interesting += 25 + } + } } + break } } - interesting } } -impl<'a, MapT: Integer + Copy> CovFeedback<'a, MapT> { - /// Create new CovFeedback using a static map observer - pub fn new(smo: &'a MapObserver) -> Self { - CovFeedback { - smo: smo, - virgin_bits: vec![MapT::zero(); smo.get_map().len()], +impl<'a, MapT: Integer + Copy + 'static> MapFeedback { + /// Create new MapFeedback using a static map observer + pub fn new(map_size: usize) -> Self { + MapFeedback { + virgin_map: vec![MapT::zero(); map_size], } } } diff --git a/src/observers/mod.rs b/src/observers/mod.rs index 69e66486fc..d5d6a7c3d5 100644 --- a/src/observers/mod.rs +++ b/src/observers/mod.rs @@ -1,13 +1,14 @@ extern crate num; -use crate::AflError; use std::slice::from_raw_parts_mut; - +use std::any::Any; use num::Integer; +use crate::AflError; + /// Observers observe different information about the target. /// They can then be used by various sorts of feedback. -pub trait Observer { +pub trait Observer : Any { fn flush(&mut self) -> Result<(), AflError> { Ok(()) } @@ -17,14 +18,16 @@ pub trait Observer { fn post_exec(&mut self) -> Result<(), AflError> { Ok(()) } + + fn as_any(&self) -> &dyn Any; } /// A staticMapObserver observes the static map, as oftentimes used for afl-like coverage information -pub struct MapObserver<'a, MapT: Integer + Copy> { - map: &'a mut [MapT], +pub struct MapObserver { + map: &'static mut [MapT], } -impl<'a, MapT: Integer + Copy> Observer for MapObserver<'a, MapT> { +impl Observer for MapObserver { fn reset(&mut self) -> Result<(), AflError> { // Normal memset, see https://rust.godbolt.org/z/Trs5hv for i in self.map.iter_mut() { @@ -32,9 +35,13 @@ impl<'a, MapT: Integer + Copy> Observer for MapObserver<'a, MapT> { } Ok(()) } + + fn as_any(&self) -> &dyn Any { + self + } } -impl<'a, MapT: Integer + Copy> MapObserver<'a, MapT> { +impl MapObserver { pub fn get_map(&self) -> &[MapT] { self.map } @@ -44,7 +51,7 @@ impl<'a, MapT: Integer + Copy> MapObserver<'a, MapT> { } } -impl<'a, MapT: Integer + Copy> MapObserver<'a, MapT> { +impl MapObserver { /// Creates a new MapObserver from a raw pointer. pub fn new(map_ptr: *mut MapT, len: usize) -> Self { unsafe {