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)?;
|
||||
}
|
||||
|
||||
if fitness >= 25 {
|
||||
if fitness > 0 {
|
||||
let testcase: Rc<RefCell<_>> = Testcase::new(input).into();
|
||||
for feedback in self.feedbacks_mut() {
|
||||
feedback.append_metadata(testcase.clone())?;
|
||||
|
@ -6,7 +6,7 @@ use core::cell::RefCell;
|
||||
use core::marker::PhantomData;
|
||||
use num::Integer;
|
||||
|
||||
use crate::corpus::Testcase;
|
||||
use crate::corpus::{Testcase, TestcaseMetadata};
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::MapObserver;
|
||||
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
|
||||
pub struct MapFeedback<T, R, O>
|
||||
where
|
||||
@ -102,26 +112,40 @@ where
|
||||
fn is_interesting(&mut self, _input: &I) -> Result<u32, AflError> {
|
||||
let mut interesting = 0;
|
||||
|
||||
// TODO: impl. correctly, optimize
|
||||
for (history, map) in self
|
||||
.history_map
|
||||
.borrow_mut()
|
||||
.iter_mut()
|
||||
.zip(self.map_observer.borrow().map().iter())
|
||||
{
|
||||
let reduced = R::reduce(*history, *map);
|
||||
if *history != reduced {
|
||||
*history = reduced;
|
||||
interesting += 25;
|
||||
if interesting >= 250 {
|
||||
return Ok(255);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
where
|
||||
T: Integer + Copy + 'static,
|
||||
@ -130,7 +154,10 @@ where
|
||||
{
|
||||
/// Create new MapFeedback using a map observer, and a map.
|
||||
/// 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 {
|
||||
map_observer: map_observer,
|
||||
history_map: history_map,
|
||||
@ -139,15 +166,126 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a usable history map of the given size
|
||||
pub fn create_history_map<T>(map_size: usize) -> Rc<RefCell<Vec<T>>>
|
||||
pub struct MapNoveltiesMetadata {
|
||||
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
|
||||
T: Default + Clone,
|
||||
T: Integer + Copy + 'static,
|
||||
R: Reducer<T>,
|
||||
O: MapObserver<T>,
|
||||
{
|
||||
/// Contains information about untouched entries
|
||||
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,
|
||||
{
|
||||
Rc::new(RefCell::new(vec![T::default(); map_size]))
|
||||
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 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 {
|
||||
fn set_seed(&mut self, seed: u64) {
|
||||
self.rand_seed = seed;
|
||||
self.rand_seed = seed ^ 0x1234567890abcdef;
|
||||
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")]
|
||||
pub fn current_milliseconds() -> u64 {
|
||||
SystemTime::now()
|
||||
|
@ -8,7 +8,7 @@ use afl::engines::{generate_initial_inputs, Engine, State, StdEngine, StdState};
|
||||
use afl::events::LoggerEventManager;
|
||||
use afl::executors::inmemory::InMemoryExecutor;
|
||||
use afl::executors::{Executor, ExitKind};
|
||||
use afl::feedbacks::{create_history_map, MaxMapFeedback};
|
||||
use afl::feedbacks::MaxMapTrackerFeedback;
|
||||
use afl::generators::RandPrintablesGenerator;
|
||||
use afl::mutators::scheduled::HavocBytesMutator;
|
||||
use afl::observers::StdMapObserver;
|
||||
@ -39,15 +39,14 @@ pub extern "C" fn afl_libfuzzer_main() {
|
||||
let mut rand = StdRand::new(0);
|
||||
|
||||
let corpus = InMemoryCorpus::new();
|
||||
let mut generator = RandPrintablesGenerator::new(1);
|
||||
let mut generator = RandPrintablesGenerator::new(32);
|
||||
let mut events = LoggerEventManager::new(stderr());
|
||||
|
||||
let edges_observer = Rc::new(RefCell::new(StdMapObserver::new_from_ptr(
|
||||
unsafe { __lafl_edges_map },
|
||||
unsafe { __lafl_max_edges_size as usize },
|
||||
)));
|
||||
let edges_history_map = create_history_map::<u8>(MAP_SIZE);
|
||||
let edges_feedback = MaxMapFeedback::new(edges_observer.clone(), edges_history_map);
|
||||
let edges_feedback = MaxMapTrackerFeedback::new(edges_observer.clone(), MAP_SIZE);
|
||||
|
||||
let executor = InMemoryExecutor::new(harness);
|
||||
let mut state = StdState::new(corpus, executor);
|
||||
|
Loading…
x
Reference in New Issue
Block a user