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);