map observer

This commit is contained in:
Andrea Fioraldi 2020-11-05 11:26:33 +01:00
parent 63a83a70ff
commit 34d51ee5e0
3 changed files with 80 additions and 41 deletions

View File

@ -215,10 +215,6 @@ mod tests {
fn post_exec(&mut self) -> Result<(), AflError> { fn post_exec(&mut self) -> Result<(), AflError> {
Err(AflError::Unknown("Nop exec, testing only".to_string())) Err(AflError::Unknown("Nop exec, testing only".to_string()))
} }
fn as_any(&self) -> &dyn Any {
self
}
} }
fn test_harness_fn_nop(_executor: &dyn Executor<NopInput>, buf: &[u8]) -> ExitKind { fn test_harness_fn_nop(_executor: &dyn Executor<NopInput>, buf: &[u8]) -> ExitKind {

View File

@ -65,26 +65,28 @@ where
} }
/// The most common AFL-like feedback type /// The most common AFL-like feedback type
pub struct MapFeedback<'a, T, R> pub struct MapFeedback<'a, T, R, O>
where where
T: Integer + Copy + 'static, T: Integer + Copy + 'static,
R: Reducer<T>, R: Reducer<T>,
O: MapObserver<T>,
{ {
/// Contains information about untouched entries /// Contains information about untouched entries
history_map: &'a RefCell<Vec<T>>, history_map: &'a RefCell<Vec<T>>,
/// The observer this feedback struct observes /// The observer this feedback struct observes
map_observer: &'a RefCell<MapObserver</*'a,*/ T>>, map_observer: &'a RefCell<O>,
/// Phantom Data of Reducer /// Phantom Data of Reducer
phantom: PhantomData<R>, phantom: PhantomData<R>,
} }
impl<'a, T, R, I> Feedback<I> for MapFeedback<'a, T, R> impl<'a, T, R, O, I> Feedback<I> for MapFeedback<'a, T, R, O>
where where
T: Integer + Copy + 'static, T: Integer + Copy + 'static,
R: Reducer<T>, R: Reducer<T>,
O: MapObserver<T>,
I: Input, I: Input,
{ {
fn is_interesting(&mut self, _executor: &dyn Executor<I>, entry: &Testcase<I>) -> u8 { fn is_interesting(&mut self, _executor: &dyn Executor<I>, _entry: &Testcase<I>) -> u8 {
let mut interesting = 0; let mut interesting = 0;
// TODO: impl. correctly, optimize // TODO: impl. correctly, optimize
@ -92,7 +94,7 @@ where
.history_map .history_map
.borrow_mut() .borrow_mut()
.iter_mut() .iter_mut()
.zip(self.map_observer.borrow().get_map().iter()) .zip(self.map_observer.borrow().map().iter())
{ {
let reduced = R::reduce(*history, *map); let reduced = R::reduce(*history, *map);
if *history != reduced { 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 where
T: Integer + Copy + 'static, T: Integer + Copy + 'static,
R: Reducer<T>, R: Reducer<T>,
O: MapObserver<T>,
{ {
/// Create new MapFeedback using a map observer, and a map. /// Create new MapFeedback using a map observer, and a map.
/// The map can be shared. /// The map can be shared.
pub fn new( pub fn new(map_observer: &'a RefCell<O>, history_map: &'a RefCell<Vec<T>>) -> Self {
map_observer: &'a RefCell<MapObserver</*'a, */ T>>,
history_map: &'a RefCell<Vec<T>>,
) -> Self {
MapFeedback { MapFeedback {
map_observer: map_observer, map_observer: map_observer,
history_map: history_map, history_map: history_map,
@ -136,7 +136,5 @@ where
} }
} }
#[allow(dead_code)] pub type MaxMapFeedback<'a, T, O> = MapFeedback<'a, T, MaxReducer<T>, O>;
type MaxMapFeedback<'a, T> = MapFeedback<'a, T, MaxReducer<T>>; pub type MinMapFeedback<'a, T, O> = MapFeedback<'a, T, MinReducer<T>, O>;
#[allow(dead_code)]
type MinMapFeedback<'a, T> = MapFeedback<'a, T, MinReducer<T>>;

View File

@ -1,14 +1,13 @@
extern crate num; extern crate num;
use num::Integer; use num::Integer;
use std::any::Any;
use std::slice::from_raw_parts_mut; use std::slice::from_raw_parts_mut;
use crate::AflError; use crate::AflError;
/// Observers observe different information about the target. /// Observers observe different information about the target.
/// They can then be used by various sorts of feedback. /// They can then be used by various sorts of feedback.
pub trait Observer: Any { pub trait Observer {
fn flush(&mut self) -> Result<(), AflError> { fn flush(&mut self) -> Result<(), AflError> {
Ok(()) Ok(())
} }
@ -18,45 +17,91 @@ pub trait Observer: Any {
fn post_exec(&mut self) -> Result<(), AflError> { fn post_exec(&mut self) -> Result<(), AflError> {
Ok(()) Ok(())
} }
fn as_any(&self) -> &dyn Any;
} }
/// A staticMapObserver observes the static map, as oftentimes used for afl-like coverage information /// A MapObserver observes the static map, as oftentimes used for afl-like coverage information
pub struct MapObserver<MapT: Integer + Copy + 'static + 'static> { pub trait MapObserver<T>
map: &'static mut [MapT], where
} T: Integer + Copy,
{
/// Get the map
fn map(&self) -> &[T];
impl<MapT: Integer + Copy + 'static> Observer for MapObserver<MapT> { /// Get the map (mutable)
fn reset(&mut self) -> Result<(), AflError> { 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 // Normal memset, see https://rust.godbolt.org/z/Trs5hv
for i in self.map.iter_mut() { for i in self.map_mut().iter_mut() {
*i = MapT::zero(); *i = T::zero();
} }
Ok(()) Ok(())
} }
}
fn as_any(&self) -> &dyn Any { pub struct DefaultMapObserver<'a, T>
self 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<MapT: Integer + Copy + 'static> MapObserver<MapT> { impl<'a, T: Integer + Copy> MapObserver<T> for DefaultMapObserver<'a, T> {
pub fn get_map(&self) -> &[MapT] { fn map(&self) -> &[T] {
self.map &self.map
} }
pub fn get_map_mut(&mut self) -> &mut [MapT] { fn map_mut(&mut self) -> &mut [T] {
self.map &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<MapT: Integer + Copy + 'static> MapObserver<MapT> { impl<'a, T: Integer + Copy> DefaultMapObserver<'a, T> {
/// Creates a new MapObserver from a raw pointer. /// Creates a new MapObserver
pub fn new(map_ptr: *mut MapT, len: usize) -> Self { 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 { unsafe {
MapObserver { let initial = if len > 0 { *map_ptr } else { T::zero() };
DefaultMapObserver {
map: from_raw_parts_mut(map_ptr, len), map: from_raw_parts_mut(map_ptr, len),
initial: initial,
} }
} }
} }