Skip to content

Commit c221108

Browse files
authored
Add MutatedTransform to the input type in TMinMutationalStage (#1251) (#1971)
* Support `MutatedTransform` in `TMinMutationalStage`. * Run `MutatedTransformPost` for the replaced testcase. * Add clone trait bound for `MutatedTransformPost`. * Return an error instead of using unwrap.
1 parent f0ee6e0 commit c221108

File tree

1 file changed

+47
-22
lines changed

1 file changed

+47
-22
lines changed

libafl/src/stages/tmin.rs

+47-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! The [`TMinMutationalStage`] is a stage which will attempt to minimize corpus entries.
22
33
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};
55

66
use ahash::RandomState;
77
use libafl_bolts::{HasLen, Named};
@@ -16,7 +16,10 @@ use crate::{
1616
mutators::{MutationResult, Mutator},
1717
observers::{MapObserver, ObserversTuple},
1818
schedulers::{RemovableScheduler, Scheduler},
19-
stages::{ExecutionCountRestartHelper, Stage},
19+
stages::{
20+
mutational::{MutatedTransform, MutatedTransformPost},
21+
ExecutionCountRestartHelper, Stage,
22+
},
2023
start_timer,
2124
state::{
2225
HasCorpus, HasCurrentTestcase, HasExecutions, HasMaxSize, HasMetadata, HasSolutions, State,
@@ -30,7 +33,7 @@ use crate::{monitors::PerfFeature, state::HasClientPerfMonitor};
3033
/// Mutational stage which minimizes corpus entries.
3134
///
3235
/// 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>:
3437
Stage<E, EM, Z> + FeedbackFactory<F2, CS::State, OT>
3538
where
3639
Self::State: HasCorpus + HasSolutions + HasExecutions + HasMaxSize,
@@ -40,12 +43,14 @@ where
4043
EM: EventFirer<State = Self::State>,
4144
F1: Feedback<Self::State>,
4245
F2: Feedback<Self::State>,
43-
M: Mutator<Self::Input, Self::State>,
46+
M: Mutator<I, Self::State>,
4447
OT: ObserversTuple<CS::State>,
4548
Z: ExecutionProcessor<OT, State = Self::State>
4649
+ ExecutesInput<E, EM>
4750
+ HasFeedback<Feedback = F1>
4851
+ HasScheduler<Scheduler = CS>,
52+
IP: MutatedTransformPost<Self::State> + Clone,
53+
I: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone,
4954
{
5055
/// The mutator registered for this stage
5156
fn mutator(&self) -> &M;
@@ -77,7 +82,10 @@ where
7782
- usize::try_from(self.execs_since_progress_start(state)?).unwrap();
7883

7984
start_timer!(state);
85+
let transformed = I::try_transform_from(state.current_testcase_mut()?.borrow_mut(), state)?;
8086
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;
8189
let base_hash = RandomState::with_seeds(0, 0, 0, 0).hash_one(&base);
8290
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
8391

@@ -93,20 +101,21 @@ where
93101
}
94102

95103
let mut next_i = i + 1;
96-
let mut input = base.clone();
104+
let mut input_transformed = transformed.clone();
97105

98-
let before_len = input.len();
106+
let before_len = base.len();
99107

100108
state.set_max_size(before_len);
101109

102110
start_timer!(state);
103-
let mutated = self.mutator_mut().mutate(state, &mut input)?;
111+
let mutated = self.mutator_mut().mutate(state, &mut input_transformed)?;
104112
mark_feature_time!(state, PerfFeature::Mutate);
105113

106114
if mutated == MutationResult::Skipped {
107115
continue;
108116
}
109117

118+
let (input, post) = input_transformed.try_transform_into(state)?;
110119
let corpus_idx = if input.len() < before_len {
111120
// run the input
112121
let exit_kind = fuzzer.execute_input(state, executor, manager, &input)?;
@@ -134,6 +143,7 @@ where
134143
if feedback.is_interesting(state, manager, &input, observers, &exit_kind)? {
135144
// we found a reduced corpus entry! use the smaller base
136145
base = input;
146+
base_post = Some(post.clone());
137147

138148
// do more runs! maybe we can minify further
139149
next_i = 0;
@@ -149,6 +159,7 @@ where
149159

150160
start_timer!(state);
151161
self.mutator_mut().post_exec(state, corpus_idx)?;
162+
post.post_exec(state, corpus_idx)?;
152163
mark_feature_time!(state, PerfFeature::MutatePostExec);
153164

154165
i = next_i;
@@ -171,6 +182,11 @@ where
171182
fuzzer
172183
.scheduler_mut()
173184
.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))?;
174190
}
175191

176192
state.set_max_size(orig_max_size);
@@ -184,7 +200,7 @@ where
184200

185201
/// The default corpus entry minimising mutational stage
186202
#[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> {
188204
/// The mutator(s) this stage uses
189205
mutator: M,
190206
/// The factory
@@ -194,22 +210,24 @@ pub struct StdTMinMutationalStage<CS, E, EM, F1, F2, FF, M, OT, Z> {
194210
/// The progress helper for this stage, keeping track of resumes after timeouts/crashes
195211
restart_helper: ExecutionCountRestartHelper,
196212
#[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)>,
198214
}
199215

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>
202218
where
203219
CS: Scheduler,
204-
M: Mutator<CS::Input, CS::State>,
220+
M: Mutator<I, CS::State>,
205221
Z: ExecutionProcessor<OT, State = CS::State>,
206222
CS::State: HasCorpus,
223+
IP: MutatedTransformPost<CS::State> + Clone,
224+
I: MutatedTransform<CS::Input, CS::State, Post = IP> + Clone,
207225
{
208226
type State = CS::State;
209227
}
210228

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>
213231
where
214232
CS: Scheduler + RemovableScheduler,
215233
CS::State: HasCorpus + HasSolutions + HasExecutions + HasMaxSize + HasCorpus + HasMetadata,
@@ -219,12 +237,14 @@ where
219237
F1: Feedback<CS::State>,
220238
F2: Feedback<CS::State>,
221239
FF: FeedbackFactory<F2, CS::State, OT>,
222-
M: Mutator<CS::Input, CS::State>,
240+
M: Mutator<I, CS::State>,
223241
OT: ObserversTuple<CS::State>,
224242
Z: ExecutionProcessor<OT, State = CS::State>
225243
+ ExecutesInput<E, EM>
226244
+ HasFeedback<Feedback = F1>
227245
+ HasScheduler<Scheduler = CS>,
246+
IP: MutatedTransformPost<CS::State> + Clone,
247+
I: MutatedTransform<CS::Input, CS::State, Post = IP> + Clone,
228248
{
229249
fn perform(
230250
&mut self,
@@ -250,8 +270,8 @@ where
250270
}
251271
}
252272

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>
255275
where
256276
F2: Feedback<Z::State>,
257277
FF: FeedbackFactory<F2, Z::State, OT>,
@@ -262,8 +282,8 @@ where
262282
}
263283
}
264284

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>
267287
where
268288
CS: Scheduler + RemovableScheduler,
269289
E: HasObservers<Observers = OT, State = CS::State> + Executor<EM, Z>,
@@ -272,13 +292,15 @@ where
272292
F2: Feedback<CS::State>,
273293
FF: FeedbackFactory<F2, CS::State, OT>,
274294
<CS::State as UsesInput>::Input: HasLen + Hash,
275-
M: Mutator<CS::Input, CS::State>,
295+
M: Mutator<I, CS::State>,
276296
OT: ObserversTuple<CS::State>,
277297
CS::State: HasCorpus + HasSolutions + HasExecutions + HasMaxSize + HasMetadata,
278298
Z: ExecutionProcessor<OT, State = CS::State>
279299
+ ExecutesInput<E, EM>
280300
+ HasFeedback<Feedback = F1>
281301
+ HasScheduler<Scheduler = CS>,
302+
IP: MutatedTransformPost<CS::State> + Clone,
303+
I: MutatedTransform<CS::Input, CS::State, Post = IP> + Clone,
282304
{
283305
/// The mutator, added to this stage
284306
#[inline]
@@ -302,12 +324,15 @@ where
302324
}
303325
}
304326

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>
306329
where
307330
CS: Scheduler,
308-
M: Mutator<CS::Input, CS::State>,
331+
M: Mutator<I, CS::State>,
309332
Z: ExecutionProcessor<OT, State = CS::State>,
310333
CS::State: HasCorpus,
334+
IP: MutatedTransformPost<CS::State> + Clone,
335+
I: MutatedTransform<CS::Input, CS::State, Post = IP> + Clone,
311336
{
312337
/// Creates a new minimizing mutational stage that will minimize provided corpus entries
313338
pub fn new(mutator: M, factory: FF, runs: usize) -> Self {

0 commit comments

Comments
 (0)