@@ -175,16 +175,14 @@ where
175
175
manager : & mut EM ,
176
176
corpus_idx : CorpusId ,
177
177
) -> Result < ( ) , Error > {
178
- let metadata: & TuneableMutationalStageMetadata = state. metadata ( ) ?;
178
+ let fuzz_time = self . seed_fuzz_time ( state) ?;
179
+ let iters = self . fixed_iters ( state) ?;
179
180
180
- let fuzz_time = metadata. fuzz_time ;
181
- let iters = metadata. iters ;
182
-
183
- let ( start_time, iters) = if fuzz_time. is_some ( ) {
184
- ( Some ( current_time ( ) ) , iters)
185
- } else {
186
- ( None , Some ( self . iterations ( state, corpus_idx) ?) )
187
- } ;
181
+ if fuzz_time. is_some ( ) && iters. is_some ( ) {
182
+ return Err ( Error :: illegal_state (
183
+ "Both fuzz_time and iters specified; failing fast!" ,
184
+ ) ) ;
185
+ }
188
186
189
187
start_timer ! ( state) ;
190
188
let mut testcase = state. corpus ( ) . get ( corpus_idx) ?. borrow_mut ( ) ;
@@ -194,39 +192,42 @@ where
194
192
drop ( testcase) ;
195
193
mark_feature_time ! ( state, PerfFeature :: GetInputFromCorpus ) ;
196
194
197
- let mut i = 0_usize ;
198
- loop {
199
- if let Some ( start_time) = start_time {
200
- if current_time ( ) - start_time >= fuzz_time. unwrap ( ) {
201
- break ;
195
+ match ( fuzz_time, iters) {
196
+ ( Some ( fuzz_time) , Some ( iters) ) => {
197
+ // perform n iterations or fuzz for provided time, whichever comes first
198
+ let start_time = current_time ( ) ;
199
+ for i in 1 ..=iters {
200
+ if current_time ( ) - start_time >= fuzz_time {
201
+ break ;
202
+ }
203
+
204
+ self . perform_mutation ( fuzzer, executor, state, manager, & input, i) ?;
202
205
}
203
206
}
204
- if let Some ( iters) = iters {
205
- if i >= iters as usize {
206
- break ;
207
+ ( Some ( fuzz_time) , None ) => {
208
+ // fuzz for provided time
209
+ let start_time = current_time ( ) ;
210
+ for i in 1 .. {
211
+ if current_time ( ) - start_time >= fuzz_time {
212
+ break ;
213
+ }
214
+
215
+ self . perform_mutation ( fuzzer, executor, state, manager, & input, i) ?;
207
216
}
208
- } else {
209
- i += 1 ;
210
217
}
211
-
212
- let mut input = input. clone ( ) ;
213
-
214
- start_timer ! ( state) ;
215
- let mutated = self . mutator_mut ( ) . mutate ( state, & mut input, i as i32 ) ?;
216
- mark_feature_time ! ( state, PerfFeature :: Mutate ) ;
217
-
218
- if mutated == MutationResult :: Skipped {
219
- continue ;
218
+ ( None , Some ( iters) ) => {
219
+ // perform n iterations
220
+ for i in 1 ..=iters {
221
+ self . perform_mutation ( fuzzer, executor, state, manager, & input, i) ?;
222
+ }
223
+ }
224
+ ( None , None ) => {
225
+ // fall back to random
226
+ let iters = self . iterations ( state, corpus_idx) ?;
227
+ for i in 1 ..=iters {
228
+ self . perform_mutation ( fuzzer, executor, state, manager, & input, i) ?;
229
+ }
220
230
}
221
-
222
- // Time is measured directly the `evaluate_input` function
223
- let ( untransformed, post) = input. try_transform_into ( state) ?;
224
- let ( _, corpus_idx) = fuzzer. evaluate_input ( state, executor, manager, untransformed) ?;
225
-
226
- start_timer ! ( state) ;
227
- self . mutator_mut ( ) . post_exec ( state, i as i32 , corpus_idx) ?;
228
- post. post_exec ( state, i as i32 , corpus_idx) ?;
229
- mark_feature_time ! ( state, PerfFeature :: MutatePostExec ) ;
230
231
}
231
232
Ok ( ( ) )
232
233
}
@@ -246,12 +247,10 @@ where
246
247
/// Gets the number of iterations as a random number
247
248
#[ allow( clippy:: cast_possible_truncation) ]
248
249
fn iterations ( & self , state : & mut Z :: State , _corpus_idx : CorpusId ) -> Result < u64 , Error > {
249
- Ok ( if let Some ( iters) = self . iters ( state) ? {
250
- iters
251
- } else {
250
+ Ok (
252
251
// fall back to random
253
- 1 + state. rand_mut ( ) . below ( DEFAULT_MUTATIONAL_MAX_ITERATIONS )
254
- } )
252
+ 1 + state. rand_mut ( ) . below ( DEFAULT_MUTATIONAL_MAX_ITERATIONS ) ,
253
+ )
255
254
}
256
255
}
257
256
@@ -302,6 +301,7 @@ where
302
301
M : Mutator < I , Z :: State > ,
303
302
Z : Evaluator < E , EM > ,
304
303
Z :: State : HasClientPerfMonitor + HasCorpus + HasRand + HasNamedMetadata + HasMetadata ,
304
+ I : MutatedTransform < Z :: Input , Z :: State > + Clone ,
305
305
{
306
306
/// Creates a new default tuneable mutational stage
307
307
#[ must_use]
@@ -335,20 +335,20 @@ where
335
335
set_iters_by_name ( state, iters, name)
336
336
}
337
337
338
- /// Get the set iterations for this [`TuneableMutationalStage`]
339
- pub fn iters < S > ( & self , state : & S ) -> Result < Option < u64 > , Error >
338
+ /// Get the set iterations for this [`TuneableMutationalStage`], if any
339
+ pub fn fixed_iters < S > ( & self , state : & S ) -> Result < Option < u64 > , Error >
340
340
where
341
341
S : HasNamedMetadata ,
342
342
{
343
343
get_iters_by_name ( state, & self . name )
344
344
}
345
345
346
- /// Get the set iterations for the std [`TuneableMutationalStage`]
346
+ /// Get the set iterations for the std [`TuneableMutationalStage`], if any
347
347
pub fn iters_std ( state : & Z :: State ) -> Result < Option < u64 > , Error > {
348
348
get_iters_by_name ( state, STD_TUNEABLE_MUTATIONAL_STAGE_NAME )
349
349
}
350
350
351
- /// Get the set iterations for the [`TuneableMutationalStage`] with the given name
351
+ /// Get the set iterations for the [`TuneableMutationalStage`] with the given name, if any
352
352
pub fn iters_by_name < S > ( state : & S , name : & str ) -> Result < Option < u64 > , Error >
353
353
where
354
354
S : HasNamedMetadata ,
@@ -426,6 +426,40 @@ where
426
426
{
427
427
reset_by_name ( state, name)
428
428
}
429
+
430
+ fn perform_mutation (
431
+ & mut self ,
432
+ fuzzer : & mut Z ,
433
+ executor : & mut E ,
434
+ state : & mut Z :: State ,
435
+ manager : & mut EM ,
436
+ input : & I ,
437
+ stage_idx : u64 ,
438
+ ) -> Result < ( ) , Error > {
439
+ let mut input = input. clone ( ) ;
440
+
441
+ start_timer ! ( state) ;
442
+ let mutated = self
443
+ . mutator_mut ( )
444
+ . mutate ( state, & mut input, stage_idx as i32 ) ?;
445
+ mark_feature_time ! ( state, PerfFeature :: Mutate ) ;
446
+
447
+ if mutated == MutationResult :: Skipped {
448
+ return Ok ( ( ) ) ;
449
+ }
450
+
451
+ // Time is measured directly the `evaluate_input` function
452
+ let ( untransformed, post) = input. try_transform_into ( state) ?;
453
+ let ( _, corpus_idx) = fuzzer. evaluate_input ( state, executor, manager, untransformed) ?;
454
+
455
+ start_timer ! ( state) ;
456
+ self . mutator_mut ( )
457
+ . post_exec ( state, stage_idx as i32 , corpus_idx) ?;
458
+ post. post_exec ( state, stage_idx as i32 , corpus_idx) ?;
459
+ mark_feature_time ! ( state, PerfFeature :: MutatePostExec ) ;
460
+
461
+ Ok ( ( ) )
462
+ }
429
463
}
430
464
431
465
impl < E , EM , I , M , Z > TuneableMutationalStage < E , EM , I , M , Z >
0 commit comments