* libafl: Remove `{update,clear}_hash` from `ObserverWithHashField` These methods aren't used by `NewHashFeedback`, so there's no compelling reason to keep them in the interface. They preclude implementations of `ObserverWithHashField` that calculcate a hash on-the-fly from a value. For example, my use-case is to store the stdout of a process, and use `NewHashFeedback` to only collect inputs that result in new messages on stdout. Both of these methods are pretty suspicious to begin with - why should other code be able to update the internal state of the observer? What are the semantics of `update_hash`? If there are compelling reasons to keep these methods, let's clarify their intent in the documentation. * libafl: Return hash by value from `ObserverWithHashField` This allows implementors of this trait to not store the hash, but rather to compute it on-the-fly. Since `Option<u64>` is `Copy` (and quite small), and this method is called once per execution of the target program, this is likely to have negligible performance impact. * libafl: Implement `ObserverWithHashField` for `ValueObserver` This demonstrates the utility of the previous two commits. Now, `ValueObserver` can be used with `NewHashFeedback`. * Clippy, move to ahasher * Oops :) --------- Co-authored-by: Langston Barrett <langston.barrett@gmail.com>
This commit is contained in:
parent
fdf579bcd5
commit
cc53da85fb
@ -593,6 +593,7 @@ mod apple {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
pub fn set_for_current(_core_id: CoreId) -> Result<(), Error> {
|
pub fn set_for_current(_core_id: CoreId) -> Result<(), Error> {
|
||||||
// This is the best we can do, unlike on intel architecture
|
// This is the best we can do, unlike on intel architecture
|
||||||
// the system does not allow to pin a process/thread to specific cpu.
|
// the system does not allow to pin a process/thread to specific cpu.
|
||||||
|
@ -109,7 +109,7 @@ where
|
|||||||
match observer.hash() {
|
match observer.hash() {
|
||||||
Some(hash) => {
|
Some(hash) => {
|
||||||
let res = backtrace_state
|
let res = backtrace_state
|
||||||
.update_hash_set(*hash)
|
.update_hash_set(hash)
|
||||||
.expect("Failed to update the hash state");
|
.expect("Failed to update the hash state");
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -280,11 +280,7 @@ where
|
|||||||
/// A trait for [`Observer`]`s` with a hash field
|
/// A trait for [`Observer`]`s` with a hash field
|
||||||
pub trait ObserverWithHashField {
|
pub trait ObserverWithHashField {
|
||||||
/// get the value of the hash field
|
/// get the value of the hash field
|
||||||
fn hash(&self) -> &Option<u64>;
|
fn hash(&self) -> Option<u64>;
|
||||||
/// update the hash field with the given value
|
|
||||||
fn update_hash(&mut self, hash: u64);
|
|
||||||
/// clears the current value of the hash and sets it to None
|
|
||||||
fn clear_hash(&mut self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait for [`Observer`]`s` which observe over differential execution.
|
/// A trait for [`Observer`]`s` which observe over differential execution.
|
||||||
|
@ -77,26 +77,26 @@ impl<'a> BacktraceObserver<'a> {
|
|||||||
harness_type,
|
harness_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ObserverWithHashField for BacktraceObserver<'a> {
|
|
||||||
/// Gets the hash value of this observer.
|
|
||||||
#[must_use]
|
|
||||||
fn hash(&self) -> &Option<u64> {
|
|
||||||
self.hash.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the hash value of this observer.
|
/// Updates the hash value of this observer.
|
||||||
fn update_hash(&mut self, hash: u64) {
|
fn update_hash(&mut self, hash: u64) {
|
||||||
*self.hash.as_mut() = Some(hash);
|
*self.hash.as_mut() = Some(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears the current hash value
|
/// Clears the current hash value (sets it to `None`)
|
||||||
fn clear_hash(&mut self) {
|
fn clear_hash(&mut self) {
|
||||||
*self.hash.as_mut() = None;
|
*self.hash.as_mut() = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ObserverWithHashField for BacktraceObserver<'a> {
|
||||||
|
/// Gets the hash value of this observer.
|
||||||
|
#[must_use]
|
||||||
|
fn hash(&self) -> Option<u64> {
|
||||||
|
*self.hash.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, S> Observer<S> for BacktraceObserver<'a>
|
impl<'a, S> Observer<S> for BacktraceObserver<'a>
|
||||||
where
|
where
|
||||||
S: UsesInput,
|
S: UsesInput,
|
||||||
@ -219,23 +219,18 @@ impl AsanBacktraceObserver {
|
|||||||
});
|
});
|
||||||
self.update_hash(hash);
|
self.update_hash(hash);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ObserverWithHashField for AsanBacktraceObserver {
|
|
||||||
/// Gets the hash value of this observer.
|
|
||||||
#[must_use]
|
|
||||||
fn hash(&self) -> &Option<u64> {
|
|
||||||
&self.hash
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the hash value of this observer.
|
/// Updates the hash value of this observer.
|
||||||
fn update_hash(&mut self, hash: u64) {
|
fn update_hash(&mut self, hash: u64) {
|
||||||
self.hash = Some(hash);
|
self.hash = Some(hash);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Clears the current hash value
|
impl ObserverWithHashField for AsanBacktraceObserver {
|
||||||
fn clear_hash(&mut self) {
|
/// Gets the hash value of this observer.
|
||||||
self.hash = None;
|
#[must_use]
|
||||||
|
fn hash(&self) -> Option<u64> {
|
||||||
|
self.hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,14 +4,19 @@ use alloc::{
|
|||||||
boxed::Box,
|
boxed::Box,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
use core::fmt::Debug;
|
use core::{
|
||||||
|
fmt::Debug,
|
||||||
|
hash::{BuildHasher, Hash, Hasher},
|
||||||
|
};
|
||||||
|
|
||||||
|
use ahash::RandomState;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::Observer;
|
use super::Observer;
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::{ownedref::OwnedRef, tuples::Named},
|
bolts::{ownedref::OwnedRef, tuples::Named},
|
||||||
inputs::UsesInput,
|
inputs::UsesInput,
|
||||||
|
observers::ObserverWithHashField,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,3 +93,14 @@ where
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Hash> ObserverWithHashField for ValueObserver<'a, T>
|
||||||
|
where
|
||||||
|
T: Debug + Serialize + serde::de::DeserializeOwned,
|
||||||
|
{
|
||||||
|
fn hash(&self) -> Option<u64> {
|
||||||
|
let mut s = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
|
||||||
|
Hash::hash(self.value.as_ref(), &mut s);
|
||||||
|
Some(s.finish())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user