diff --git a/libafl/src/executors/combined.rs b/libafl/src/executors/combined.rs index a4ae7b3ccb..535a63377b 100644 --- a/libafl/src/executors/combined.rs +++ b/libafl/src/executors/combined.rs @@ -1,22 +1,43 @@ //! A `CombinedExecutor` wraps a primary executor and a secondary one +use core::marker::PhantomData; + use crate::{ - executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks}, + executors::{ + Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks, + }, inputs::Input, observers::ObserversTuple, Error, }; /// A [`CombinedExecutor`] wraps a primary executor, forwarding its methods, and a secondary one -pub struct CombinedExecutor { + +pub struct CombinedExecutor +where + A: Executor, + B: Executor, + I: Input, +{ primary: A, secondary: B, + exec_tmout: Duration, + phantom: PhantomData, } -impl CombinedExecutor { +impl CombinedExecutor +where + A: Executor, + B: Executor, + I: Input, +{ /// Create a new `CombinedExecutor`, wrapping the given `executor`s. - pub fn new(primary: A, secondary: B) -> Self { - Self { primary, secondary } + pub fn new(primary: A, secondary: B) -> Self { + Self { + primary, + secondary, + phantom: PhantomData, + } } /// Retrieve the primary `Executor` that is wrapped by this `CombinedExecutor`. @@ -30,26 +51,22 @@ impl CombinedExecutor { } } -impl Executor for CombinedExecutor +impl Executor for CombinedExecutor where - A: Executor, - B: Executor, + A: Executor, + B: Executor, I: Input, { - fn run_target( - &mut self, - fuzzer: &mut Z, - state: &mut S, - mgr: &mut EM, - input: &I, - ) -> Result { - self.primary.run_target(fuzzer, state, mgr, input) + fn run_target(&mut self, input: &I) -> Result { + self.primary.run_target(input) } } -impl HasObservers for CombinedExecutor +impl HasObservers for CombinedExecutor where - A: HasObservers, + A: Executor + HasObservers, + B: Executor, + I: Input, OT: ObserversTuple, { #[inline] @@ -63,10 +80,40 @@ where } } -impl HasObserversHooks for CombinedExecutor +impl HasObserversHooks for TimeoutExecutor where - A: HasObservers, + A: Executor + HasObservers, + B: Executor, I: Input, OT: ObserversTuple + HasExecHooksTuple, { } + +impl HasExecHooks for TimeoutExecutor +where + A: Executor + HasObservers, + B: Executor, + I: Input, +{ + #[inline] + fn pre_exec( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result<(), Error> { + self.primary.pre_exec(fuzzer, state, mgr, input) + } + + #[inline] + fn post_exec( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result<(), Error> { + self.primary.post_exec(fuzzer, state, mgr, input) + } +} diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index 25bcaf3c89..2b992f74da 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -4,6 +4,8 @@ pub mod inprocess; pub use inprocess::InProcessExecutor; pub mod timeout; pub use timeout::TimeoutExecutor; +pub mod combined; +pub use combined::CombinedExecutor; #[cfg(all(feature = "std", unix))] pub mod forkserver; diff --git a/libafl/src/feedbacks/cmp.rs b/libafl/src/feedbacks/cmp.rs new file mode 100644 index 0000000000..1617d204bd --- /dev/null +++ b/libafl/src/feedbacks/cmp.rs @@ -0,0 +1,96 @@ +use alloc::{ + string::{String, ToString}, +}; +use core::marker::PhantomData; +use num::Integer; +use serde::{Deserialize, Serialize}; + +use crate::{ + bolts::tuples::Named, + executors::ExitKind, + feedbacks::{Feedback, FeedbackState, FeedbackStatesTuple}, + inputs::Input, + observers::{CmpObserver, ObserversTuple}, + state::{HasFeedbackStates, HasMetadata}, + utils::AsSlice, + Error, +}; + +/// A state metadata holding a list of values logged from comparisons +#[derive(Serialize, Deserialize)] +pub struct CmpValuesMetadata { + /// A `list` of values. + pub list: Vec<(u64, u64)>, +} + +crate::impl_serdeany!(CmpValuesMetadata); + +impl AsSlice<(u64, u64)> for CmpValuesMetadata { + /// Convert to a slice + #[must_use] + fn as_slice(&self) -> &[(u64, u64)] { + self.list.as_slice() + } +} + +impl CmpValuesMetadata { + /// Creates a new [`struct@CmpValuesMetadata`] + #[must_use] + pub fn new(list: Vec<(u64, u64)>) -> Self { + Self { list } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct CmpFeedback { + name: String, + phantom: PhantomData +} + +impl Feedback for CmpFeedback +where + I: Input, +{ + fn is_interesting( + &mut self, + _state: &mut S, + _input: &I, + observers: &OT, + _exit_kind: &ExitKind, + ) -> Result + where + OT: ObserversTuple, + { + // TODO Replace with match_name_type when stable + let observer = observers.match_name::>(self.name()).unwrap(); + // TODO + Ok(false) + } +} + +impl Named for CmpFeedback { + #[inline] + fn name(&self) -> &str { + self.name.as_str() + } +} + +impl CmpFeedback { + /// Creates a new [`CmpFeedback`] + #[must_use] + pub fn new(name: &'static str) -> Self { + Self { + name: name.to_string(), + phantom: PhantomData + } + } + + /// Creates a new [`CmpFeedback`] + #[must_use] + pub fn new_with_observer(observer: &CmpObserver) -> Self { + Self { + name: observer.name().to_string(), + phantom: PhantomData + } + } +} diff --git a/libafl/src/observers/cmp.rs b/libafl/src/observers/cmp.rs index 581908d202..b375ff93a8 100644 --- a/libafl/src/observers/cmp.rs +++ b/libafl/src/observers/cmp.rs @@ -6,6 +6,7 @@ use alloc::{ }; use core::slice::from_raw_parts_mut; +use num_enum::{IntoPrimitive, TryFromPrimitive}; use serde::{Deserialize, Serialize}; use crate::{ @@ -18,7 +19,7 @@ use crate::{ Error, }; -/// A [`MapObserver`] observes the static map, as oftentimes used for afl-like coverage information +/// A [`CmpObserver`] observes the traced comparisons during the current execution pub trait CmpObserver: Observer { /// Get the number of usable cmps (all by default) fn usable_count(&self) -> usize; @@ -28,8 +29,6 @@ pub trait CmpObserver: Observer { fn executions_for(idx: usize) -> usize; - fn kind_for(idx: usize) -> CmpKind; - fn bytes_for(idx: usize) -> usize; fn values_of(idx: usize, execution: usize) -> (T, T);