Refcnt for MapIndexesMetadata (#348)

* refcnt for MapIndexesMetadata

* fix clippy
This commit is contained in:
Andrea Fioraldi 2021-11-05 12:14:57 +01:00 committed by GitHub
parent bf67b6ca76
commit d1700f8775
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 14 deletions

View File

@ -13,8 +13,8 @@ use libafl::{
tuples::{tuple_list, Merge}, tuples::{tuple_list, Merge},
}, },
corpus::{ corpus::{
ondisk::OnDiskMetadataFormat, Corpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, ondisk::OnDiskMetadataFormat, CachedOnDiskCorpus, Corpus,
QueueCorpusScheduler, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler,
}, },
events::{llmp::LlmpRestartingEventManager, EventConfig}, events::{llmp::LlmpRestartingEventManager, EventConfig},
executors::{ executors::{
@ -347,7 +347,7 @@ unsafe fn fuzz(
// RNG // RNG
StdRand::with_seed(current_nanos()), StdRand::with_seed(current_nanos()),
// Corpus that will be evolved, we keep it in memory for performance // Corpus that will be evolved, we keep it in memory for performance
OnDiskCorpus::new(PathBuf::from("./corpus_discovered")).unwrap(), CachedOnDiskCorpus::new(PathBuf::from("./corpus_discovered"), 64).unwrap(),
// Corpus in which we store solutions (crashes in this example), // Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer // on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new_save_meta( OnDiskCorpus::new_save_meta(

View File

@ -38,6 +38,11 @@ pub trait HasLen {
} }
} }
pub trait HasRefCnt {
fn refcnt(&self) -> isize;
fn refcnt_mut(&mut self) -> &mut isize;
}
/// Current time /// Current time
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[must_use] #[must_use]

View File

