combined executor
This commit is contained in:
parent
a3a2b47b2a
commit
f81a52e14d
@ -1,22 +1,43 @@
|
|||||||
//! A `CombinedExecutor` wraps a primary executor and a secondary one
|
//! A `CombinedExecutor` wraps a primary executor and a secondary one
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
executors::{
|
||||||
|
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
|
},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A [`CombinedExecutor`] wraps a primary executor, forwarding its methods, and a secondary one
|
/// A [`CombinedExecutor`] wraps a primary executor, forwarding its methods, and a secondary one
|
||||||
pub struct CombinedExecutor<A, B> {
|
|
||||||
|
pub struct CombinedExecutor<A, B, I>
|
||||||
|
where
|
||||||
|
A: Executor<I>,
|
||||||
|
B: Executor<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
primary: A,
|
primary: A,
|
||||||
secondary: B,
|
secondary: B,
|
||||||
|
exec_tmout: Duration,
|
||||||
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B> CombinedExecutor<A, B> {
|
impl<A, B, I> CombinedExecutor<A, B, I>
|
||||||
|
where
|
||||||
|
A: Executor<I>,
|
||||||
|
B: Executor<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
/// Create a new `CombinedExecutor`, wrapping the given `executor`s.
|
/// Create a new `CombinedExecutor`, wrapping the given `executor`s.
|
||||||
pub fn new<EM, I, S, Z>(primary: A, secondary: B) -> Self {
|
pub fn new(primary: A, secondary: B) -> Self {
|
||||||
Self { primary, secondary }
|
Self {
|
||||||
|
primary,
|
||||||
|
secondary,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the primary `Executor` that is wrapped by this `CombinedExecutor`.
|
/// Retrieve the primary `Executor` that is wrapped by this `CombinedExecutor`.
|
||||||
@ -30,26 +51,22 @@ impl<A, B> CombinedExecutor<A, B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, EM, I, S, Z> Executor<EM, I, S, Z> for CombinedExecutor<A, B>
|
impl<A, B, I> Executor<I> for CombinedExecutor<A, B, I>
|
||||||
where
|
where
|
||||||
A: Executor<EM, I, S, Z>,
|
A: Executor<I>,
|
||||||
B: Executor<EM, I, S, Z>,
|
B: Executor<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn run_target(
|
fn run_target(&mut self, input: &I) -> Result<ExitKind, Error> {
|
||||||
&mut self,
|
self.primary.run_target(input)
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<ExitKind, Error> {
|
|
||||||
self.primary.run_target(fuzzer, state, mgr, input)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, OT> HasObservers<OT> for CombinedExecutor<A, B>
|
impl<A, B, I, OT> HasObservers<OT> for CombinedExecutor<A, B, I>
|
||||||
where
|
where
|
||||||
A: HasObservers<OT>,
|
A: Executor<I> + HasObservers<OT>,
|
||||||
|
B: Executor<I>,
|
||||||
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -63,10 +80,40 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, EM, I, OT, S, Z> HasObserversHooks<EM, I, OT, S, Z> for CombinedExecutor<A, B>
|
impl<A, B, EM, I, OT, S, Z> HasObserversHooks<EM, I, OT, S, Z> for TimeoutExecutor<A, B, I>
|
||||||
where
|
where
|
||||||
A: HasObservers<OT>,
|
A: Executor<I> + HasObservers<OT>,
|
||||||
|
B: Executor<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A, B, EM, I, S, Z> HasExecHooks<EM, I, S, Z> for TimeoutExecutor<A, B, I>
|
||||||
|
where
|
||||||
|
A: Executor<I> + HasObservers<OT>,
|
||||||
|
B: Executor<I>,
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,6 +4,8 @@ pub mod inprocess;
|
|||||||
pub use inprocess::InProcessExecutor;
|
pub use inprocess::InProcessExecutor;
|
||||||
pub mod timeout;
|
pub mod timeout;
|
||||||
pub use timeout::TimeoutExecutor;
|
pub use timeout::TimeoutExecutor;
|
||||||
|
pub mod combined;
|
||||||
|
pub use combined::CombinedExecutor;
|
||||||
|
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
pub mod forkserver;
|
pub mod forkserver;
|
||||||
|
96
libafl/src/feedbacks/cmp.rs
Normal file
96
libafl/src/feedbacks/cmp.rs
Normal file
@ -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<T> {
|
||||||
|
name: String,
|
||||||
|
phantom: PhantomData<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, S, T> Feedback<I, S> for CmpFeedback<T>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn is_interesting<OT>(
|
||||||
|
&mut self,
|
||||||
|
_state: &mut S,
|
||||||
|
_input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
// TODO Replace with match_name_type when stable
|
||||||
|
let observer = observers.match_name::<CmpObserver<T>>(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<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: observer.name().to_string(),
|
||||||
|
phantom: PhantomData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use core::slice::from_raw_parts_mut;
|
use core::slice::from_raw_parts_mut;
|
||||||
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -18,7 +19,7 @@ use crate::{
|
|||||||
Error,
|
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<T>: Observer {
|
pub trait CmpObserver<T>: Observer {
|
||||||
/// Get the number of usable cmps (all by default)
|
/// Get the number of usable cmps (all by default)
|
||||||
fn usable_count(&self) -> usize;
|
fn usable_count(&self) -> usize;
|
||||||
@ -28,8 +29,6 @@ pub trait CmpObserver<T>: Observer {
|
|||||||
|
|
||||||
fn executions_for(idx: usize) -> usize;
|
fn executions_for(idx: usize) -> usize;
|
||||||
|
|
||||||
fn kind_for(idx: usize) -> CmpKind;
|
|
||||||
|
|
||||||
fn bytes_for(idx: usize) -> usize;
|
fn bytes_for(idx: usize) -> usize;
|
||||||
|
|
||||||
fn values_of(idx: usize, execution: usize) -> (T, T);
|
fn values_of(idx: usize, execution: usize) -> (T, T);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user