tracker map feedback
This commit is contained in:
parent
42257f3ffb
commit
acee52ddfb
9
README.md
Normal file
9
README.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
How to perf:
|
||||||
|
|
||||||
|
```
|
||||||
|
perf record -e task-clock ./PROGRAM
|
||||||
|
|
||||||
|
perf report --stdio --dsos=PROGRAM
|
||||||
|
|
||||||
|
rm perf.data
|
||||||
|
```
|
@ -126,7 +126,7 @@ where
|
|||||||
fitness += feedback.is_interesting(&input)?;
|
fitness += feedback.is_interesting(&input)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fitness >= 25 {
|
if fitness > 0 {
|
||||||
let testcase: Rc<RefCell<_>> = Testcase::new(input).into();
|
let testcase: Rc<RefCell<_>> = Testcase::new(input).into();
|
||||||
for feedback in self.feedbacks_mut() {
|
for feedback in self.feedbacks_mut() {
|
||||||
feedback.append_metadata(testcase.clone())?;
|
feedback.append_metadata(testcase.clone())?;
|
||||||
|
@ -6,7 +6,7 @@ use core::cell::RefCell;
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use num::Integer;
|
use num::Integer;
|
||||||
|
|
||||||
use crate::corpus::Testcase;
|
use crate::corpus::{Testcase, TestcaseMetadata};
|
||||||
use crate::inputs::Input;
|
use crate::inputs::Input;
|
||||||
use crate::observers::MapObserver;
|
use crate::observers::MapObserver;
|
||||||
use crate::AflError;
|
use crate::AflError;
|
||||||
@ -77,6 +77,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a usable history map of the given size
|
||||||
|
pub fn create_history_map<T>(map_size: usize) -> Rc<RefCell<Vec<T>>>
|
||||||
|
where
|
||||||
|
T: Default + Clone,
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Rc::new(RefCell::new(vec![T::default(); map_size]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The most common AFL-like feedback type
|
/// The most common AFL-like feedback type
|
||||||
pub struct MapFeedback<T, R, O>
|
pub struct MapFeedback<T, R, O>
|
||||||
where
|
where
|
||||||
@ -102,26 +112,40 @@ where
|
|||||||
fn is_interesting(&mut self, _input: &I) -> Result<u32, AflError> {
|
fn is_interesting(&mut self, _input: &I) -> Result<u32, AflError> {
|
||||||
let mut interesting = 0;
|
let mut interesting = 0;
|
||||||
|
|
||||||
// TODO: impl. correctly, optimize
|
// TODO optimize
|
||||||
for (history, map) in self
|
let size = self.map_observer.borrow().map().len();
|
||||||
.history_map
|
let mut history_map = self.history_map.borrow_mut();
|
||||||
.borrow_mut()
|
let observer = self.map_observer.borrow();
|
||||||
.iter_mut()
|
for i in 0..size {
|
||||||
.zip(self.map_observer.borrow().map().iter())
|
let history = history_map[i];
|
||||||
{
|
let item = observer.map()[i];
|
||||||
let reduced = R::reduce(*history, *map);
|
let reduced = R::reduce(history, item);
|
||||||
if *history != reduced {
|
if history != reduced {
|
||||||
*history = reduced;
|
history_map[i] = reduced;
|
||||||
interesting += 25;
|
interesting += 1;
|
||||||
if interesting >= 250 {
|
|
||||||
return Ok(255);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(interesting)
|
Ok(interesting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, R, O> MapFeedback<T, R, O>
|
||||||
|
where
|
||||||
|
T: Integer + Copy + Default + 'static,
|
||||||
|
R: Reducer<T>,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
|
/// Create new MapFeedback using a map observer
|
||||||
|
pub fn new(map_observer: Rc<RefCell<O>>, map_size: usize) -> Self {
|
||||||
|
MapFeedback {
|
||||||
|
map_observer: map_observer,
|
||||||
|
history_map: create_history_map::<T>(map_size),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, R, O> MapFeedback<T, R, O>
|
impl<T, R, O> MapFeedback<T, R, O>
|
||||||
where
|
where
|
||||||
T: Integer + Copy + 'static,
|
T: Integer + Copy + 'static,
|
||||||
@ -130,7 +154,10 @@ where
|
|||||||
{
|
{
|
||||||
/// Create new MapFeedback using a map observer, and a map.
|
/// Create new MapFeedback using a map observer, and a map.
|
||||||
/// The map can be shared.
|
/// The map can be shared.
|
||||||
pub fn new(map_observer: Rc<RefCell<O>>, history_map: Rc<RefCell<Vec<T>>>) -> Self {
|
pub fn with_history_map(
|
||||||
|
map_observer: Rc<RefCell<O>>,
|
||||||
|
history_map: Rc<RefCell<Vec<T>>>,
|
||||||
|
) -> Self {
|
||||||
MapFeedback {
|
MapFeedback {
|
||||||
map_observer: map_observer,
|
map_observer: map_observer,
|
||||||
history_map: history_map,
|
history_map: history_map,
|
||||||
@ -139,15 +166,126 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a usable history map of the given size
|
pub struct MapNoveltiesMetadata {
|
||||||
pub fn create_history_map<T>(map_size: usize) -> Rc<RefCell<Vec<T>>>
|
novelties: Vec<usize>,
|
||||||
|
}
|
||||||
|
impl TestcaseMetadata for MapNoveltiesMetadata {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"MapNoveltiesMetadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MapNoveltiesMetadata {
|
||||||
|
pub fn novelties(&self) -> &[usize] {
|
||||||
|
&self.novelties
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(novelties: Vec<usize>) -> Self {
|
||||||
|
MapNoveltiesMetadata {
|
||||||
|
novelties: novelties,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The most common AFL-like feedback type that adds metadata about newly discovered entries
|
||||||
|
pub struct MapTrackerFeedback<T, R, O>
|
||||||
where
|
where
|
||||||
T: Default + Clone,
|
T: Integer + Copy + 'static,
|
||||||
|
R: Reducer<T>,
|
||||||
|
O: MapObserver<T>,
|
||||||
{
|
{
|
||||||
{
|
/// Contains information about untouched entries
|
||||||
Rc::new(RefCell::new(vec![T::default(); map_size]))
|
history_map: Rc<RefCell<Vec<T>>>,
|
||||||
|
/// The observer this feedback struct observes
|
||||||
|
map_observer: Rc<RefCell<O>>,
|
||||||
|
/// Phantom Data of Reducer
|
||||||
|
phantom: PhantomData<R>,
|
||||||
|
/// Track novel entries indexes
|
||||||
|
novelties: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, R, O, I> Feedback<I> for MapTrackerFeedback<T, R, O>
|
||||||
|
where
|
||||||
|
T: Integer + Copy + 'static,
|
||||||
|
R: Reducer<T>,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn is_interesting(&mut self, _input: &I) -> Result<u32, AflError> {
|
||||||
|
let mut interesting = 0;
|
||||||
|
|
||||||
|
// TODO optimize
|
||||||
|
let size = self.map_observer.borrow().map().len();
|
||||||
|
let mut history_map = self.history_map.borrow_mut();
|
||||||
|
let observer = self.map_observer.borrow();
|
||||||
|
for i in 0..size {
|
||||||
|
let history = history_map[i];
|
||||||
|
let item = observer.map()[i];
|
||||||
|
let reduced = R::reduce(history, item);
|
||||||
|
if history != reduced {
|
||||||
|
history_map[i] = reduced;
|
||||||
|
interesting += 1;
|
||||||
|
self.novelties.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(interesting)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append_metadata(&mut self, testcase: Rc<RefCell<Testcase<I>>>) -> Result<(), AflError> {
|
||||||
|
let meta = Box::new(MapNoveltiesMetadata::new(core::mem::take(
|
||||||
|
&mut self.novelties,
|
||||||
|
)));
|
||||||
|
testcase.borrow_mut().add_metadata(meta);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
||||||
|
fn discard_metadata(&mut self) -> Result<(), AflError> {
|
||||||
|
self.novelties.clear();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, R, O> MapTrackerFeedback<T, R, O>
|
||||||
|
where
|
||||||
|
T: Integer + Copy + Default + 'static,
|
||||||
|
R: Reducer<T>,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
|
/// Create new MapFeedback using a map observer
|
||||||
|
pub fn new(map_observer: Rc<RefCell<O>>, map_size: usize) -> Self {
|
||||||
|
MapTrackerFeedback {
|
||||||
|
map_observer: map_observer,
|
||||||
|
history_map: create_history_map::<T>(map_size),
|
||||||
|
phantom: PhantomData,
|
||||||
|
novelties: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, R, O> MapTrackerFeedback<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 with_history_map(
|
||||||
|
map_observer: Rc<RefCell<O>>,
|
||||||
|
history_map: Rc<RefCell<Vec<T>>>,
|
||||||
|
) -> Self {
|
||||||
|
MapTrackerFeedback {
|
||||||
|
map_observer: map_observer,
|
||||||
|
history_map: history_map,
|
||||||
|
phantom: PhantomData,
|
||||||
|
novelties: vec![],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MaxMapFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
|
pub type MaxMapFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
|
||||||
pub type MinMapFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
|
pub type MinMapFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
|
||||||
|
|
||||||
|
pub type MaxMapTrackerFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
|
||||||
|
pub type MinMapTrackerFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
|
||||||
|
@ -175,7 +175,7 @@ pub struct XorShift64Rand {
|
|||||||
|
|
||||||
impl Rand for XorShift64Rand {
|
impl Rand for XorShift64Rand {
|
||||||
fn set_seed(&mut self, seed: u64) {
|
fn set_seed(&mut self, seed: u64) {
|
||||||
self.rand_seed = seed;
|
self.rand_seed = seed ^ 0x1234567890abcdef;
|
||||||
self.seeded = true;
|
self.seeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,6 +219,56 @@ impl XorShift64Rand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// XXH3 Based, hopefully speedy, rnd implementation
|
||||||
|
///
|
||||||
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
pub struct Lehmer64Rand {
|
||||||
|
rand_seed: u128,
|
||||||
|
seeded: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rand for Lehmer64Rand {
|
||||||
|
fn set_seed(&mut self, seed: u64) {
|
||||||
|
self.rand_seed = (seed as u128) ^ 0x1234567890abcdef;
|
||||||
|
self.seeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next(&mut self) -> u64 {
|
||||||
|
self.rand_seed *= 0xda942042e4dd58b5;
|
||||||
|
return (self.rand_seed >> 64) as u64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Rc<RefCell<Self>>> for Lehmer64Rand {
|
||||||
|
fn into(self) -> Rc<RefCell<Self>> {
|
||||||
|
Rc::new(RefCell::new(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Lehmer64Rand {
|
||||||
|
/// Creates a new Xoshiro rand with the given seed
|
||||||
|
pub fn new(seed: u64) -> Self {
|
||||||
|
let mut ret: Self = Default::default();
|
||||||
|
ret.set_seed(seed); // TODO: Proper random seed?
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_rc_refcell(self) -> Rc<RefCell<Self>> {
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a rand instance, pre-seeded with the current time in nanoseconds.
|
||||||
|
/// Needs stdlib timer
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub fn preseeded() -> Self {
|
||||||
|
let seed = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_nanos() as u64;
|
||||||
|
Self::new(seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn current_milliseconds() -> u64 {
|
pub fn current_milliseconds() -> u64 {
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
|
@ -8,7 +8,7 @@ use afl::engines::{generate_initial_inputs, Engine, State, StdEngine, StdState};
|
|||||||
use afl::events::LoggerEventManager;
|
use afl::events::LoggerEventManager;
|
||||||
use afl::executors::inmemory::InMemoryExecutor;
|
use afl::executors::inmemory::InMemoryExecutor;
|
||||||
use afl::executors::{Executor, ExitKind};
|
use afl::executors::{Executor, ExitKind};
|
||||||
use afl::feedbacks::{create_history_map, MaxMapFeedback};
|
use afl::feedbacks::MaxMapTrackerFeedback;
|
||||||
use afl::generators::RandPrintablesGenerator;
|
use afl::generators::RandPrintablesGenerator;
|
||||||
use afl::mutators::scheduled::HavocBytesMutator;
|
use afl::mutators::scheduled::HavocBytesMutator;
|
||||||
use afl::observers::StdMapObserver;
|
use afl::observers::StdMapObserver;
|
||||||
@ -39,15 +39,14 @@ pub extern "C" fn afl_libfuzzer_main() {
|
|||||||
let mut rand = StdRand::new(0);
|
let mut rand = StdRand::new(0);
|
||||||
|
|
||||||
let corpus = InMemoryCorpus::new();
|
let corpus = InMemoryCorpus::new();
|
||||||
let mut generator = RandPrintablesGenerator::new(1);
|
let mut generator = RandPrintablesGenerator::new(32);
|
||||||
let mut events = LoggerEventManager::new(stderr());
|
let mut events = LoggerEventManager::new(stderr());
|
||||||
|
|
||||||
let edges_observer = Rc::new(RefCell::new(StdMapObserver::new_from_ptr(
|
let edges_observer = Rc::new(RefCell::new(StdMapObserver::new_from_ptr(
|
||||||
unsafe { __lafl_edges_map },
|
unsafe { __lafl_edges_map },
|
||||||
unsafe { __lafl_max_edges_size as usize },
|
unsafe { __lafl_max_edges_size as usize },
|
||||||
)));
|
)));
|
||||||
let edges_history_map = create_history_map::<u8>(MAP_SIZE);
|
let edges_feedback = MaxMapTrackerFeedback::new(edges_observer.clone(), MAP_SIZE);
|
||||||
let edges_feedback = MaxMapFeedback::new(edges_observer.clone(), edges_history_map);
|
|
||||||
|
|
||||||
let executor = InMemoryExecutor::new(harness);
|
let executor = InMemoryExecutor::new(harness);
|
||||||
let mut state = StdState::new(corpus, executor);
|
let mut state = StdState::new(corpus, executor);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user