From 99a105d90778a92e9ef0ecfce0da4b11705c9455 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 30 Sep 2022 11:34:28 +0200 Subject: [PATCH] Disable ObserversOwnedMap due to new Rust error (#807) Co-authored-by: Andrea Fioraldi --- libafl/src/observers/mod.rs | 11 ++- libafl/src/stages/getdeps.rs | 160 +++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 libafl/src/stages/getdeps.rs diff --git a/libafl/src/observers/mod.rs b/libafl/src/observers/mod.rs index a7add150c0..2040598162 100644 --- a/libafl/src/observers/mod.rs +++ b/libafl/src/observers/mod.rs @@ -18,16 +18,18 @@ pub use stacktrace::*; pub mod concolic; -#[cfg(unstable_feature)] -pub mod owned; +// Rust is breaking this with 'error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `type_id`' and so we disable this component for the moment +//#[cfg(unstable_feature)] +//pub mod owned; +//#[cfg(unstable_feature)] +//pub use owned::*; + use alloc::{ string::{String, ToString}, vec::Vec, }; use core::{fmt::Debug, time::Duration}; -#[cfg(unstable_feature)] -pub use owned::*; use serde::{Deserialize, Serialize}; use crate::{ @@ -183,6 +185,7 @@ pub trait ObserverWithHashField { /// clears the current value of the hash and sets it to None fn clear_hash(&mut self); } + /// A simple observer, just overlooking the runtime of the target. #[derive(Serialize, Deserialize, Debug, Clone)] pub struct TimeObserver { diff --git a/libafl/src/stages/getdeps.rs b/libafl/src/stages/getdeps.rs new file mode 100644 index 0000000000..2d9352f1b3 --- /dev/null +++ b/libafl/src/stages/getdeps.rs @@ -0,0 +1,160 @@ +//! The tracing stage can trace the target and enrich a testcase with metadata, for example for `CmpLog`. + +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use core::{fmt::Debug, marker::PhantomData}; + +use hashbrown::HashSet; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "introspection")] +use crate::monitors::PerfFeature; +use crate::{ + bolts::AsSlice, + corpus::Corpus, + executors::{Executor, HasObservers}, + feedbacks::map::MapNoveltiesMetadata, + inputs::{GeneralizedInput, GeneralizedItem, HasBytesVec}, + mark_feature_time, + observers::{MapObserver, ObserversTuple}, + stages::Stage, + start_timer, + state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasMetadata}, + Error, +}; + +const MAX_GENERALIZED_LEN: usize = 8192; + +/// A state metadata holding the set of indexes related to the generalized corpus entries +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct GeneralizedIndexesMetadata { + /// The set of indexes + pub indexes: HashSet, +} + +crate::impl_serdeany!(GeneralizedIndexesMetadata); + +impl GeneralizedIndexesMetadata { + /// Create the metadata + #[must_use] + pub fn new() -> Self { + Self::default() + } +} + +fn increment_by_offset(_list: &[Option], idx: usize, off: u8) -> usize { + idx + 1 + off as usize +} + +fn find_next_char(list: &[Option], mut idx: usize, ch: u8) -> usize { + while idx < list.len() { + if list[idx] == Some(ch) { + return idx + 1; + } + idx += 1; + } + idx +} + +/// A stage that runs a tracer executor +#[derive(Clone, Debug)] +pub struct GetDepsStage +where + O: MapObserver, + OT: ObserversTuple, + S: HasClientPerfMonitor + HasExecutions + HasMetadata + HasCorpus, +{ + map_observer_name: String, + #[allow(clippy::type_complexity)] + phantom: PhantomData<(EM, O, OT, S, Z)>, +} + +impl Stage for GetDepsStage +where + O: MapObserver, + E: Executor + HasObservers, + OT: ObserversTuple, + S: HasClientPerfMonitor + HasExecutions + HasMetadata + HasCorpus, +{ + #[inline] + #[allow(clippy::too_many_lines)] + fn perform( + &mut self, + fuzzer: &mut Z, + executor: &mut E, + state: &mut S, + manager: &mut EM, + corpus_idx: usize, + ) -> Result<(), Error> { + if state + .metadata() + .get::() + .is_none() + { + state.add_metadata(GeneralizedIndexesMetadata::new()); + } + + let (mut payload, original, novelties) = { + start_timer!(state); + state.corpus().get(corpus_idx)?.borrow_mut().load_input()?; + mark_feature_time!(state, PerfFeature::GetInputFromCorpus); + let mut entry = state.corpus().get(corpus_idx)?.borrow_mut(); + let input = entry.input_mut().as_mut().unwrap(); + + if input.generalized().is_some() { + drop(entry); + state + .metadata_mut() + .get_mut::() + .unwrap() + .indexes + .insert(corpus_idx); + return Ok(()); + } + + let payload: Vec<_> = input.bytes().iter().map(|&x| Some(x)).collect(); + let original = input.clone(); + let meta = entry.metadata().get::().ok_or_else(|| { + Error::key_not_found(format!( + "MapNoveltiesMetadata needed for GetDepsStage not found in testcase #{} (check the arguments of MapFeedback::new(...))", + corpus_idx + )) + })?; + (payload, original, meta.as_slice().to_vec()) + }; + + // Do not generalized unstable inputs + if !self.verify_input(fuzzer, executor, state, manager, &novelties, &original)? { + return Ok(()); + } + + Ok(()) + } +} + +impl GetDepsStage +where + O: MapObserver, + OT: ObserversTuple, + S: HasClientPerfMonitor + HasExecutions + HasMetadata + HasCorpus, +{ + /// Create a new [`GetDepsStage`]. + #[must_use] + pub fn new(map_observer: &O) -> Self { + Self { + map_observer_name: map_observer.name().to_string(), + phantom: PhantomData, + } + } + + /// Create a new [`GetDepsStage`] from name + #[must_use] + pub fn from_name(map_observer_name: &str) -> Self { + Self { + map_observer_name: map_observer_name.to_string(), + phantom: PhantomData, + } + } +}