Add RefCellValueObserver (#1363)
* add RefCellValueObserver * appease the clippy gods * Update libafl/src/observers/value.rs Co-authored-by: Langston Barrett <langston.barrett@gmail.com> --------- Co-authored-by: Langston Barrett <langston.barrett@gmail.com>
This commit is contained in:
parent
a95b322b1c
commit
f76331eac7
@ -5,8 +5,10 @@ use alloc::{
|
||||
string::{String, ToString},
|
||||
};
|
||||
use core::{
|
||||
cell::{Ref, RefCell},
|
||||
fmt::Debug,
|
||||
hash::{BuildHasher, Hash, Hasher},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use ahash::RandomState;
|
||||
@ -22,9 +24,8 @@ use crate::{
|
||||
|
||||
/// A simple observer with a single value.
|
||||
///
|
||||
/// The intent is that the value is something with interior mutability (e.g., a
|
||||
/// `RefCell`), which the target could write to even though this observer has a
|
||||
/// reference to it.
|
||||
/// The intent is that the value is something with interior mutability which the target could write to even though this
|
||||
/// observer has a reference to it. Use [`RefCellValueObserver`] if using a [`RefCell`] around the value.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||
pub struct ValueObserver<'a, T>
|
||||
@ -104,3 +105,87 @@ where
|
||||
Some(s.finish())
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple observer with a single [`RefCell`]'d value.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||
pub struct RefCellValueObserver<'a, T>
|
||||
where
|
||||
T: Debug + Serialize,
|
||||
{
|
||||
/// The name of this observer.
|
||||
name: String,
|
||||
/// The value.
|
||||
pub value: OwnedRef<'a, RefCell<T>>,
|
||||
}
|
||||
|
||||
impl<'a, T> RefCellValueObserver<'a, T>
|
||||
where
|
||||
T: Debug + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
/// Creates a new [`RefCellValueObserver`] with the given name.
|
||||
#[must_use]
|
||||
pub fn new(name: &'static str, value: &'a RefCell<T>) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
value: OwnedRef::Ref(value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the underlying value.
|
||||
#[must_use]
|
||||
pub fn get_ref<'b>(&'b self) -> Ref<'a, T>
|
||||
where
|
||||
'b: 'a,
|
||||
{
|
||||
self.value.as_ref().borrow()
|
||||
}
|
||||
|
||||
/// Set the value.
|
||||
pub fn set(&mut self, new_value: T) {
|
||||
self.value.as_ref().replace(new_value);
|
||||
}
|
||||
|
||||
/// Clone or move the current value out of this object.
|
||||
#[must_use]
|
||||
pub fn take(self) -> T
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
match self.value {
|
||||
OwnedRef::Ref(r) => r.borrow().deref().clone(),
|
||||
OwnedRef::Owned(v) => v.borrow().clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This *does not* reset the value inside the observer.
|
||||
impl<'a, S, T> Observer<S> for RefCellValueObserver<'a, T>
|
||||
where
|
||||
S: UsesInput,
|
||||
T: Debug + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Named for RefCellValueObserver<'a, T>
|
||||
where
|
||||
T: Debug + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Hash> ObserverWithHashField for RefCellValueObserver<'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();
|
||||
self.value.as_ref().borrow().hash(&mut s);
|
||||
Some(s.finish())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user