Metadata + infinite loop fix for TuneableMutationalStage (#1514)
* update tuneable: consistently access metadata + force 'choice' * oops, loop in the wrong place * clarify API some; allow for least of set configuration
This commit is contained in:
parent
d4f47340a3
commit
6d0d4e287a
@ -175,16 +175,14 @@ where
|
|||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
corpus_idx: CorpusId,
|
corpus_idx: CorpusId,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let metadata: &TuneableMutationalStageMetadata = state.metadata()?;
|
let fuzz_time = self.seed_fuzz_time(state)?;
|
||||||
|
let iters = self.fixed_iters(state)?;
|
||||||
|
|
||||||
let fuzz_time = metadata.fuzz_time;
|
if fuzz_time.is_some() && iters.is_some() {
|
||||||
let iters = metadata.iters;
|
return Err(Error::illegal_state(
|
||||||
|
"Both fuzz_time and iters specified; failing fast!",
|
||||||
let (start_time, iters) = if fuzz_time.is_some() {
|
));
|
||||||
(Some(current_time()), iters)
|
}
|
||||||
} else {
|
|
||||||
(None, Some(self.iterations(state, corpus_idx)?))
|
|
||||||
};
|
|
||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut();
|
let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut();
|
||||||
@ -194,39 +192,42 @@ where
|
|||||||
drop(testcase);
|
drop(testcase);
|
||||||
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
|
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
|
||||||
|
|
||||||
let mut i = 0_usize;
|
match (fuzz_time, iters) {
|
||||||
loop {
|
(Some(fuzz_time), Some(iters)) => {
|
||||||
if let Some(start_time) = start_time {
|
// perform n iterations or fuzz for provided time, whichever comes first
|
||||||
if current_time() - start_time >= fuzz_time.unwrap() {
|
let start_time = current_time();
|
||||||
break;
|
for i in 1..=iters {
|
||||||
|
if current_time() - start_time >= fuzz_time {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.perform_mutation(fuzzer, executor, state, manager, &input, i)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(iters) = iters {
|
(Some(fuzz_time), None) => {
|
||||||
if i >= iters as usize {
|
// fuzz for provided time
|
||||||
break;
|
let start_time = current_time();
|
||||||
|
for i in 1.. {
|
||||||
|
if current_time() - start_time >= fuzz_time {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.perform_mutation(fuzzer, executor, state, manager, &input, i)?;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
|
(None, Some(iters)) => {
|
||||||
let mut input = input.clone();
|
// perform n iterations
|
||||||
|
for i in 1..=iters {
|
||||||
start_timer!(state);
|
self.perform_mutation(fuzzer, executor, state, manager, &input, i)?;
|
||||||
let mutated = self.mutator_mut().mutate(state, &mut input, i as i32)?;
|
}
|
||||||
mark_feature_time!(state, PerfFeature::Mutate);
|
}
|
||||||
|
(None, None) => {
|
||||||
if mutated == MutationResult::Skipped {
|
// fall back to random
|
||||||
continue;
|
let iters = self.iterations(state, corpus_idx)?;
|
||||||
|
for i in 1..=iters {
|
||||||
|
self.perform_mutation(fuzzer, executor, state, manager, &input, i)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time is measured directly the `evaluate_input` function
|
|
||||||
let (untransformed, post) = input.try_transform_into(state)?;
|
|
||||||
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, untransformed)?;
|
|
||||||
|
|
||||||
start_timer!(state);
|
|
||||||
self.mutator_mut().post_exec(state, i as i32, corpus_idx)?;
|
|
||||||
post.post_exec(state, i as i32, corpus_idx)?;
|
|
||||||
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -246,12 +247,10 @@ where
|
|||||||
/// Gets the number of iterations as a random number
|
/// Gets the number of iterations as a random number
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
fn iterations(&self, state: &mut Z::State, _corpus_idx: CorpusId) -> Result<u64, Error> {
|
fn iterations(&self, state: &mut Z::State, _corpus_idx: CorpusId) -> Result<u64, Error> {
|
||||||
Ok(if let Some(iters) = self.iters(state)? {
|
Ok(
|
||||||
iters
|
|
||||||
} else {
|
|
||||||
// fall back to random
|
// fall back to random
|
||||||
1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS)
|
1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS),
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,6 +301,7 @@ where
|
|||||||
M: Mutator<I, Z::State>,
|
M: Mutator<I, Z::State>,
|
||||||
Z: Evaluator<E, EM>,
|
Z: Evaluator<E, EM>,
|
||||||
Z::State: HasClientPerfMonitor + HasCorpus + HasRand + HasNamedMetadata + HasMetadata,
|
Z::State: HasClientPerfMonitor + HasCorpus + HasRand + HasNamedMetadata + HasMetadata,
|
||||||
|
I: MutatedTransform<Z::Input, Z::State> + Clone,
|
||||||
{
|
{
|
||||||
/// Creates a new default tuneable mutational stage
|
/// Creates a new default tuneable mutational stage
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -335,20 +335,20 @@ where
|
|||||||
set_iters_by_name(state, iters, name)
|
set_iters_by_name(state, iters, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the set iterations for this [`TuneableMutationalStage`]
|
/// Get the set iterations for this [`TuneableMutationalStage`], if any
|
||||||
pub fn iters<S>(&self, state: &S) -> Result<Option<u64>, Error>
|
pub fn fixed_iters<S>(&self, state: &S) -> Result<Option<u64>, Error>
|
||||||
where
|
where
|
||||||
S: HasNamedMetadata,
|
S: HasNamedMetadata,
|
||||||
{
|
{
|
||||||
get_iters_by_name(state, &self.name)
|
get_iters_by_name(state, &self.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the set iterations for the std [`TuneableMutationalStage`]
|
/// Get the set iterations for the std [`TuneableMutationalStage`], if any
|
||||||
pub fn iters_std(state: &Z::State) -> Result<Option<u64>, Error> {
|
pub fn iters_std(state: &Z::State) -> Result<Option<u64>, Error> {
|
||||||
get_iters_by_name(state, STD_TUNEABLE_MUTATIONAL_STAGE_NAME)
|
get_iters_by_name(state, STD_TUNEABLE_MUTATIONAL_STAGE_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the set iterations for the [`TuneableMutationalStage`] with the given name
|
/// Get the set iterations for the [`TuneableMutationalStage`] with the given name, if any
|
||||||
pub fn iters_by_name<S>(state: &S, name: &str) -> Result<Option<u64>, Error>
|
pub fn iters_by_name<S>(state: &S, name: &str) -> Result<Option<u64>, Error>
|
||||||
where
|
where
|
||||||
S: HasNamedMetadata,
|
S: HasNamedMetadata,
|
||||||
@ -426,6 +426,40 @@ where
|
|||||||
{
|
{
|
||||||
reset_by_name(state, name)
|
reset_by_name(state, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn perform_mutation(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
executor: &mut E,
|
||||||
|
state: &mut Z::State,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
stage_idx: u64,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut input = input.clone();
|
||||||
|
|
||||||
|
start_timer!(state);
|
||||||
|
let mutated = self
|
||||||
|
.mutator_mut()
|
||||||
|
.mutate(state, &mut input, stage_idx as i32)?;
|
||||||
|
mark_feature_time!(state, PerfFeature::Mutate);
|
||||||
|
|
||||||
|
if mutated == MutationResult::Skipped {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time is measured directly the `evaluate_input` function
|
||||||
|
let (untransformed, post) = input.try_transform_into(state)?;
|
||||||
|
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, untransformed)?;
|
||||||
|
|
||||||
|
start_timer!(state);
|
||||||
|
self.mutator_mut()
|
||||||
|
.post_exec(state, stage_idx as i32, corpus_idx)?;
|
||||||
|
post.post_exec(state, stage_idx as i32, corpus_idx)?;
|
||||||
|
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, I, M, Z> TuneableMutationalStage<E, EM, I, M, Z>
|
impl<E, EM, I, M, Z> TuneableMutationalStage<E, EM, I, M, Z>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user