map feedback, todo reducer traits

This commit is contained in:
Andrea Fioraldi 2020-10-29 14:27:51 +01:00
parent 604e278664
commit 9c30a42667
3 changed files with 63 additions and 26 deletions

View File

@ -21,6 +21,8 @@ pub trait Executor {
fn post_exec_observers(&mut self) -> Result<(), AflError>; fn post_exec_observers(&mut self) -> Result<(), AflError>;
fn add_observer(&mut self, observer: Box<dyn Observer>); fn add_observer(&mut self, observer: Box<dyn Observer>);
fn get_observers(&self) -> &Vec<Box<dyn Observer>>;
} }
// TODO abstract classes? how? // TODO abstract classes? how?
@ -161,6 +163,10 @@ impl Executor for InMemoryExecutor {
fn add_observer(&mut self, observer: Box<dyn Observer>) { fn add_observer(&mut self, observer: Box<dyn Observer>) {
self.base.observers.push(observer); self.base.observers.push(observer);
} }
fn get_observers(&self) -> &Vec<Box<dyn Observer>> {
&self.base.observers
}
} }
impl InMemoryExecutor { impl InMemoryExecutor {
@ -177,6 +183,7 @@ impl InMemoryExecutor {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::any::Any;
use crate::executors::{Executor, ExitKind, InMemoryExecutor}; use crate::executors::{Executor, ExitKind, InMemoryExecutor};
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::Observer; use crate::observers::Observer;
@ -201,6 +208,10 @@ mod tests {
fn post_exec(&mut self) -> Result<(), AflError> { fn post_exec(&mut self) -> Result<(), AflError> {
Err(AflError::Unknown) Err(AflError::Unknown)
} }
fn as_any(&self) -> &dyn Any {
self
}
} }
fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind {

View File

@ -11,34 +11,53 @@ pub trait Feedback {
fn is_interesting(&mut self, executor: &dyn Executor, entry: &dyn Testcase) -> u8; fn is_interesting(&mut self, executor: &dyn Executor, entry: &dyn Testcase) -> u8;
} }
pub struct CovFeedback<'a, MapT: Integer + Copy> { pub trait Reducer<T: Integer + Copy + 'static> {
virgin_bits: Vec<MapT>, fn reduce(first: T, second: T) -> T;
smo: &'a MapObserver<'a, MapT>,
} }
impl<'a, MapT: Integer + Copy> Feedback for CovFeedback<'a, MapT> { pub trait MaxReducer<T: Integer + Copy + 'static> {
fn is_interesting(&mut self, _executor: &dyn Executor, _entry: &dyn Testcase) -> u8 { fn reduce(first: T, second: T) -> T {
if first > second { first } else { second }
}
}
pub trait MinReducer<T: Integer + Copy + 'static> {
fn reduce(first: T, second: T) -> T {
if first < second { first } else { second }
}
}
pub struct MapFeedback<MapT: Integer + Copy + 'static> {
virgin_map: Vec<MapT>,
}
impl<'a, MapT: Integer + Copy + 'static, ReducerT: Reducer<MapT>> Feedback for MapFeedback<MapT> {
fn is_interesting(&mut self, executor: &dyn Executor, entry: &dyn Testcase) -> u8 {
let mut interesting = 0; let mut interesting = 0;
// TODO: impl. correctly, optimize for observer in executor.get_observers() {
for (virgin, map) in self.virgin_bits.iter_mut().zip(self.smo.get_map().iter()) { if let Some(o) = observer.as_any().downcast_ref::<MapObserver<MapT>>() {
if virgin != map { // TODO: impl. correctly, optimize
*virgin = *map; for (virgin, map) in self.virgin_map.iter_mut().zip(o.get_map().iter()) {
if interesting < 250 { let reduced = ReducerT::reduce(*virgin, *map);
interesting += 25 if *virgin != reduced {
*virgin = reduced;
if interesting < 250 {
interesting += 25
}
}
} }
break
} }
} }
interesting interesting
} }
} }
impl<'a, MapT: Integer + Copy> CovFeedback<'a, MapT> { impl<'a, MapT: Integer + Copy + 'static> MapFeedback<MapT> {
/// Create new CovFeedback using a static map observer /// Create new MapFeedback using a static map observer
pub fn new(smo: &'a MapObserver<MapT>) -> Self { pub fn new(map_size: usize) -> Self {
CovFeedback { MapFeedback {
smo: smo, virgin_map: vec![MapT::zero(); map_size],
virgin_bits: vec![MapT::zero(); smo.get_map().len()],
} }
} }
} }

View File

@ -1,13 +1,14 @@
extern crate num; extern crate num;
use crate::AflError;
use std::slice::from_raw_parts_mut; use std::slice::from_raw_parts_mut;
use std::any::Any;
use num::Integer; use num::Integer;
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 { pub trait Observer : Any {
fn flush(&mut self) -> Result<(), AflError> { fn flush(&mut self) -> Result<(), AflError> {
Ok(()) Ok(())
} }
@ -17,14 +18,16 @@ pub trait Observer {
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 staticMapObserver observes the static map, as oftentimes used for afl-like coverage information
pub struct MapObserver<'a, MapT: Integer + Copy> { pub struct MapObserver<MapT: Integer + Copy + 'static + 'static> {
map: &'a mut [MapT], map: &'static mut [MapT],
} }
impl<'a, MapT: Integer + Copy> Observer for MapObserver<'a, MapT> { impl<MapT: Integer + Copy + 'static> Observer for MapObserver<MapT> {
fn reset(&mut self) -> Result<(), AflError> { fn reset(&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.iter_mut() {
@ -32,9 +35,13 @@ impl<'a, MapT: Integer + Copy> Observer for MapObserver<'a, MapT> {
} }
Ok(()) Ok(())
} }
fn as_any(&self) -> &dyn Any {
self
}
} }
impl<'a, MapT: Integer + Copy> MapObserver<'a, MapT> { impl<MapT: Integer + Copy + 'static> MapObserver<MapT> {
pub fn get_map(&self) -> &[MapT] { pub fn get_map(&self) -> &[MapT] {
self.map self.map
} }
@ -44,7 +51,7 @@ impl<'a, MapT: Integer + Copy> MapObserver<'a, MapT> {
} }
} }
impl<'a, MapT: Integer + Copy> MapObserver<'a, MapT> { impl<MapT: Integer + Copy + 'static> MapObserver<MapT> {
/// Creates a new MapObserver from a raw pointer. /// Creates a new MapObserver from a raw pointer.
pub fn new(map_ptr: *mut MapT, len: usize) -> Self { pub fn new(map_ptr: *mut MapT, len: usize) -> Self {
unsafe { unsafe {