Remove MapObserver dependency from observer-dependent stages and schedulers in favour of generic hashing (#2851)
* Introdue SimpleHash separate from MapObserver * Move to Hash for hashing * Fix docs, remove even more restrictions * fix libafl_targets * fix fuzzer * Remove broken and unnecessary derive * Remove unnecessary trait restriction * Remove unnecessary import * Add changes to MIGRATION.md * Remove more unnecessary imports
This commit is contained in:
parent
15aa498d5e
commit
93c5adde4d
@ -16,6 +16,8 @@
|
|||||||
- For the structs/traits that used to use `UsesState`, we bring back the generic for the state.
|
- For the structs/traits that used to use `UsesState`, we bring back the generic for the state.
|
||||||
- For `UsesState`, you can access to the input type through `HasCorpus` and `Corpus` traits
|
- For `UsesState`, you can access to the input type through `HasCorpus` and `Corpus` traits
|
||||||
- The `State` trait is now private in favour of individual and more specific traits
|
- The `State` trait is now private in favour of individual and more specific traits
|
||||||
|
- Restrictions from certain schedulers and stages that required their inner observer to implement `MapObserver` have been lifted in favor of requiring `Hash`
|
||||||
|
- Related: removed `hash_simple` from `MapObserver`
|
||||||
|
|
||||||
# 0.14.0 -> 0.14.1
|
# 0.14.0 -> 0.14.1
|
||||||
- Removed `with_observers` from `Executor` trait.
|
- Removed `with_observers` from `Executor` trait.
|
||||||
|
@ -39,7 +39,7 @@ pub fn main() -> Result<(), Error> {
|
|||||||
#[allow(static_mut_refs)] // only a problem in nightly
|
#[allow(static_mut_refs)] // only a problem in nightly
|
||||||
let observer = unsafe { StdMapObserver::from_mut_ptr("signals", SIGNALS_PTR, SIGNALS.len()) };
|
let observer = unsafe { StdMapObserver::from_mut_ptr("signals", SIGNALS_PTR, SIGNALS.len()) };
|
||||||
|
|
||||||
let factory = MapEqualityFactory::new(&observer);
|
let factory = ObserverEqualityFactory::new(&observer);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
let mut feedback = MaxMapFeedback::new(&observer);
|
let mut feedback = MaxMapFeedback::new(&observer);
|
||||||
|
@ -8,7 +8,6 @@ use core::{
|
|||||||
ptr::NonNull,
|
ptr::NonNull,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ahash::RandomState;
|
|
||||||
use libafl_bolts::{ownedref::OwnedMutSizedSlice, HasLen, Named};
|
use libafl_bolts::{ownedref::OwnedMutSizedSlice, HasLen, Named};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
@ -111,11 +110,6 @@ where
|
|||||||
self.len()
|
self.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
RandomState::with_seeds(0, 0, 0, 0).hash_one(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset the map
|
/// Reset the map
|
||||||
#[inline]
|
#[inline]
|
||||||
fn reset_map(&mut self) -> Result<(), Error> {
|
fn reset_map(&mut self) -> Result<(), Error> {
|
||||||
|
@ -221,11 +221,6 @@ where
|
|||||||
self.base.reset_map()
|
self.base.reset_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
self.base.hash_simple()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_vec(&self) -> Vec<u8> {
|
fn to_vec(&self) -> Vec<u8> {
|
||||||
self.base.to_vec()
|
self.base.to_vec()
|
||||||
}
|
}
|
||||||
@ -443,10 +438,6 @@ where
|
|||||||
self.base.reset_map()
|
self.base.reset_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
self.base.hash_simple()
|
|
||||||
}
|
|
||||||
fn to_vec(&self) -> Vec<u8> {
|
fn to_vec(&self) -> Vec<u8> {
|
||||||
self.base.to_vec()
|
self.base.to_vec()
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ use core::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ahash::RandomState;
|
|
||||||
use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut, HasLen, Named, Truncate};
|
use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut, HasLen, Named, Truncate};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
@ -350,7 +349,7 @@ pub mod macros {
|
|||||||
///
|
///
|
||||||
/// TODO: enforce `iter() -> AssociatedTypeIter` when generic associated types stabilize
|
/// TODO: enforce `iter() -> AssociatedTypeIter` when generic associated types stabilize
|
||||||
pub trait MapObserver:
|
pub trait MapObserver:
|
||||||
HasLen + Named + Serialize + DeserializeOwned + AsRef<Self> + AsMut<Self> + Hash
|
HasLen + Named + Serialize + DeserializeOwned + AsRef<Self> + AsMut<Self>
|
||||||
// where
|
// where
|
||||||
// for<'it> &'it Self: IntoIterator<Item = &'it Self::Entry>
|
// for<'it> &'it Self: IntoIterator<Item = &'it Self::Entry>
|
||||||
{
|
{
|
||||||
@ -369,9 +368,6 @@ pub trait MapObserver:
|
|||||||
/// Count the set bytes in the map
|
/// Count the set bytes in the map
|
||||||
fn count_bytes(&self) -> u64;
|
fn count_bytes(&self) -> u64;
|
||||||
|
|
||||||
/// Compute the hash of the map without needing to provide a hasher
|
|
||||||
fn hash_simple(&self) -> u64;
|
|
||||||
|
|
||||||
/// Get the initial value for `reset()`
|
/// Get the initial value for `reset()`
|
||||||
fn initial(&self) -> Self::Entry;
|
fn initial(&self) -> Self::Entry;
|
||||||
|
|
||||||
@ -526,11 +522,6 @@ where
|
|||||||
self.as_slice().len()
|
self.as_slice().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
RandomState::with_seeds(0, 0, 0, 0).hash_one(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn initial(&self) -> T {
|
fn initial(&self) -> T {
|
||||||
self.initial
|
self.initial
|
||||||
|
@ -8,7 +8,6 @@ use core::{
|
|||||||
slice::{Iter, IterMut},
|
slice::{Iter, IterMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ahash::RandomState;
|
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
ownedref::OwnedMutSlice, AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named,
|
ownedref::OwnedMutSlice, AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named,
|
||||||
};
|
};
|
||||||
@ -124,11 +123,6 @@ where
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
RandomState::with_seeds(0, 0, 0, 0).hash_one(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset_map(&mut self) -> Result<(), Error> {
|
fn reset_map(&mut self) -> Result<(), Error> {
|
||||||
let initial = self.initial();
|
let initial = self.initial();
|
||||||
for map in &mut self.maps {
|
for map in &mut self.maps {
|
||||||
|
@ -7,7 +7,6 @@ use core::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ahash::RandomState;
|
|
||||||
use libafl_bolts::{AsSlice, AsSliceMut, HasLen, Named};
|
use libafl_bolts::{AsSlice, AsSliceMut, HasLen, Named};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
@ -105,11 +104,6 @@ where
|
|||||||
self.as_slice().len()
|
self.as_slice().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
RandomState::with_seeds(0, 0, 0, 0).hash_one(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn initial(&self) -> T {
|
fn initial(&self) -> T {
|
||||||
self.initial
|
self.initial
|
||||||
|
@ -7,7 +7,6 @@ use core::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ahash::RandomState;
|
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
ownedref::{OwnedMutPtr, OwnedMutSlice},
|
ownedref::{OwnedMutPtr, OwnedMutSlice},
|
||||||
AsSlice, AsSliceMut, HasLen, Named,
|
AsSlice, AsSliceMut, HasLen, Named,
|
||||||
@ -113,11 +112,6 @@ where
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
RandomState::with_seeds(0, 0, 0, 0).hash_one(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset the map
|
/// Reset the map
|
||||||
#[inline]
|
#[inline]
|
||||||
fn reset_map(&mut self) -> Result<(), Error> {
|
fn reset_map(&mut self) -> Result<(), Error> {
|
||||||
|
@ -12,9 +12,8 @@ use ahash::RandomState;
|
|||||||
use libafl_bolts::{ownedref::OwnedRef, AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named};
|
use libafl_bolts::{ownedref::OwnedRef, AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
use super::Observer;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
observers::{MapObserver, ObserverWithHashField},
|
observers::{MapObserver, Observer, ObserverWithHashField},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -289,6 +288,7 @@ impl<T> AsMut<Self> for RefCellValueObserver<'_, T> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, A> MapObserver for RefCellValueObserver<'_, A>
|
impl<T, A> MapObserver for RefCellValueObserver<'_, A>
|
||||||
where
|
where
|
||||||
T: PartialEq + Copy + Hash + Default + DeserializeOwned + Serialize + Debug,
|
T: PartialEq + Copy + Hash + Default + DeserializeOwned + Serialize + Debug,
|
||||||
@ -308,12 +308,6 @@ where
|
|||||||
self.get_ref_mut()[idx] = val;
|
self.get_ref_mut()[idx] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Panics if the contained value is already mutably borrowed (calls
|
|
||||||
/// [`RefCell::borrow`]).
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
RandomState::with_seeds(0, 0, 0, 0).hash_one(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Panics if the contained value is already mutably borrowed (calls
|
/// Panics if the contained value is already mutably borrowed (calls
|
||||||
/// [`RefCell::borrow`]).
|
/// [`RefCell::borrow`]).
|
||||||
fn usable_count(&self) -> usize {
|
fn usable_count(&self) -> usize {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Schedule the access to the Corpus.
|
//! Schedule the access to the Corpus.
|
||||||
|
|
||||||
use alloc::{borrow::ToOwned, string::ToString};
|
use alloc::{borrow::ToOwned, string::ToString};
|
||||||
use core::marker::PhantomData;
|
use core::{hash::Hash, marker::PhantomData};
|
||||||
|
|
||||||
pub mod testcase_score;
|
pub mod testcase_score;
|
||||||
pub use testcase_score::{LenTimeMulTestcaseScore, TestcaseScore};
|
pub use testcase_score::{LenTimeMulTestcaseScore, TestcaseScore};
|
||||||
@ -28,6 +28,7 @@ pub use weighted::{StdWeightedScheduler, WeightedScheduler};
|
|||||||
|
|
||||||
pub mod tuneable;
|
pub mod tuneable;
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
|
generic_hash_std,
|
||||||
rands::Rand,
|
rands::Rand,
|
||||||
tuples::{Handle, MatchName, MatchNameRef},
|
tuples::{Handle, MatchName, MatchNameRef},
|
||||||
};
|
};
|
||||||
@ -35,7 +36,6 @@ pub use tuneable::*;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase},
|
corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase},
|
||||||
observers::MapObserver,
|
|
||||||
random_corpus_id,
|
random_corpus_id,
|
||||||
state::{HasCorpus, HasRand},
|
state::{HasCorpus, HasRand},
|
||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
@ -107,17 +107,17 @@ pub fn on_evaluation_metadata_default<CS, O, OT, S>(
|
|||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
CS: AflScheduler,
|
CS: AflScheduler,
|
||||||
CS::MapObserverRef: AsRef<O>,
|
CS::ObserverRef: AsRef<O>,
|
||||||
S: HasMetadata,
|
S: HasMetadata,
|
||||||
O: MapObserver,
|
O: Hash,
|
||||||
OT: MatchName,
|
OT: MatchName,
|
||||||
{
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.get(scheduler.map_observer_handle())
|
.get(scheduler.observer_handle())
|
||||||
.ok_or_else(|| Error::key_not_found("MapObserver not found".to_string()))?
|
.ok_or_else(|| Error::key_not_found("Observer not found".to_string()))?
|
||||||
.as_ref();
|
.as_ref();
|
||||||
|
|
||||||
let mut hash = observer.hash_simple() as usize;
|
let mut hash = generic_hash_std(observer) as usize;
|
||||||
|
|
||||||
let psmeta = state.metadata_mut::<SchedulerMetadata>()?;
|
let psmeta = state.metadata_mut::<SchedulerMetadata>()?;
|
||||||
|
|
||||||
@ -153,8 +153,8 @@ where
|
|||||||
|
|
||||||
/// Defines the common metadata operations for the AFL-style schedulers
|
/// Defines the common metadata operations for the AFL-style schedulers
|
||||||
pub trait AflScheduler {
|
pub trait AflScheduler {
|
||||||
/// The type of [`MapObserver`] that this scheduler will use as reference
|
/// The type of [`crate::observers::Observer`] that this scheduler will use as reference
|
||||||
type MapObserverRef;
|
type ObserverRef;
|
||||||
|
|
||||||
/// Return the last hash
|
/// Return the last hash
|
||||||
fn last_hash(&self) -> usize;
|
fn last_hash(&self) -> usize;
|
||||||
@ -162,8 +162,8 @@ pub trait AflScheduler {
|
|||||||
/// Set the last hash
|
/// Set the last hash
|
||||||
fn set_last_hash(&mut self, value: usize);
|
fn set_last_hash(&mut self, value: usize);
|
||||||
|
|
||||||
/// Get the observer map observer name
|
/// Get the observer handle
|
||||||
fn map_observer_handle(&self) -> &Handle<Self::MapObserverRef>;
|
fn observer_handle(&self) -> &Handle<Self::ObserverRef>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for Schedulers which track queue cycles
|
/// Trait for Schedulers which track queue cycles
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! The queue corpus scheduler for power schedules.
|
//! The queue corpus scheduler for power schedules.
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{marker::PhantomData, time::Duration};
|
use core::{hash::Hash, marker::PhantomData, time::Duration};
|
||||||
|
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
tuples::{Handle, Handled, MatchName},
|
tuples::{Handle, Handled, MatchName},
|
||||||
@ -11,7 +11,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
|
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
|
||||||
observers::MapObserver,
|
|
||||||
schedulers::{
|
schedulers::{
|
||||||
on_add_metadata_default, on_evaluation_metadata_default, on_next_metadata_default,
|
on_add_metadata_default, on_evaluation_metadata_default, on_next_metadata_default,
|
||||||
AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler,
|
AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler,
|
||||||
@ -276,7 +275,7 @@ pub enum BaseSchedule {
|
|||||||
pub struct PowerQueueScheduler<C, O> {
|
pub struct PowerQueueScheduler<C, O> {
|
||||||
queue_cycles: u64,
|
queue_cycles: u64,
|
||||||
strat: PowerSchedule,
|
strat: PowerSchedule,
|
||||||
map_observer_handle: Handle<C>,
|
observer_handle: Handle<C>,
|
||||||
last_hash: usize,
|
last_hash: usize,
|
||||||
phantom: PhantomData<O>,
|
phantom: PhantomData<O>,
|
||||||
}
|
}
|
||||||
@ -304,7 +303,7 @@ impl<C, I, O, S> RemovableScheduler<I, S> for PowerQueueScheduler<C, O> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<C, O> AflScheduler for PowerQueueScheduler<C, O> {
|
impl<C, O> AflScheduler for PowerQueueScheduler<C, O> {
|
||||||
type MapObserverRef = C;
|
type ObserverRef = C;
|
||||||
|
|
||||||
fn last_hash(&self) -> usize {
|
fn last_hash(&self) -> usize {
|
||||||
self.last_hash
|
self.last_hash
|
||||||
@ -314,8 +313,8 @@ impl<C, O> AflScheduler for PowerQueueScheduler<C, O> {
|
|||||||
self.last_hash = hash;
|
self.last_hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_observer_handle(&self) -> &Handle<C> {
|
fn observer_handle(&self) -> &Handle<C> {
|
||||||
&self.map_observer_handle
|
&self.observer_handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +327,7 @@ impl<C, O> HasQueueCycles for PowerQueueScheduler<C, O> {
|
|||||||
impl<C, I, O, S> Scheduler<I, S> for PowerQueueScheduler<C, O>
|
impl<C, I, O, S> Scheduler<I, S> for PowerQueueScheduler<C, O>
|
||||||
where
|
where
|
||||||
S: HasCorpus + HasMetadata + HasTestcase,
|
S: HasCorpus + HasMetadata + HasTestcase,
|
||||||
O: MapObserver,
|
O: Hash,
|
||||||
C: AsRef<O>,
|
C: AsRef<O>,
|
||||||
{
|
{
|
||||||
/// Called when a [`Testcase`] is added to the corpus
|
/// Called when a [`Testcase`] is added to the corpus
|
||||||
@ -383,12 +382,12 @@ where
|
|||||||
|
|
||||||
impl<C, O> PowerQueueScheduler<C, O>
|
impl<C, O> PowerQueueScheduler<C, O>
|
||||||
where
|
where
|
||||||
O: MapObserver,
|
O: Hash,
|
||||||
C: AsRef<O> + Named,
|
C: AsRef<O> + Named,
|
||||||
{
|
{
|
||||||
/// Create a new [`PowerQueueScheduler`]
|
/// Create a new [`PowerQueueScheduler`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new<S>(state: &mut S, map_observer: &C, strat: PowerSchedule) -> Self
|
pub fn new<S>(state: &mut S, observer: &C, strat: PowerSchedule) -> Self
|
||||||
where
|
where
|
||||||
S: HasMetadata,
|
S: HasMetadata,
|
||||||
{
|
{
|
||||||
@ -398,7 +397,7 @@ where
|
|||||||
PowerQueueScheduler {
|
PowerQueueScheduler {
|
||||||
queue_cycles: 0,
|
queue_cycles: 0,
|
||||||
strat,
|
strat,
|
||||||
map_observer_handle: map_observer.handle(),
|
observer_handle: observer.handle(),
|
||||||
last_hash: 0,
|
last_hash: 0,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! The queue corpus scheduler with weighted queue item selection [from AFL++](https://github.com/AFLplusplus/AFLplusplus/blob/1d4f1e48797c064ee71441ba555b29fc3f467983/src/afl-fuzz-queue.c#L32).
|
//! The queue corpus scheduler with weighted queue item selection [from AFL++](https://github.com/AFLplusplus/AFLplusplus/blob/1d4f1e48797c064ee71441ba555b29fc3f467983/src/afl-fuzz-queue.c#L32).
|
||||||
//! This queue corpus scheduler needs calibration stage.
|
//! This queue corpus scheduler needs calibration stage.
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::{hash::Hash, marker::PhantomData};
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
@ -13,14 +13,12 @@ use libafl_bolts::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::powersched::PowerSchedule;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
|
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
|
||||||
observers::MapObserver,
|
|
||||||
random_corpus_id,
|
random_corpus_id,
|
||||||
schedulers::{
|
schedulers::{
|
||||||
on_add_metadata_default, on_evaluation_metadata_default, on_next_metadata_default,
|
on_add_metadata_default, on_evaluation_metadata_default, on_next_metadata_default,
|
||||||
powersched::{BaseSchedule, SchedulerMetadata},
|
powersched::{BaseSchedule, PowerSchedule, SchedulerMetadata},
|
||||||
testcase_score::{CorpusWeightTestcaseScore, TestcaseScore},
|
testcase_score::{CorpusWeightTestcaseScore, TestcaseScore},
|
||||||
AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler,
|
AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler,
|
||||||
},
|
},
|
||||||
@ -101,7 +99,7 @@ libafl_bolts::impl_serdeany!(WeightedScheduleMetadata);
|
|||||||
pub struct WeightedScheduler<C, F, O> {
|
pub struct WeightedScheduler<C, F, O> {
|
||||||
table_invalidated: bool,
|
table_invalidated: bool,
|
||||||
strat: Option<PowerSchedule>,
|
strat: Option<PowerSchedule>,
|
||||||
map_observer_handle: Handle<C>,
|
observer_handle: Handle<C>,
|
||||||
last_hash: usize,
|
last_hash: usize,
|
||||||
queue_cycles: u64,
|
queue_cycles: u64,
|
||||||
phantom: PhantomData<(F, O)>,
|
phantom: PhantomData<(F, O)>,
|
||||||
@ -115,16 +113,16 @@ where
|
|||||||
{
|
{
|
||||||
/// Create a new [`WeightedScheduler`] without any power schedule
|
/// Create a new [`WeightedScheduler`] without any power schedule
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new<S>(state: &mut S, map_observer: &C) -> Self
|
pub fn new<S>(state: &mut S, observer: &C) -> Self
|
||||||
where
|
where
|
||||||
S: HasMetadata,
|
S: HasMetadata,
|
||||||
{
|
{
|
||||||
Self::with_schedule(state, map_observer, None)
|
Self::with_schedule(state, observer, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new [`WeightedScheduler`]
|
/// Create a new [`WeightedScheduler`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_schedule<S>(state: &mut S, map_observer: &C, strat: Option<PowerSchedule>) -> Self
|
pub fn with_schedule<S>(state: &mut S, observer: &C, strat: Option<PowerSchedule>) -> Self
|
||||||
where
|
where
|
||||||
S: HasMetadata,
|
S: HasMetadata,
|
||||||
{
|
{
|
||||||
@ -133,7 +131,7 @@ where
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
strat,
|
strat,
|
||||||
map_observer_handle: map_observer.handle(),
|
observer_handle: observer.handle(),
|
||||||
last_hash: 0,
|
last_hash: 0,
|
||||||
queue_cycles: 0,
|
queue_cycles: 0,
|
||||||
table_invalidated: true,
|
table_invalidated: true,
|
||||||
@ -284,7 +282,7 @@ impl<C, F, I, O, S> RemovableScheduler<I, S> for WeightedScheduler<C, F, O> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<C, F, O> AflScheduler for WeightedScheduler<C, F, O> {
|
impl<C, F, O> AflScheduler for WeightedScheduler<C, F, O> {
|
||||||
type MapObserverRef = C;
|
type ObserverRef = C;
|
||||||
|
|
||||||
fn last_hash(&self) -> usize {
|
fn last_hash(&self) -> usize {
|
||||||
self.last_hash
|
self.last_hash
|
||||||
@ -294,8 +292,8 @@ impl<C, F, O> AflScheduler for WeightedScheduler<C, F, O> {
|
|||||||
self.last_hash = hash;
|
self.last_hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_observer_handle(&self) -> &Handle<C> {
|
fn observer_handle(&self) -> &Handle<C> {
|
||||||
&self.map_observer_handle
|
&self.observer_handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +307,7 @@ impl<C, F, O, S> Scheduler<<S::Corpus as Corpus>::Input, S> for WeightedSchedule
|
|||||||
where
|
where
|
||||||
C: AsRef<O> + Named,
|
C: AsRef<O> + Named,
|
||||||
F: TestcaseScore<S>,
|
F: TestcaseScore<S>,
|
||||||
O: MapObserver,
|
O: Hash,
|
||||||
S: HasCorpus + HasMetadata + HasRand + HasTestcase,
|
S: HasCorpus + HasMetadata + HasRand + HasTestcase,
|
||||||
{
|
{
|
||||||
/// Called when a [`Testcase`] is added to the corpus
|
/// Called when a [`Testcase`] is added to the corpus
|
||||||
|
@ -4,9 +4,10 @@ use alloc::{
|
|||||||
collections::binary_heap::BinaryHeap,
|
collections::binary_heap::BinaryHeap,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::{cmp::Ordering, fmt::Debug, marker::PhantomData, ops::Range};
|
use core::{cmp::Ordering, fmt::Debug, hash::Hash, marker::PhantomData, ops::Range};
|
||||||
|
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
|
generic_hash_std,
|
||||||
rands::Rand,
|
rands::Rand,
|
||||||
tuples::{Handle, Handled},
|
tuples::{Handle, Handled},
|
||||||
Named,
|
Named,
|
||||||
@ -20,7 +21,7 @@ use crate::{
|
|||||||
inputs::{HasMutatorBytes, HasMutatorResizableBytes},
|
inputs::{HasMutatorBytes, HasMutatorResizableBytes},
|
||||||
mutators::mutations::buffer_copy,
|
mutators::mutations::buffer_copy,
|
||||||
nonzero,
|
nonzero,
|
||||||
observers::{MapObserver, ObserversTuple},
|
observers::ObserversTuple,
|
||||||
stages::{RetryCountRestartHelper, Stage},
|
stages::{RetryCountRestartHelper, Stage},
|
||||||
state::{HasCorpus, HasCurrentTestcase, HasRand},
|
state::{HasCorpus, HasCurrentTestcase, HasRand},
|
||||||
Error, HasMetadata, HasNamedMetadata,
|
Error, HasMetadata, HasNamedMetadata,
|
||||||
@ -81,7 +82,7 @@ where
|
|||||||
S: HasCorpus + HasMetadata + HasRand + HasNamedMetadata + HasCurrentCorpusId,
|
S: HasCorpus + HasMetadata + HasRand + HasNamedMetadata + HasCurrentCorpusId,
|
||||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||||
<S::Corpus as Corpus>::Input: HasMutatorResizableBytes + Clone,
|
<S::Corpus as Corpus>::Input: HasMutatorResizableBytes + Clone,
|
||||||
O: MapObserver,
|
O: Hash,
|
||||||
C: AsRef<O> + Named,
|
C: AsRef<O> + Named,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -152,7 +153,7 @@ libafl_bolts::impl_serdeany!(TaintMetadata);
|
|||||||
impl<C, E, EM, O, S, Z> ColorizationStage<C, E, EM, O, S, Z>
|
impl<C, E, EM, O, S, Z> ColorizationStage<C, E, EM, O, S, Z>
|
||||||
where
|
where
|
||||||
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
|
EM: EventFirer<<S::Corpus as Corpus>::Input, S>,
|
||||||
O: MapObserver,
|
O: Hash,
|
||||||
C: AsRef<O> + Named,
|
C: AsRef<O> + Named,
|
||||||
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
E: HasObservers + Executor<EM, <S::Corpus as Corpus>::Input, S, Z>,
|
||||||
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
E::Observers: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||||
@ -317,7 +318,7 @@ where
|
|||||||
let observers = executor.observers();
|
let observers = executor.observers();
|
||||||
let observer = observers[observer_handle].as_ref();
|
let observer = observers[observer_handle].as_ref();
|
||||||
|
|
||||||
let hash = observer.hash_simple() as usize;
|
let hash = generic_hash_std(observer) as usize;
|
||||||
|
|
||||||
executor
|
executor
|
||||||
.observers_mut()
|
.observers_mut()
|
||||||
|
@ -37,7 +37,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
pub use sync::*;
|
pub use sync::*;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use time_tracker::TimeTrackingStageWrapper;
|
pub use time_tracker::TimeTrackingStageWrapper;
|
||||||
pub use tmin::{MapEqualityFactory, MapEqualityFeedback, StdTMinMutationalStage};
|
pub use tmin::{ObserverEqualityFactory, ObserverEqualityFeedback, StdTMinMutationalStage};
|
||||||
pub use tracing::{ShadowTracingStage, TracingStage};
|
pub use tracing::{ShadowTracingStage, TracingStage};
|
||||||
pub use tuneable::*;
|
pub use tuneable::*;
|
||||||
use tuple_list::NonEmptyTuple;
|
use tuple_list::NonEmptyTuple;
|
||||||
|
@ -8,6 +8,7 @@ use core::{borrow::BorrowMut, fmt::Debug, hash::Hash, marker::PhantomData};
|
|||||||
|
|
||||||
use ahash::RandomState;
|
use ahash::RandomState;
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
|
generic_hash_std,
|
||||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||||
HasLen, Named,
|
HasLen, Named,
|
||||||
};
|
};
|
||||||
@ -25,7 +26,7 @@ use crate::{
|
|||||||
inputs::Input,
|
inputs::Input,
|
||||||
mark_feature_time,
|
mark_feature_time,
|
||||||
mutators::{MutationResult, Mutator},
|
mutators::{MutationResult, Mutator},
|
||||||
observers::{MapObserver, ObserversTuple},
|
observers::ObserversTuple,
|
||||||
schedulers::RemovableScheduler,
|
schedulers::RemovableScheduler,
|
||||||
stages::{
|
stages::{
|
||||||
mutational::{MutatedTransform, MutatedTransformPost},
|
mutational::{MutatedTransform, MutatedTransformPost},
|
||||||
@ -329,12 +330,12 @@ impl<E, EM, F, FF, M, S, Z> StdTMinMutationalStage<E, EM, F, FF, M, S, Z> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A feedback which checks if the hash of the currently observed map is equal to the original hash
|
/// A feedback which checks if the hash of the current observed value is equal to the original hash
|
||||||
/// provided
|
/// provided
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MapEqualityFeedback<C, M, S> {
|
pub struct ObserverEqualityFeedback<C, M, S> {
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
map_ref: Handle<C>,
|
observer_handle: Handle<C>,
|
||||||
orig_hash: u64,
|
orig_hash: u64,
|
||||||
#[cfg(feature = "track_hit_feedbacks")]
|
#[cfg(feature = "track_hit_feedbacks")]
|
||||||
// The previous run's result of `Self::is_interesting`
|
// The previous run's result of `Self::is_interesting`
|
||||||
@ -342,25 +343,25 @@ pub struct MapEqualityFeedback<C, M, S> {
|
|||||||
phantom: PhantomData<(M, S)>,
|
phantom: PhantomData<(M, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S> Named for MapEqualityFeedback<C, M, S> {
|
impl<C, M, S> Named for ObserverEqualityFeedback<C, M, S> {
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S> HasObserverHandle for MapEqualityFeedback<C, M, S> {
|
impl<C, M, S> HasObserverHandle for ObserverEqualityFeedback<C, M, S> {
|
||||||
type Observer = C;
|
type Observer = C;
|
||||||
|
|
||||||
fn observer_handle(&self) -> &Handle<Self::Observer> {
|
fn observer_handle(&self) -> &Handle<Self::Observer> {
|
||||||
&self.map_ref
|
&self.observer_handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S> StateInitializer<S> for MapEqualityFeedback<C, M, S> {}
|
impl<C, M, S> StateInitializer<S> for ObserverEqualityFeedback<C, M, S> {}
|
||||||
|
|
||||||
impl<C, EM, I, M, OT, S> Feedback<EM, I, OT, S> for MapEqualityFeedback<C, M, S>
|
impl<C, EM, I, M, OT, S> Feedback<EM, I, OT, S> for ObserverEqualityFeedback<C, M, S>
|
||||||
where
|
where
|
||||||
M: MapObserver,
|
M: Hash,
|
||||||
C: AsRef<M>,
|
C: AsRef<M>,
|
||||||
OT: MatchName,
|
OT: MatchName,
|
||||||
{
|
{
|
||||||
@ -375,7 +376,7 @@ where
|
|||||||
let obs = observers
|
let obs = observers
|
||||||
.get(self.observer_handle())
|
.get(self.observer_handle())
|
||||||
.expect("Should have been provided valid observer name.");
|
.expect("Should have been provided valid observer name.");
|
||||||
let res = obs.as_ref().hash_simple() == self.orig_hash;
|
let res = generic_hash_std(obs.as_ref()) == self.orig_hash;
|
||||||
#[cfg(feature = "track_hit_feedbacks")]
|
#[cfg(feature = "track_hit_feedbacks")]
|
||||||
{
|
{
|
||||||
self.last_result = Some(res);
|
self.last_result = Some(res);
|
||||||
@ -388,50 +389,51 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A feedback factory for ensuring that the maps for minimized inputs are the same
|
/// A feedback factory for ensuring that the values of the observers for minimized inputs are the same
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MapEqualityFactory<C, M, S> {
|
pub struct ObserverEqualityFactory<C, M, S> {
|
||||||
map_ref: Handle<C>,
|
observer_handle: Handle<C>,
|
||||||
phantom: PhantomData<(C, M, S)>,
|
phantom: PhantomData<(C, M, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S> MapEqualityFactory<C, M, S>
|
impl<C, M, S> ObserverEqualityFactory<C, M, S>
|
||||||
where
|
where
|
||||||
M: MapObserver,
|
M: Hash,
|
||||||
C: AsRef<M> + Handled,
|
C: AsRef<M> + Handled,
|
||||||
{
|
{
|
||||||
/// Creates a new map equality feedback for the given observer
|
/// Creates a new observer equality feedback for the given observer
|
||||||
pub fn new(obs: &C) -> Self {
|
pub fn new(obs: &C) -> Self {
|
||||||
Self {
|
Self {
|
||||||
map_ref: obs.handle(),
|
observer_handle: obs.handle(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S> HasObserverHandle for MapEqualityFactory<C, M, S> {
|
impl<C, M, S> HasObserverHandle for ObserverEqualityFactory<C, M, S> {
|
||||||
type Observer = C;
|
type Observer = C;
|
||||||
|
|
||||||
fn observer_handle(&self) -> &Handle<C> {
|
fn observer_handle(&self) -> &Handle<C> {
|
||||||
&self.map_ref
|
&self.observer_handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, OT, S> FeedbackFactory<MapEqualityFeedback<C, M, S>, OT> for MapEqualityFactory<C, M, S>
|
impl<C, M, OT, S> FeedbackFactory<ObserverEqualityFeedback<C, M, S>, OT>
|
||||||
|
for ObserverEqualityFactory<C, M, S>
|
||||||
where
|
where
|
||||||
M: MapObserver,
|
M: Hash,
|
||||||
C: AsRef<M> + Handled,
|
C: AsRef<M> + Handled,
|
||||||
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
OT: ObserversTuple<<S::Corpus as Corpus>::Input, S>,
|
||||||
S: HasCorpus,
|
S: HasCorpus,
|
||||||
{
|
{
|
||||||
fn create_feedback(&self, observers: &OT) -> MapEqualityFeedback<C, M, S> {
|
fn create_feedback(&self, observers: &OT) -> ObserverEqualityFeedback<C, M, S> {
|
||||||
let obs = observers
|
let obs = observers
|
||||||
.get(self.observer_handle())
|
.get(self.observer_handle())
|
||||||
.expect("Should have been provided valid observer name.");
|
.expect("Should have been provided valid observer name.");
|
||||||
MapEqualityFeedback {
|
ObserverEqualityFeedback {
|
||||||
name: Cow::from("MapEq"),
|
name: Cow::from("ObserverEq"),
|
||||||
map_ref: obs.handle(),
|
observer_handle: obs.handle(),
|
||||||
orig_hash: obs.as_ref().hash_simple(),
|
orig_hash: generic_hash_std(obs.as_ref()),
|
||||||
#[cfg(feature = "track_hit_feedbacks")]
|
#[cfg(feature = "track_hit_feedbacks")]
|
||||||
last_result: None,
|
last_result: None,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
|
@ -83,7 +83,6 @@ mod observers {
|
|||||||
slice::{from_raw_parts, Iter, IterMut},
|
slice::{from_raw_parts, Iter, IterMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ahash::RandomState;
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
observers::{DifferentialObserver, MapObserver, Observer},
|
observers::{DifferentialObserver, MapObserver, Observer},
|
||||||
Error,
|
Error,
|
||||||
@ -230,11 +229,6 @@ mod observers {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn hash_simple(&self) -> u64 {
|
|
||||||
RandomState::with_seeds(0, 0, 0, 0).hash_one(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset_map(&mut self) -> Result<(), Error> {
|
fn reset_map(&mut self) -> Result<(), Error> {
|
||||||
let initial = self.initial();
|
let initial = self.initial();
|
||||||
for map in unsafe { &mut *counter_maps_ptr_mut() } {
|
for map in unsafe { &mut *counter_maps_ptr_mut() } {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user