From 34d51ee5e03ceb6ac247176454920fe4b6e0c3fb Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 5 Nov 2020 11:26:33 +0100 Subject: [PATCH] map observer --- src/executors/inmemory.rs | 4 -- src/feedbacks/mod.rs | 26 ++++++----- src/observers/mod.rs | 91 +++++++++++++++++++++++++++++---------- 3 files changed, 80 insertions(+), 41 deletions(-) diff --git a/src/executors/inmemory.rs b/src/executors/inmemory.rs index ed986ebbda..dc6afca1c6 100644 --- a/src/executors/inmemory.rs +++ b/src/executors/inmemory.rs @@ -215,10 +215,6 @@ mod tests { fn post_exec(&mut self) -> Result<(), AflError> { Err(AflError::Unknown("Nop exec, testing only".to_string())) } - - 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 07f36e97dc..683565b717 100644 --- a/src/feedbacks/mod.rs +++ b/src/feedbacks/mod.rs @@ -65,26 +65,28 @@ where } /// The most common AFL-like feedback type -pub struct MapFeedback<'a, T, R> +pub struct MapFeedback<'a, T, R, O> where T: Integer + Copy + 'static, R: Reducer, + O: MapObserver, { /// Contains information about untouched entries history_map: &'a RefCell>, /// The observer this feedback struct observes - map_observer: &'a RefCell>, + map_observer: &'a RefCell, /// Phantom Data of Reducer phantom: PhantomData, } -impl<'a, T, R, I> Feedback for MapFeedback<'a, T, R> +impl<'a, T, R, O, I> Feedback for MapFeedback<'a, T, R, O> where T: Integer + Copy + 'static, R: Reducer, + O: MapObserver, I: Input, { - fn is_interesting(&mut self, _executor: &dyn Executor, entry: &Testcase) -> u8 { + fn is_interesting(&mut self, _executor: &dyn Executor, _entry: &Testcase) -> u8 { let mut interesting = 0; // TODO: impl. correctly, optimize @@ -92,7 +94,7 @@ where .history_map .borrow_mut() .iter_mut() - .zip(self.map_observer.borrow().get_map().iter()) + .zip(self.map_observer.borrow().map().iter()) { let reduced = R::reduce(*history, *map); if *history != reduced { @@ -107,17 +109,15 @@ where } } -impl<'a, T, R> MapFeedback<'a, T, R> +impl<'a, T, R, O> MapFeedback<'a, T, R, O> where T: Integer + Copy + 'static, R: Reducer, + O: MapObserver, { /// Create new MapFeedback using a map observer, and a map. /// The map can be shared. - pub fn new( - map_observer: &'a RefCell>, - history_map: &'a RefCell>, - ) -> Self { + pub fn new(map_observer: &'a RefCell, history_map: &'a RefCell>) -> Self { MapFeedback { map_observer: map_observer, history_map: history_map, @@ -136,7 +136,5 @@ where } } -#[allow(dead_code)] -type MaxMapFeedback<'a, T> = MapFeedback<'a, T, MaxReducer>; -#[allow(dead_code)] -type MinMapFeedback<'a, T> = MapFeedback<'a, T, MinReducer>; +pub type MaxMapFeedback<'a, T, O> = MapFeedback<'a, T, MaxReducer, O>; +pub type MinMapFeedback<'a, T, O> = MapFeedback<'a, T, MinReducer, O>; diff --git a/src/observers/mod.rs b/src/observers/mod.rs index 752744ff24..bcd9da6e72 100644 --- a/src/observers/mod.rs +++ b/src/observers/mod.rs @@ -1,14 +1,13 @@ extern crate num; use num::Integer; -use std::any::Any; use std::slice::from_raw_parts_mut; use crate::AflError; /// Observers observe different information about the target. /// They can then be used by various sorts of feedback. -pub trait Observer: Any { +pub trait Observer { fn flush(&mut self) -> Result<(), AflError> { Ok(()) } @@ -18,45 +17,91 @@ pub trait Observer: Any { 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 { - map: &'static mut [MapT], -} +/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information +pub trait MapObserver +where + T: Integer + Copy, +{ + /// Get the map + fn map(&self) -> &[T]; -impl Observer for MapObserver { - fn reset(&mut self) -> Result<(), AflError> { + /// Get the map (mutable) + fn map_mut(&mut self) -> &mut [T]; + + /// Get the initial value for reset() + fn initial(&self) -> &T; + + /// Get the initial value for reset() + fn initial_mut(&mut self) -> &mut T; + + /// Set the initial value for reset() + fn set_initial(&mut self, initial: T); + + /// Reset the map + fn reset_map(&mut self) -> Result<(), AflError> { // Normal memset, see https://rust.godbolt.org/z/Trs5hv - for i in self.map.iter_mut() { - *i = MapT::zero(); + for i in self.map_mut().iter_mut() { + *i = T::zero(); } Ok(()) } +} - fn as_any(&self) -> &dyn Any { - self +pub struct DefaultMapObserver<'a, T> +where + T: Integer + Copy, +{ + map: &'a mut [T], + initial: T, +} + +impl<'a, T: Integer + Copy> Observer for DefaultMapObserver<'a, T> { + fn reset(&mut self) -> Result<(), AflError> { + self.reset_map() } } -impl MapObserver { - pub fn get_map(&self) -> &[MapT] { - self.map +impl<'a, T: Integer + Copy> MapObserver for DefaultMapObserver<'a, T> { + fn map(&self) -> &[T] { + &self.map } - pub fn get_map_mut(&mut self) -> &mut [MapT] { - self.map + fn map_mut(&mut self) -> &mut [T] { + &mut self.map + } + + fn initial(&self) -> &T { + &self.initial + } + + fn initial_mut(&mut self) -> &mut T { + &mut self.initial + } + + fn set_initial(&mut self, initial: T) { + self.initial = initial } } -impl MapObserver { - /// Creates a new MapObserver from a raw pointer. - pub fn new(map_ptr: *mut MapT, len: usize) -> Self { +impl<'a, T: Integer + Copy> DefaultMapObserver<'a, T> { + /// Creates a new MapObserver + pub fn new(map: &'a mut [T]) -> Self { + let initial = if map.len() > 0 { map[0] } else { T::zero() }; + DefaultMapObserver { + map: map, + initial: initial, + } + } + + /// Creates a new MapObserver from a raw pointer + pub fn new_from_ptr(map_ptr: *mut T, len: usize) -> Self { unsafe { - MapObserver { + let initial = if len > 0 { *map_ptr } else { T::zero() }; + DefaultMapObserver { map: from_raw_parts_mut(map_ptr, len), + initial: initial, } } }