@ -2,7 +2,7 @@
// with testcases only from a subset of the total corpus. // with testcases only from a subset of the total corpus.
use crate::{ use crate::{
bolts::{rands::Rand, serdeany::SerdeAny, AsSlice, HasLen}, bolts::{rands::Rand, serdeany::SerdeAny, AsSlice, HasLen, HasRefCnt},
corpus::{Corpus, CorpusScheduler, Testcase}, corpus::{Corpus, CorpusScheduler, Testcase},
feedbacks::MapIndexesMetadata, feedbacks::MapIndexesMetadata,
inputs::Input, inputs::Input,
@ -84,7 +84,7 @@ where
CS: CorpusScheduler<I, S>, CS: CorpusScheduler<I, S>,
F: FavFactor<I>, F: FavFactor<I>,
I: Input, I: Input,
M: AsSlice<usize> + SerdeAny, M: AsSlice<usize> + SerdeAny + HasRefCnt,
S: HasCorpus<C, I> + HasMetadata, S: HasCorpus<C, I> + HasMetadata,
C: Corpus<I>, C: Corpus<I>,
{ {
@ -98,7 +98,7 @@ where
CS: CorpusScheduler<I, S>, CS: CorpusScheduler<I, S>,
F: FavFactor<I>, F: FavFactor<I>,
I: Input, I: Input,
M: AsSlice<usize> + SerdeAny, M: AsSlice<usize> + SerdeAny + HasRefCnt,
S: HasCorpus<C, I> + HasMetadata + HasRand<R>, S: HasCorpus<C, I> + HasMetadata + HasRand<R>,
C: Corpus<I>, C: Corpus<I>,
R: Rand, R: Rand,
@ -148,13 +148,14 @@ where
CS: CorpusScheduler<I, S>, CS: CorpusScheduler<I, S>,
F: FavFactor<I>, F: FavFactor<I>,
I: Input, I: Input,
M: AsSlice<usize> + SerdeAny, M: AsSlice<usize> + SerdeAny + HasRefCnt,
S: HasCorpus<C, I> + HasMetadata + HasRand<R>, S: HasCorpus<C, I> + HasMetadata + HasRand<R>,
C: Corpus<I>, C: Corpus<I>,
R: Rand, R: Rand,
{ {
/// Update the `Corpus` score using the `MinimizerCorpusScheduler` /// Update the `Corpus` score using the `MinimizerCorpusScheduler`
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
#[allow(clippy::cast_possible_wrap)]
pub fn update_score(&self, state: &mut S, idx: usize) -> Result<(), Error> { pub fn update_score(&self, state: &mut S, idx: usize) -> Result<(), Error> {
// Create a new top rated meta if not existing // Create a new top rated meta if not existing
if state.metadata().get::<TopRatedsMetadata>().is_none() { if state.metadata().get::<TopRatedsMetadata>().is_none() {
@ -165,7 +166,7 @@ where
{ {
let mut entry = state.corpus().get(idx)?.borrow_mut(); let mut entry = state.corpus().get(idx)?.borrow_mut();
let factor = F::compute(&mut *entry)?; let factor = F::compute(&mut *entry)?;
let meta = entry.metadata().get::<M>().ok_or_else(|| { let meta = entry.metadata_mut().get_mut::<M>().ok_or_else(|| {
Error::KeyNotFound(format!( Error::KeyNotFound(format!(
"Metadata needed for MinimizerCorpusScheduler not found in testcase #{}", "Metadata needed for MinimizerCorpusScheduler not found in testcase #{}",
idx idx
@ -179,22 +180,52 @@ where
.map .map
.get(elem) .get(elem)
{ {
if factor > F::compute(&mut *state.corpus().get(*old_idx)?.borrow_mut())? { let mut old = state.corpus().get(*old_idx)?.borrow_mut();
if factor > F::compute(&mut *old)? {
continue; continue;
} }
let must_remove = {
let old_meta = old.metadata_mut().get_mut::<M>().ok_or_else(|| {
Error::KeyNotFound(format!(
"Metadata needed for MinimizerCorpusScheduler not found in testcase #{}",
old_idx
))
})?;
*old_meta.refcnt_mut() -= 1;
old_meta.refcnt() <= 0
};
if must_remove {
drop(old.metadata_mut().remove::<M>());
}
} }
new_favoreds.push((*elem, idx)); new_favoreds.push(*elem);
} }
*meta.refcnt_mut() = new_favoreds.len() as isize;
} }
for pair in new_favoreds { if new_favoreds.is_empty() {
drop(
state
.corpus()
.get(idx)?
.borrow_mut()
.metadata_mut()
.remove::<M>(),
);
return Ok(());
}
for elem in new_favoreds {
state state
.metadata_mut() .metadata_mut()
.get_mut::<TopRatedsMetadata>() .get_mut::<TopRatedsMetadata>()
.unwrap() .unwrap()
.map .map
.insert(pair.0, pair.1); .insert(elem, idx);
} }
Ok(()) Ok(())
} }

View File

@ -9,7 +9,7 @@ use num::Integer;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
bolts::{tuples::Named, AsSlice}, bolts::{tuples::Named, AsSlice, HasRefCnt},
corpus::Testcase, corpus::Testcase,
events::{Event, EventFirer}, events::{Event, EventFirer},
executors::ExitKind, executors::ExitKind,
@ -76,6 +76,8 @@ where
pub struct MapIndexesMetadata { pub struct MapIndexesMetadata {
/// The list of indexes. /// The list of indexes.
pub list: Vec<usize>, pub list: Vec<usize>,
/// A refcount used to know when remove this meta
pub tcref: isize,
} }
crate::impl_serdeany!(MapIndexesMetadata); crate::impl_serdeany!(MapIndexesMetadata);
@ -87,11 +89,21 @@ impl AsSlice<usize> for MapIndexesMetadata {
} }
} }
impl HasRefCnt for MapIndexesMetadata {
fn refcnt(&self) -> isize {
self.tcref
}
fn refcnt_mut(&mut self) -> &mut isize {
&mut self.tcref
}
}
impl MapIndexesMetadata { impl MapIndexesMetadata {
/// Creates a new [`struct@MapIndexesMetadata`]. /// Creates a new [`struct@MapIndexesMetadata`].
#[must_use] #[must_use]
pub fn new(list: Vec<usize>) -> Self { pub fn new(list: Vec<usize>) -> Self {
Self { list } Self { list, tcref: 0 }
} }
} }