@@ -12,6 +12,159 @@ use crate::{inputs::UsesInput, observers::Observer, state::State, Error};
12
12
13
13
/// An observer that captures stdout of a target.
14
14
/// Only works for supported executors.
15
+ ///
16
+ /// # Example usage
17
+ #[ cfg_attr( all( feature = "std" , target_os = "linux" , not( miri) ) , doc = " ```" ) ] // miri doesn't like the Command crate, linux as a shorthand for the availability of base64
18
+ #[ cfg_attr(
19
+ not( all( feature = "std" , target_os = "linux" , not( miri) ) ) ,
20
+ doc = " ```ignore"
21
+ ) ]
22
+ /// use std::borrow::Cow;
23
+ ///
24
+ /// use libafl::{
25
+ /// corpus::{Corpus, InMemoryCorpus, Testcase},
26
+ /// events::{EventFirer, NopEventManager},
27
+ /// executors::{CommandExecutor, ExitKind},
28
+ /// feedbacks::Feedback,
29
+ /// inputs::{BytesInput, UsesInput},
30
+ /// mutators::{MutationResult, NopMutator},
31
+ /// observers::{ObserversTuple, StdErrObserver, StdOutObserver},
32
+ /// schedulers::QueueScheduler,
33
+ /// stages::StdMutationalStage,
34
+ /// state::{HasCorpus, State, StdState},
35
+ /// Error, Fuzzer, StdFuzzer,
36
+ /// };
37
+ ///
38
+ /// use libafl_bolts::{
39
+ /// current_nanos,
40
+ /// rands::StdRand,
41
+ /// tuples::{tuple_list, Handle, Handled, MatchNameRef},
42
+ /// Named,
43
+ /// };
44
+ ///
45
+ /// static mut STDOUT: Option<Vec<u8>> = None;
46
+ /// static mut STDERR: Option<Vec<u8>> = None;
47
+ ///
48
+ /// #[derive(Clone)]
49
+ /// struct ExportStdXObserver {
50
+ /// stdout_observer: Handle<StdOutObserver>,
51
+ /// stderr_observer: Handle<StdErrObserver>,
52
+ /// }
53
+ ///
54
+ /// impl<S> Feedback<S> for ExportStdXObserver
55
+ /// where
56
+ /// S: State
57
+ /// {
58
+ /// fn is_interesting<EM, OT>(
59
+ /// &mut self,
60
+ /// _state: &mut S,
61
+ /// _manager: &mut EM,
62
+ /// _input: &<S>::Input,
63
+ /// observers: &OT,
64
+ /// _exit_kind: &ExitKind,
65
+ /// ) -> Result<bool, Error>
66
+ /// where
67
+ /// EM: EventFirer<State = S>,
68
+ /// OT: ObserversTuple<S>,
69
+ /// {
70
+ /// unsafe {
71
+ /// STDOUT = observers.get(&self.stdout_observer).unwrap().stdout.clone();
72
+ /// STDERR = observers.get(&self.stderr_observer).unwrap().stderr.clone();
73
+ /// }
74
+ /// Ok(true)
75
+ /// }
76
+ ///
77
+ /// #[cfg(feature = "track_hit_feedbacks")]
78
+ /// fn last_result(&self) -> Result<bool, Error> {
79
+ /// Ok(true)
80
+ /// }
81
+ /// }
82
+ ///
83
+ /// impl Named for ExportStdXObserver {
84
+ /// fn name(&self) -> &Cow<'static, str> {
85
+ /// &Cow::Borrowed("ExportStdXObserver")
86
+ /// }
87
+ /// }
88
+ ///
89
+ /// fn main() {
90
+ /// let input_text = "Hello, World!";
91
+ /// let encoded_input_text = "SGVsbG8sIFdvcmxkIQo=";
92
+ ///
93
+ /// let stdout_observer = StdOutObserver::new("stdout-observer");
94
+ /// let stderr_observer = StdErrObserver::new("stderr-observer");
95
+ ///
96
+ /// let mut feedback = ExportStdXObserver {
97
+ /// stdout_observer: stdout_observer.handle(),
98
+ /// stderr_observer: stderr_observer.handle(),
99
+ /// };
100
+ ///
101
+ /// let mut objective = ();
102
+ ///
103
+ /// let mut executor = CommandExecutor::builder()
104
+ /// .program("base64")
105
+ /// .arg("--decode")
106
+ /// .stdout_observer(stdout_observer.handle())
107
+ /// .stderr_observer(stderr_observer.handle())
108
+ /// .build(tuple_list!(stdout_observer, stderr_observer))
109
+ /// .unwrap();
110
+ ///
111
+ /// let mut state = StdState::new(
112
+ /// StdRand::with_seed(current_nanos()),
113
+ /// InMemoryCorpus::new(),
114
+ /// InMemoryCorpus::new(),
115
+ /// &mut feedback,
116
+ /// &mut objective,
117
+ /// )
118
+ /// .unwrap();
119
+ ///
120
+ /// let scheduler = QueueScheduler::new();
121
+ /// let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
122
+ /// let mut manager = NopEventManager::new();
123
+ ///
124
+ /// let mut stages = tuple_list!(StdMutationalStage::new(NopMutator::new(
125
+ /// MutationResult::Mutated
126
+ /// )));
127
+ ///
128
+ /// state
129
+ /// .corpus_mut()
130
+ /// .add(Testcase::new(BytesInput::from(
131
+ /// encoded_input_text.as_bytes().to_vec(),
132
+ /// )))
133
+ /// .unwrap();
134
+ ///
135
+ /// let corpus_id = fuzzer
136
+ /// .fuzz_one(&mut stages, &mut executor, &mut state, &mut manager)
137
+ /// .unwrap();
138
+ ///
139
+ /// unsafe {
140
+ /// assert!(input_text
141
+ /// .as_bytes()
142
+ /// .iter()
143
+ /// .zip(STDOUT.as_ref().unwrap().iter().filter(|e| **e != 10)) // ignore newline chars
144
+ /// .all(|(&a, &b)| a == b));
145
+ /// assert!(STDERR.as_ref().unwrap().is_empty());
146
+ /// }
147
+ ///
148
+ /// state
149
+ /// .corpus()
150
+ /// .get(corpus_id)
151
+ /// .unwrap()
152
+ /// .replace(Testcase::new(BytesInput::from(
153
+ /// encoded_input_text.bytes().skip(1).collect::<Vec<u8>>(), // skip one char to make it invalid code
154
+ /// )));
155
+ ///
156
+ /// fuzzer
157
+ /// .fuzz_one(&mut stages, &mut executor, &mut state, &mut manager)
158
+ /// .unwrap();
159
+ ///
160
+ /// unsafe {
161
+ /// let compare_vec: Vec<u8> = Vec::new();
162
+ /// assert_eq!(compare_vec, *STDERR.as_ref().unwrap());
163
+ /// // stdout will still contain data, we're just checking that there is an error message
164
+ /// }
165
+ /// }
166
+ /// ```
167
+
15
168
#[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
16
169
pub struct StdOutObserver {
17
170
/// The name of the observer.
@@ -55,10 +208,17 @@ where
55
208
self . stdout = None ;
56
209
Ok ( ( ) )
57
210
}
211
+
212
+ fn pre_exec ( & mut self , _state : & mut S , _input : & <S as UsesInput >:: Input ) -> Result < ( ) , Error > {
213
+ self . stdout = None ;
214
+ Ok ( ( ) )
215
+ }
58
216
}
59
217
60
218
/// An observer that captures stderr of a target.
61
219
/// Only works for supported executors.
220
+ ///
221
+ /// Check docs for [`StdOutObserver`] for example.
62
222
#[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
63
223
pub struct StdErrObserver {
64
224
/// The name of the observer.
@@ -102,4 +262,9 @@ where
102
262
self . stderr = None ;
103
263
Ok ( ( ) )
104
264
}
265
+
266
+ fn pre_exec ( & mut self , _state : & mut S , _input : & <S as UsesInput >:: Input ) -> Result < ( ) , Error > {
267
+ self . stderr = None ;
268
+ Ok ( ( ) )
269
+ }
105
270
}
0 commit comments