From f76331eac75016b751df9b7a68b892301fab1bd3 Mon Sep 17 00:00:00 2001 From: Addison Crump Date: Thu, 13 Jul 2023 18:02:02 +0200 Subject: [PATCH] Add RefCellValueObserver (#1363) * add RefCellValueObserver * appease the clippy gods * Update libafl/src/observers/value.rs Co-authored-by: Langston Barrett --------- Co-authored-by: Langston Barrett --- libafl/src/observers/value.rs | 91 +++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/libafl/src/observers/value.rs b/libafl/src/observers/value.rs index 67a3276321..35c2a0da1c 100644 --- a/libafl/src/observers/value.rs +++ b/libafl/src/observers/value.rs @@ -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>, +} + +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) -> 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 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 { + let mut s = RandomState::with_seeds(1, 2, 3, 4).build_hasher(); + self.value.as_ref().borrow().hash(&mut s); + Some(s.finish()) + } +}