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 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 {
|
||||||
|
@ -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()],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user