QoL Types and Changes (#3124)
* Nop executor * Qol types * no stage * A new() for NopStage * clippy * clippy again --------- Co-authored-by: Dongjia "toka" Zhang <tokazerkje@outlook.com>
This commit is contained in:
parent
0fdfa1d7a1
commit
db7ce822dc
@ -28,6 +28,7 @@ pub mod differential;
|
||||
#[cfg(all(feature = "std", feature = "fork", unix))]
|
||||
pub mod forkserver;
|
||||
pub mod inprocess;
|
||||
pub mod nop;
|
||||
/// SAND(<https://github.com/wtdcode/sand-aflpp>) implementation
|
||||
pub mod sand;
|
||||
|
||||
|
75
libafl/src/executors/nop.rs
Normal file
75
libafl/src/executors/nop.rs
Normal file
@ -0,0 +1,75 @@
|
||||
//! Trivial Constant Executor
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use libafl_bolts::tuples::RefIndexable;
|
||||
|
||||
use super::{Executor, ExitKind, HasObservers, HasTimeout};
|
||||
|
||||
/// [`NopExecutor`] is an executor that does nothing
|
||||
pub type NopExecutor = ConstantExecutor<()>;
|
||||
|
||||
/// Constant Executor that returns a fixed value. Mostly helpful
|
||||
/// when you need it to satisfy some bounds like [`crate::fuzzer::NopFuzzer`]
|
||||
#[derive(Debug)]
|
||||
pub struct ConstantExecutor<OT = ()> {
|
||||
exit: ExitKind,
|
||||
tm: Duration,
|
||||
ot: OT,
|
||||
}
|
||||
|
||||
impl<OT> ConstantExecutor<OT> {
|
||||
/// Construct a [`ConstantExecutor`]
|
||||
#[must_use]
|
||||
pub fn new(exit: ExitKind, tm: Duration, ot: OT) -> Self {
|
||||
Self { exit, tm, ot }
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantExecutor<()> {
|
||||
/// Construct a [`ConstantExecutor`] that always returns Ok
|
||||
#[must_use]
|
||||
pub fn ok() -> Self {
|
||||
Self::new(ExitKind::Ok, Duration::default(), ())
|
||||
}
|
||||
|
||||
/// Construct a [`ConstantExecutor`] that always returns Crash
|
||||
#[must_use]
|
||||
pub fn crash() -> Self {
|
||||
Self::new(ExitKind::Crash, Duration::default(), ())
|
||||
}
|
||||
}
|
||||
|
||||
/// These are important to allow [`ConstantExecutor`] to be used with other components
|
||||
impl<OT> HasObservers for ConstantExecutor<OT> {
|
||||
type Observers = OT;
|
||||
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||
RefIndexable::from(&self.ot)
|
||||
}
|
||||
|
||||
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||
RefIndexable::from(&mut self.ot)
|
||||
}
|
||||
}
|
||||
|
||||
impl<OT> HasTimeout for ConstantExecutor<OT> {
|
||||
fn timeout(&self) -> Duration {
|
||||
self.tm
|
||||
}
|
||||
|
||||
fn set_timeout(&mut self, timeout: Duration) {
|
||||
self.tm = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
impl<OT, EM, I, S, Z> Executor<EM, I, S, Z> for ConstantExecutor<OT> {
|
||||
fn run_target(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
_state: &mut S,
|
||||
_mgr: &mut EM,
|
||||
_input: &I,
|
||||
) -> Result<ExitKind, libafl_bolts::Error> {
|
||||
Ok(self.exit)
|
||||
}
|
||||
}
|
51
libafl/src/stages/dynamic.rs
Normal file
51
libafl/src/stages/dynamic.rs
Normal file
@ -0,0 +1,51 @@
|
||||
//! A stage implementation that can have dynamic stage runtime
|
||||
|
||||
use super::{Restartable, Stage};
|
||||
|
||||
/// A dynamic stage implementation. This explicity uses enum so that rustc can better
|
||||
/// reason about the bounds.
|
||||
#[derive(Debug)]
|
||||
pub enum DynamicStage<T1, T2> {
|
||||
/// One stage
|
||||
Stage1(T1),
|
||||
/// The alernative stage
|
||||
Stage2(T2),
|
||||
}
|
||||
|
||||
impl<T1, T2, E, EM, S, Z> Stage<E, EM, S, Z> for DynamicStage<T1, T2>
|
||||
where
|
||||
T1: Stage<E, EM, S, Z>,
|
||||
T2: Stage<E, EM, S, Z>,
|
||||
{
|
||||
fn perform(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
executor: &mut E,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
) -> Result<(), libafl_bolts::Error> {
|
||||
match self {
|
||||
Self::Stage1(st1) => st1.perform(fuzzer, executor, state, manager),
|
||||
Self::Stage2(st2) => st2.perform(fuzzer, executor, state, manager),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T1, T2, S> Restartable<S> for DynamicStage<T1, T2>
|
||||
where
|
||||
T1: Restartable<S>,
|
||||
T2: Restartable<S>,
|
||||
{
|
||||
fn should_restart(&mut self, state: &mut S) -> Result<bool, libafl_bolts::Error> {
|
||||
match self {
|
||||
Self::Stage1(st1) => st1.should_restart(state),
|
||||
Self::Stage2(st2) => st2.should_restart(state),
|
||||
}
|
||||
}
|
||||
fn clear_progress(&mut self, state: &mut S) -> Result<(), libafl_bolts::Error> {
|
||||
match self {
|
||||
Self::Stage1(st1) => st1.clear_progress(state),
|
||||
Self::Stage2(st2) => st2.clear_progress(state),
|
||||
}
|
||||
}
|
||||
}
|
@ -71,9 +71,11 @@ pub mod colorization;
|
||||
pub mod concolic;
|
||||
#[cfg(feature = "std")]
|
||||
pub mod dump;
|
||||
pub mod dynamic;
|
||||
pub mod generalization;
|
||||
pub mod generation;
|
||||
pub mod logics;
|
||||
pub mod nop;
|
||||
pub mod power;
|
||||
#[cfg(feature = "std")]
|
||||
pub mod sync;
|
||||
|
37
libafl/src/stages/nop.rs
Normal file
37
libafl/src/stages/nop.rs
Normal file
@ -0,0 +1,37 @@
|
||||
//! A nop stage does nothing
|
||||
|
||||
use super::{Restartable, Stage};
|
||||
|
||||
/// A stage that does nothing
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NopStage {}
|
||||
|
||||
impl NopStage {
|
||||
/// Create a [`NopStage`]
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, EM, S, Z> Stage<E, EM, S, Z> for NopStage {
|
||||
fn perform(
|
||||
&mut self,
|
||||
_fuzzer: &mut Z,
|
||||
_executor: &mut E,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
) -> Result<(), libafl_bolts::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Restartable<S> for NopStage {
|
||||
fn clear_progress(&mut self, _state: &mut S) -> Result<(), libafl_bolts::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn should_restart(&mut self, _state: &mut S) -> Result<bool, libafl_bolts::Error> {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user