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 add_observer(&mut self, observer: Box<dyn Observer>);
fn get_observers(&self) -> &Vec<Box<dyn Observer>>;
}
// TODO abstract classes? how?
@ -161,6 +163,10 @@ impl Executor for InMemoryExecutor {
fn add_observer(&mut self, observer: Box<dyn Observer>) {
self.base.observers.push(observer);
}
fn get_observers(&self) -> &Vec<Box<dyn Observer>> {
&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 {

View File

@ -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<MapT>,
smo: &'a MapObserver<'a, MapT>,
pub trait Reducer<T: Integer + Copy + 'static> {
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<T: Integer + Copy + 'static> {
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;
for observer in executor.get_observers() {
if let Some(o) = observer.as_any().downcast_ref::<MapObserver<MapT>>() {
// TODO: impl. correctly, optimize
for (virgin, map) in self.virgin_bits.iter_mut().zip(self.smo.get_map().iter()) {
if virgin != map {
*virgin = *map;
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<MapT>) -> Self {
CovFeedback {
smo: smo,
virgin_bits: vec![MapT::zero(); smo.get_map().len()],
impl<'a, MapT: Integer + Copy + 'static> MapFeedback<MapT> {
/// Create new MapFeedback using a static map observer
pub fn new(map_size: usize) -> Self {
MapFeedback {
virgin_map: vec![MapT::zero(); map_size],
}
}
}

View File

@ -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<MapT: Integer + Copy + 'static + 'static> {
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> {
// 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<MapT: Integer + Copy + 'static> MapObserver<MapT> {
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<MapT: Integer + Copy + 'static> MapObserver<MapT> {
/// Creates a new MapObserver from a raw pointer.
pub fn new(map_ptr: *mut MapT, len: usize) -> Self {
unsafe {