1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
pub mod inprocess;
pub use inprocess::InProcessExecutor;
pub mod timeout;
pub use timeout::TimeoutExecutor;
#[cfg(all(feature = "std", unix))]
pub mod forkserver;
#[cfg(all(feature = "std", unix))]
pub use forkserver::{Forkserver, ForkserverExecutor, OutFile, TimeoutForkserverExecutor};
pub mod combined;
pub use combined::CombinedExecutor;
pub mod shadow;
pub use shadow::{HasShadowObserverHooks, ShadowExecutor};
use crate::{
inputs::{HasTargetBytes, Input},
observers::ObserversTuple,
Error,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ExitKind {
Ok,
Crash,
Oom,
Timeout,
}
pub trait HasObservers<I, OT, S>
where
OT: ObserversTuple<I, S>,
{
fn observers(&self) -> &OT;
fn observers_mut(&mut self) -> &mut OT;
}
pub trait Executor<EM, I, S, Z>
where
I: Input,
{
fn run_target(
&mut self,
fuzzer: &mut Z,
state: &mut S,
mgr: &mut EM,
input: &I,
) -> Result<ExitKind, Error>;
}
struct NopExecutor {}
impl<EM, I, S, Z> Executor<EM, I, S, Z> for NopExecutor
where
I: Input + HasTargetBytes,
{
fn run_target(
&mut self,
_fuzzer: &mut Z,
_state: &mut S,
_mgr: &mut EM,
input: &I,
) -> Result<ExitKind, Error> {
if input.target_bytes().as_slice().is_empty() {
Err(Error::Empty("Input Empty".into()))
} else {
Ok(ExitKind::Ok)
}
}
}
#[cfg(test)]
mod test {
use super::{Executor, NopExecutor};
use crate::inputs::BytesInput;
#[test]
fn nop_executor() {
let empty_input = BytesInput::new(vec![]);
let nonempty_input = BytesInput::new(vec![1u8]);
let mut executor = NopExecutor {};
assert!(executor
.run_target(&mut (), &mut (), &mut (), &empty_input)
.is_err());
assert!(executor
.run_target(&mut (), &mut (), &mut (), &nonempty_input)
.is_ok());
}
}