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:
Dongjia "toka" Zhang 2024-07-18 11:11:14 +02:00 committed by GitHub
parent 536f00a056
commit 4f970baa7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 27 deletions

View File

@ -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.

View File

@ -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;
} // skip the currently fuzzed id; don't remove it
do_retain.push(retain); // because else after restart we can't call currrent.next() to find the next testcase
if idx == currently_fuzzed_idx {
// eprintln!("skipping {:#?}", idx);
continue;
} }
// Make sure that at least somthing is in the let removed = state.corpus_mut().remove(idx)?;
if !retain_any { fuzzer
let r = state.rand_mut().below(n_corpus); .scheduler_mut()
do_retain[r] = true; .on_remove(state, idx, &Some(removed.clone()))?;
// because [n_enabled, n_all) is disabled testcases
// and [0, n_enabled) is enabled testcases
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));
} }
for (i_th, retain) in do_retain.iter().enumerate().take(n_corpus) {
if !retain {
let corpus_id = state.corpus().nth_from_all(i_th);
let corpus = state.corpus_mut();
let removed = corpus.remove(corpus_id)?;
corpus.add_disabled(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(())
} }