1
1
//! The [`TMinMutationalStage`] is a stage which will attempt to minimize corpus entries.
2
2
3
3
use alloc:: string:: { String , ToString } ;
4
- use core:: { fmt:: Debug , hash:: Hash , marker:: PhantomData } ;
4
+ use core:: { borrow :: BorrowMut , fmt:: Debug , hash:: Hash , marker:: PhantomData } ;
5
5
6
6
use ahash:: RandomState ;
7
7
use libafl_bolts:: { HasLen , Named } ;
@@ -16,7 +16,10 @@ use crate::{
16
16
mutators:: { MutationResult , Mutator } ,
17
17
observers:: { MapObserver , ObserversTuple } ,
18
18
schedulers:: { RemovableScheduler , Scheduler } ,
19
- stages:: { ExecutionCountRestartHelper , Stage } ,
19
+ stages:: {
20
+ mutational:: { MutatedTransform , MutatedTransformPost } ,
21
+ ExecutionCountRestartHelper , Stage ,
22
+ } ,
20
23
start_timer,
21
24
state:: {
22
25
HasCorpus , HasCurrentTestcase , HasExecutions , HasMaxSize , HasMetadata , HasSolutions , State ,
@@ -30,7 +33,7 @@ use crate::{monitors::PerfFeature, state::HasClientPerfMonitor};
30
33
/// Mutational stage which minimizes corpus entries.
31
34
///
32
35
/// You must provide at least one mutator that actually reduces size.
33
- pub trait TMinMutationalStage < CS , E , EM , F1 , F2 , M , OT , Z > :
36
+ pub trait TMinMutationalStage < CS , E , EM , F1 , F2 , I , IP , M , OT , Z > :
34
37
Stage < E , EM , Z > + FeedbackFactory < F2 , CS :: State , OT >
35
38
where
36
39
Self :: State : HasCorpus + HasSolutions + HasExecutions + HasMaxSize ,
@@ -40,12 +43,14 @@ where
40
43
EM : EventFirer < State = Self :: State > ,
41
44
F1 : Feedback < Self :: State > ,
42
45
F2 : Feedback < Self :: State > ,
43
- M : Mutator < Self :: Input , Self :: State > ,
46
+ M : Mutator < I , Self :: State > ,
44
47
OT : ObserversTuple < CS :: State > ,
45
48
Z : ExecutionProcessor < OT , State = Self :: State >
46
49
+ ExecutesInput < E , EM >
47
50
+ HasFeedback < Feedback = F1 >
48
51
+ HasScheduler < Scheduler = CS > ,
52
+ IP : MutatedTransformPost < Self :: State > + Clone ,
53
+ I : MutatedTransform < Self :: Input , Self :: State , Post = IP > + Clone ,
49
54
{
50
55
/// The mutator registered for this stage
51
56
fn mutator ( & self ) -> & M ;
77
82
- usize:: try_from ( self . execs_since_progress_start ( state) ?) . unwrap ( ) ;
78
83
79
84
start_timer ! ( state) ;
85
+ let transformed = I :: try_transform_from ( state. current_testcase_mut ( ) ?. borrow_mut ( ) , state) ?;
80
86
let mut base = state. current_input_cloned ( ) ?;
87
+ // potential post operation if base is replaced by a shorter input
88
+ let mut base_post = None ;
81
89
let base_hash = RandomState :: with_seeds ( 0 , 0 , 0 , 0 ) . hash_one ( & base) ;
82
90
mark_feature_time ! ( state, PerfFeature :: GetInputFromCorpus ) ;
83
91
@@ -93,20 +101,21 @@ where
93
101
}
94
102
95
103
let mut next_i = i + 1 ;
96
- let mut input = base . clone ( ) ;
104
+ let mut input_transformed = transformed . clone ( ) ;
97
105
98
- let before_len = input . len ( ) ;
106
+ let before_len = base . len ( ) ;
99
107
100
108
state. set_max_size ( before_len) ;
101
109
102
110
start_timer ! ( state) ;
103
- let mutated = self . mutator_mut ( ) . mutate ( state, & mut input ) ?;
111
+ let mutated = self . mutator_mut ( ) . mutate ( state, & mut input_transformed ) ?;
104
112
mark_feature_time ! ( state, PerfFeature :: Mutate ) ;
105
113
106
114
if mutated == MutationResult :: Skipped {
107
115
continue ;
108
116
}
109
117
118
+ let ( input, post) = input_transformed. try_transform_into ( state) ?;
110
119
let corpus_idx = if input. len ( ) < before_len {
111
120
// run the input
112
121
let exit_kind = fuzzer. execute_input ( state, executor, manager, & input) ?;
@@ -134,6 +143,7 @@ where
134
143
if feedback. is_interesting ( state, manager, & input, observers, & exit_kind) ? {
135
144
// we found a reduced corpus entry! use the smaller base
136
145
base = input;
146
+ base_post = Some ( post. clone ( ) ) ;
137
147
138
148
// do more runs! maybe we can minify further
139
149
next_i = 0 ;
@@ -149,6 +159,7 @@ where
149
159
150
160
start_timer ! ( state) ;
151
161
self . mutator_mut ( ) . post_exec ( state, corpus_idx) ?;
162
+ post. post_exec ( state, corpus_idx) ?;
152
163
mark_feature_time ! ( state, PerfFeature :: MutatePostExec ) ;
153
164
154
165
i = next_i;
@@ -171,6 +182,11 @@ where
171
182
fuzzer
172
183
. scheduler_mut ( )
173
184
. on_replace ( state, base_corpus_idx, & prev) ?;
185
+ // perform the post operation for the new testcase, e.g. to update metadata.
186
+ // base_post should be updated along with the base (and is no longer None)
187
+ base_post
188
+ . ok_or_else ( || Error :: empty_optional ( "Failed to get the MutatedTransformPost" ) ) ?
189
+ . post_exec ( state, Some ( base_corpus_idx) ) ?;
174
190
}
175
191
176
192
state. set_max_size ( orig_max_size) ;
@@ -184,7 +200,7 @@ where
184
200
185
201
/// The default corpus entry minimising mutational stage
186
202
#[ derive( Clone , Debug ) ]
187
- pub struct StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , M , OT , Z > {
203
+ pub struct StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z > {
188
204
/// The mutator(s) this stage uses
189
205
mutator : M ,
190
206
/// The factory
@@ -194,22 +210,24 @@ pub struct StdTMinMutationalStage<CS, E, EM, F1, F2, FF, M, OT, Z> {
194
210
/// The progress helper for this stage, keeping track of resumes after timeouts/crashes
195
211
restart_helper : ExecutionCountRestartHelper ,
196
212
#[ allow( clippy:: type_complexity) ]
197
- phantom : PhantomData < ( CS , E , EM , F1 , F2 , OT , Z ) > ,
213
+ phantom : PhantomData < ( CS , E , EM , F1 , F2 , I , IP , OT , Z ) > ,
198
214
}
199
215
200
- impl < CS , E , EM , F1 , F2 , FF , M , OT , Z > UsesState
201
- for StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , M , OT , Z >
216
+ impl < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z > UsesState
217
+ for StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z >
202
218
where
203
219
CS : Scheduler ,
204
- M : Mutator < CS :: Input , CS :: State > ,
220
+ M : Mutator < I , CS :: State > ,
205
221
Z : ExecutionProcessor < OT , State = CS :: State > ,
206
222
CS :: State : HasCorpus ,
223
+ IP : MutatedTransformPost < CS :: State > + Clone ,
224
+ I : MutatedTransform < CS :: Input , CS :: State , Post = IP > + Clone ,
207
225
{
208
226
type State = CS :: State ;
209
227
}
210
228
211
- impl < CS , E , EM , F1 , F2 , FF , M , OT , Z > Stage < E , EM , Z >
212
- for StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , M , OT , Z >
229
+ impl < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z > Stage < E , EM , Z >
230
+ for StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z >
213
231
where
214
232
CS : Scheduler + RemovableScheduler ,
215
233
CS :: State : HasCorpus + HasSolutions + HasExecutions + HasMaxSize + HasCorpus + HasMetadata ,
@@ -219,12 +237,14 @@ where
219
237
F1 : Feedback < CS :: State > ,
220
238
F2 : Feedback < CS :: State > ,
221
239
FF : FeedbackFactory < F2 , CS :: State , OT > ,
222
- M : Mutator < CS :: Input , CS :: State > ,
240
+ M : Mutator < I , CS :: State > ,
223
241
OT : ObserversTuple < CS :: State > ,
224
242
Z : ExecutionProcessor < OT , State = CS :: State >
225
243
+ ExecutesInput < E , EM >
226
244
+ HasFeedback < Feedback = F1 >
227
245
+ HasScheduler < Scheduler = CS > ,
246
+ IP : MutatedTransformPost < CS :: State > + Clone ,
247
+ I : MutatedTransform < CS :: Input , CS :: State , Post = IP > + Clone ,
228
248
{
229
249
fn perform (
230
250
& mut self ,
@@ -250,8 +270,8 @@ where
250
270
}
251
271
}
252
272
253
- impl < CS , E , EM , F1 , F2 , FF , M , OT , Z > FeedbackFactory < F2 , Z :: State , OT >
254
- for StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , M , OT , Z >
273
+ impl < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z > FeedbackFactory < F2 , Z :: State , OT >
274
+ for StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z >
255
275
where
256
276
F2 : Feedback < Z :: State > ,
257
277
FF : FeedbackFactory < F2 , Z :: State , OT > ,
@@ -262,8 +282,8 @@ where
262
282
}
263
283
}
264
284
265
- impl < CS , E , EM , F1 , F2 , FF , M , OT , Z > TMinMutationalStage < CS , E , EM , F1 , F2 , M , OT , Z >
266
- for StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , M , OT , Z >
285
+ impl < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z > TMinMutationalStage < CS , E , EM , F1 , F2 , I , IP , M , OT , Z >
286
+ for StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z >
267
287
where
268
288
CS : Scheduler + RemovableScheduler ,
269
289
E : HasObservers < Observers = OT , State = CS :: State > + Executor < EM , Z > ,
@@ -272,13 +292,15 @@ where
272
292
F2 : Feedback < CS :: State > ,
273
293
FF : FeedbackFactory < F2 , CS :: State , OT > ,
274
294
<CS :: State as UsesInput >:: Input : HasLen + Hash ,
275
- M : Mutator < CS :: Input , CS :: State > ,
295
+ M : Mutator < I , CS :: State > ,
276
296
OT : ObserversTuple < CS :: State > ,
277
297
CS :: State : HasCorpus + HasSolutions + HasExecutions + HasMaxSize + HasMetadata ,
278
298
Z : ExecutionProcessor < OT , State = CS :: State >
279
299
+ ExecutesInput < E , EM >
280
300
+ HasFeedback < Feedback = F1 >
281
301
+ HasScheduler < Scheduler = CS > ,
302
+ IP : MutatedTransformPost < CS :: State > + Clone ,
303
+ I : MutatedTransform < CS :: Input , CS :: State , Post = IP > + Clone ,
282
304
{
283
305
/// The mutator, added to this stage
284
306
#[ inline]
@@ -302,12 +324,15 @@ where
302
324
}
303
325
}
304
326
305
- impl < CS , E , EM , F1 , F2 , FF , M , OT , Z > StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , M , OT , Z >
327
+ impl < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z >
328
+ StdTMinMutationalStage < CS , E , EM , F1 , F2 , FF , I , IP , M , OT , Z >
306
329
where
307
330
CS : Scheduler ,
308
- M : Mutator < CS :: Input , CS :: State > ,
331
+ M : Mutator < I , CS :: State > ,
309
332
Z : ExecutionProcessor < OT , State = CS :: State > ,
310
333
CS :: State : HasCorpus ,
334
+ IP : MutatedTransformPost < CS :: State > + Clone ,
335
+ I : MutatedTransform < CS :: Input , CS :: State , Post = IP > + Clone ,
311
336
{
312
337
/// Creates a new minimizing mutational stage that will minimize provided corpus entries
313
338
pub fn new ( mutator : M , factory : FF , runs : usize ) -> Self {
0 commit comments