Change Corpus Pruning algorithm (#2418)
* push * upd * add last found time * add common as prerequisite * clp * aa * more clp * fix how to get corpus id * pruning * aa * no std * fix * working? * push
This commit is contained in:
parent
536f00a056
commit
4f970baa7b
@ -81,6 +81,7 @@ pub mod tuneable;
|
|||||||
pub mod unicode;
|
pub mod unicode;
|
||||||
|
|
||||||
pub mod pruning;
|
pub mod pruning;
|
||||||
|
pub use pruning::*;
|
||||||
|
|
||||||
/// A stage is one step in the fuzzing process.
|
/// A stage is one step in the fuzzing process.
|
||||||
/// Multiple stages will be scheduled one by one for each input.
|
/// Multiple stages will be scheduled one by one for each input.
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
//! Corpus pruning stage
|
//! Corpus pruning stage
|
||||||
|
|
||||||
|
use alloc::string::ToString;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use libafl_bolts::{rands::Rand, Error};
|
use libafl_bolts::{rands::Rand, Error};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::Corpus,
|
corpus::{Corpus, HasCurrentCorpusId},
|
||||||
|
schedulers::{RemovableScheduler, Scheduler},
|
||||||
stages::Stage,
|
stages::Stage,
|
||||||
state::{HasCorpus, HasRand, UsesState},
|
state::{HasCorpus, HasRand, UsesState},
|
||||||
|
HasScheduler,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use crate::{events::EventRestarter, state::Stoppable};
|
use crate::{events::EventRestarter, state::Stoppable};
|
||||||
@ -48,47 +51,76 @@ impl<E, EM, Z> Stage<E, EM, Z> for CorpusPruning<EM>
|
|||||||
where
|
where
|
||||||
EM: UsesState,
|
EM: UsesState,
|
||||||
E: UsesState<State = Self::State>,
|
E: UsesState<State = Self::State>,
|
||||||
Z: UsesState<State = Self::State>,
|
Z: UsesState<State = Self::State> + HasScheduler,
|
||||||
|
<Z as HasScheduler>::Scheduler: RemovableScheduler,
|
||||||
Self::State: HasCorpus + HasRand,
|
Self::State: HasCorpus + HasRand,
|
||||||
{
|
{
|
||||||
#[allow(clippy::cast_precision_loss)]
|
#[allow(clippy::cast_precision_loss)]
|
||||||
fn perform(
|
fn perform(
|
||||||
&mut self,
|
&mut self,
|
||||||
_fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
_executor: &mut E,
|
_executor: &mut E,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
_manager: &mut EM,
|
_manager: &mut EM,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Iterate over every corpus entry
|
// Iterate over every corpus entr
|
||||||
let n_corpus = state.corpus().count_all();
|
let n_all = state.corpus().count_all();
|
||||||
let mut do_retain = vec![];
|
let n_enabled = state.corpus().count();
|
||||||
let mut retain_any = false;
|
|
||||||
for _ in 0..n_corpus {
|
let Some(currently_fuzzed_idx) = state.current_corpus_id()? else {
|
||||||
|
return Err(Error::illegal_state("Not fuzzing any testcase".to_string()));
|
||||||
|
};
|
||||||
|
|
||||||
|
// eprintln!("Currently fuzzing {:#?}", currently_fuzzed_idx);
|
||||||
|
|
||||||
|
let mut disabled_to_enabled = vec![];
|
||||||
|
let mut enabled_to_disabled = vec![];
|
||||||
|
// do it backwards so that the index won't change even after remove
|
||||||
|
for i in (0..n_all).rev() {
|
||||||
let r = state.rand_mut().below(100) as f64;
|
let r = state.rand_mut().below(100) as f64;
|
||||||
let retain = self.prob * 100_f64 < r;
|
if self.prob * 100_f64 < r {
|
||||||
if retain {
|
let idx = state.corpus().nth_from_all(i);
|
||||||
retain_any = true;
|
|
||||||
}
|
|
||||||
do_retain.push(retain);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that at least somthing is in the
|
// skip the currently fuzzed id; don't remove it
|
||||||
if !retain_any {
|
// because else after restart we can't call currrent.next() to find the next testcase
|
||||||
let r = state.rand_mut().below(n_corpus);
|
if idx == currently_fuzzed_idx {
|
||||||
do_retain[r] = true;
|
// eprintln!("skipping {:#?}", idx);
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (i_th, retain) in do_retain.iter().enumerate().take(n_corpus) {
|
let removed = state.corpus_mut().remove(idx)?;
|
||||||
if !retain {
|
fuzzer
|
||||||
let corpus_id = state.corpus().nth_from_all(i_th);
|
.scheduler_mut()
|
||||||
|
.on_remove(state, idx, &Some(removed.clone()))?;
|
||||||
let corpus = state.corpus_mut();
|
// because [n_enabled, n_all) is disabled testcases
|
||||||
let removed = corpus.remove(corpus_id)?;
|
// and [0, n_enabled) is enabled testcases
|
||||||
corpus.add_disabled(removed)?;
|
if i >= n_enabled {
|
||||||
|
// we are moving disabled to enabled now
|
||||||
|
disabled_to_enabled.push((idx, removed));
|
||||||
|
} else {
|
||||||
|
// we are moving enabled to disabled now
|
||||||
|
enabled_to_disabled.push((idx, removed));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// println!("There was {}, and we retained {} corpura", n_corpus, state.corpus().count());
|
// Actually move them
|
||||||
|
for (idx, testcase) in disabled_to_enabled {
|
||||||
|
state.corpus_mut().add(testcase)?;
|
||||||
|
fuzzer.scheduler_mut().on_add(state, idx)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx, testcase) in enabled_to_disabled {
|
||||||
|
state.corpus_mut().add_disabled(testcase)?;
|
||||||
|
fuzzer.scheduler_mut().on_add(state, idx)?;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
eprintln!(
|
||||||
|
"There was {}, and we retained {} corpura",
|
||||||
|
n_all,
|
||||||
|
state.corpus().count()
|
||||||
|
);
|
||||||
|
*/
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user