Skip to content

Commit db7ce82

Browse files
wtdcodetokatoka
andauthored
QoL Types and Changes (#3124)
* Nop executor * Qol types * no stage * A new() for NopStage * clippy * clippy again --------- Co-authored-by: Dongjia "toka" Zhang <[email protected]>
1 parent 0fdfa1d commit db7ce82

File tree

5 files changed

+166
-0
lines changed

5 files changed

+166
-0
lines changed

libafl/src/executors/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub mod differential;
2828
#[cfg(all(feature = "std", feature = "fork", unix))]
2929
pub mod forkserver;
3030
pub mod inprocess;
31+
pub mod nop;
3132
/// SAND(<https://github.com/wtdcode/sand-aflpp>) implementation
3233
pub mod sand;
3334

libafl/src/executors/nop.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//! Trivial Constant Executor
2+
3+
use core::time::Duration;
4+
5+
use libafl_bolts::tuples::RefIndexable;
6+
7+
use super::{Executor, ExitKind, HasObservers, HasTimeout};
8+
9+
/// [`NopExecutor`] is an executor that does nothing
10+
pub type NopExecutor = ConstantExecutor<()>;
11+
12+
/// Constant Executor that returns a fixed value. Mostly helpful
13+
/// when you need it to satisfy some bounds like [`crate::fuzzer::NopFuzzer`]
14+
#[derive(Debug)]
15+
pub struct ConstantExecutor<OT = ()> {
16+
exit: ExitKind,
17+
tm: Duration,
18+
ot: OT,
19+
}
20+
21+
impl<OT> ConstantExecutor<OT> {
22+
/// Construct a [`ConstantExecutor`]
23+
#[must_use]
24+
pub fn new(exit: ExitKind, tm: Duration, ot: OT) -> Self {
25+
Self { exit, tm, ot }
26+
}
27+
}
28+
29+
impl ConstantExecutor<()> {
30+
/// Construct a [`ConstantExecutor`] that always returns Ok
31+
#[must_use]
32+
pub fn ok() -> Self {
33+
Self::new(ExitKind::Ok, Duration::default(), ())
34+
}
35+
36+
/// Construct a [`ConstantExecutor`] that always returns Crash
37+
#[must_use]
38+
pub fn crash() -> Self {
39+
Self::new(ExitKind::Crash, Duration::default(), ())
40+
}
41+
}
42+
43+
/// These are important to allow [`ConstantExecutor`] to be used with other components
44+
impl<OT> HasObservers for ConstantExecutor<OT> {
45+
type Observers = OT;
46+
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
47+
RefIndexable::from(&self.ot)
48+
}
49+
50+
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
51+
RefIndexable::from(&mut self.ot)
52+
}
53+
}
54+
55+
impl<OT> HasTimeout for ConstantExecutor<OT> {
56+
fn timeout(&self) -> Duration {
57+
self.tm
58+
}
59+
60+
fn set_timeout(&mut self, timeout: Duration) {
61+
self.tm = timeout;
62+
}
63+
}
64+
65+
impl<OT, EM, I, S, Z> Executor<EM, I, S, Z> for ConstantExecutor<OT> {
66+
fn run_target(
67+
&mut self,
68+
_fuzzer: &mut Z,
69+
_state: &mut S,
70+
_mgr: &mut EM,
71+
_input: &I,
72+
) -> Result<ExitKind, libafl_bolts::Error> {
73+
Ok(self.exit)
74+
}
75+
}

libafl/src/stages/dynamic.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//! A stage implementation that can have dynamic stage runtime
2+
3+
use super::{Restartable, Stage};
4+
5+
/// A dynamic stage implementation. This explicity uses enum so that rustc can better
6+
/// reason about the bounds.
7+
#[derive(Debug)]
8+
pub enum DynamicStage<T1, T2> {
9+
/// One stage
10+
Stage1(T1),
11+
/// The alernative stage
12+
Stage2(T2),
13+
}
14+
15+
impl<T1, T2, E, EM, S, Z> Stage<E, EM, S, Z> for DynamicStage<T1, T2>
16+
where
17+
T1: Stage<E, EM, S, Z>,
18+
T2: Stage<E, EM, S, Z>,
19+
{
20+
fn perform(
21+
&mut self,
22+
fuzzer: &mut Z,
23+
executor: &mut E,
24+
state: &mut S,
25+
manager: &mut EM,
26+
) -> Result<(), libafl_bolts::Error> {
27+
match self {
28+
Self::Stage1(st1) => st1.perform(fuzzer, executor, state, manager),
29+
Self::Stage2(st2) => st2.perform(fuzzer, executor, state, manager),
30+
}
31+
}
32+
}
33+
34+
impl<T1, T2, S> Restartable<S> for DynamicStage<T1, T2>
35+
where
36+
T1: Restartable<S>,
37+
T2: Restartable<S>,
38+
{
39+
fn should_restart(&mut self, state: &mut S) -> Result<bool, libafl_bolts::Error> {
40+
match self {
41+
Self::Stage1(st1) => st1.should_restart(state),
42+
Self::Stage2(st2) => st2.should_restart(state),
43+
}
44+
}
45+
fn clear_progress(&mut self, state: &mut S) -> Result<(), libafl_bolts::Error> {
46+
match self {
47+
Self::Stage1(st1) => st1.clear_progress(state),
48+
Self::Stage2(st2) => st2.clear_progress(state),
49+
}
50+
}
51+
}

libafl/src/stages/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,11 @@ pub mod colorization;
7171
pub mod concolic;
7272
#[cfg(feature = "std")]
7373
pub mod dump;
74+
pub mod dynamic;
7475
pub mod generalization;
7576
pub mod generation;
7677
pub mod logics;
78+
pub mod nop;
7779
pub mod power;
7880
#[cfg(feature = "std")]
7981
pub mod sync;

libafl/src/stages/nop.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//! A nop stage does nothing
2+
3+
use super::{Restartable, Stage};
4+
5+
/// A stage that does nothing
6+
#[derive(Debug, Default)]
7+
pub struct NopStage {}
8+
9+
impl NopStage {
10+
/// Create a [`NopStage`]
11+
#[must_use]
12+
pub fn new() -> Self {
13+
Self {}
14+
}
15+
}
16+
17+
impl<E, EM, S, Z> Stage<E, EM, S, Z> for NopStage {
18+
fn perform(
19+
&mut self,
20+
_fuzzer: &mut Z,
21+
_executor: &mut E,
22+
_state: &mut S,
23+
_manager: &mut EM,
24+
) -> Result<(), libafl_bolts::Error> {
25+
Ok(())
26+
}
27+
}
28+
29+
impl<S> Restartable<S> for NopStage {
30+
fn clear_progress(&mut self, _state: &mut S) -> Result<(), libafl_bolts::Error> {
31+
Ok(())
32+
}
33+
34+
fn should_restart(&mut self, _state: &mut S) -> Result<bool, libafl_bolts::Error> {
35+
Ok(true)
36+
}
37+
}

0 commit comments

Comments
 (0)