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> {
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 {

View File

@ -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<T>,
O: MapObserver<T>,
{
/// Contains information about untouched entries
history_map: &'a RefCell<Vec<T>>,
/// The observer this feedback struct observes
map_observer: &'a RefCell<MapObserver</*'a,*/ T>>,
map_observer: &'a RefCell<O>,
/// Phantom Data of Reducer
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
T: Integer + Copy + 'static,
R: Reducer<T>,
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>, _entry: &Testcase<I>) -> 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<T>,
O: MapObserver<T>,
{
/// Create new MapFeedback using a map observer, and a map.
/// The map can be shared.
pub fn new(
map_observer: &'a RefCell<MapObserver</*'a, */ T>>,
history_map: &'a RefCell<Vec<T>>,
) -> Self {
pub fn new(map_observer: &'a RefCell<O>, history_map: &'a RefCell<Vec<T>>) -> 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<T>>;
#[allow(dead_code)]
type MinMapFeedback<'a, T> = MapFeedback<'a, T, MinReducer<T>>;
pub type MaxMapFeedback<'a, T, O> = MapFeedback<'a, T, MaxReducer<T>, O>;
pub type MinMapFeedback<'a, T, O> = MapFeedback<'a, T, MinReducer<T>, O>;

View File

@ -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<MapT: Integer + Copy + 'static + 'static> {
map: &'static mut [MapT],
}
/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information
pub trait MapObserver<T>
where
T: Integer + Copy,
{
/// Get the map
fn map(&self) -> &[T];
impl<MapT: Integer + Copy + 'static> Observer for MapObserver<MapT> {
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<MapT: Integer + Copy + 'static> MapObserver<MapT> {
pub fn get_map(&self) -> &[MapT] {
self.map
impl<'a, T: Integer + Copy> MapObserver<T> 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<MapT: Integer + Copy + 'static> MapObserver<MapT> {
/// 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,
}
}
}