map feedback, todo reducer traits
This commit is contained in:
parent
604e278664
commit
9c30a42667
@ -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 {
|
||||
|
@ -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;
|
||||
// TODO: impl. correctly, optimize
|
||||
for (virgin, map) in self.virgin_bits.iter_mut().zip(self.smo.get_map().iter()) {
|
||||
if virgin != map {
|
||||
*virgin = *map;
|
||||
if interesting < 250 {
|
||||
interesting += 25
|
||||
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_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],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user