Call all Ids id, not idx (#2319)

* All Ids should be id not idx

* More

* fix

* win?

* win?

* win?

* fix

* more fix

* desyscall?

* more

* fmt

* std

* make id less id-y

* fmt

* fix

* cleanup

* fixes all around

* fix

* Fix the broken stuff from refactoring

* remove unused

---------

Co-authored-by: Dongjia "toka" Zhang <tokazerkje@outlook.com>
This commit is contained in:
Dominik Maier 2024-06-20 14:46:47 +01:00 committed by GitHub
parent a2da080fa6
commit 042840dba1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
55 changed files with 508 additions and 486 deletions

View File

@ -138,7 +138,9 @@ pub fn main() -> Result<(), Error> {
state.load_initial_inputs_forced(&mut fuzzer, &mut executor, &mut mgr, &[solution_dir])?;
state.set_corpus_idx(CorpusId::from(0_usize))?;
let first_id = state.corpus().first().expect("Empty corpus");
state.set_corpus_id(first_id)?;
stages.perform_all(&mut fuzzer, &mut executor, &mut state, &mut mgr)?;
Ok(())

View File

@ -1,7 +1,10 @@
use std::hash::Hash;
use lain::prelude::*;
use libafl::inputs::{HasTargetBytes, Input};
use libafl::{
corpus::CorpusId,
inputs::{HasTargetBytes, Input},
};
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
use serde::{Deserialize, Serialize};
@ -45,8 +48,12 @@ pub enum PacketType {
}
impl Input for PacketData {
fn generate_name(&self, idx: usize) -> String {
format!("id_{idx}")
fn generate_name(&self, id: Option<CorpusId>) -> String {
if let Some(id) = id {
format!("id_{}", id.0)
} else {
"id_unknown".into()
}
}
}

View File

@ -44,7 +44,7 @@ where
fn cache_testcase<'a>(
&'a self,
testcase: &'a RefCell<Testcase<I>>,
idx: CorpusId,
id: CorpusId,
) -> Result<(), Error> {
if testcase.borrow().input().is_none() {
self.load_input_into(&mut testcase.borrow_mut())?;
@ -62,7 +62,7 @@ where
}
}
}
self.cached_indexes.borrow_mut().push_back(idx);
self.cached_indexes.borrow_mut().push_back(id);
}
Ok(())
}
@ -102,30 +102,30 @@ where
/// Replaces the testcase at the given idx
#[inline]
fn replace(&mut self, idx: CorpusId, testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
// TODO finish
self.inner.replace(idx, testcase)
self.inner.replace(id, testcase)
}
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases.
fn remove(&mut self, idx: CorpusId) -> Result<Testcase<Self::Input>, Error> {
let testcase = self.inner.remove(idx)?;
self.cached_indexes.borrow_mut().retain(|e| *e != idx);
fn remove(&mut self, id: CorpusId) -> Result<Testcase<Self::Input>, Error> {
let testcase = self.inner.remove(id)?;
self.cached_indexes.borrow_mut().retain(|e| *e != id);
Ok(testcase)
}
/// Get by id; considers only enabled testcases
#[inline]
fn get(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
let testcase = { self.inner.get(idx)? };
self.cache_testcase(testcase, idx)?;
fn get(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
let testcase = { self.inner.get(id)? };
self.cache_testcase(testcase, id)?;
Ok(testcase)
}
/// Get by id; considers both enabled and disabled testcases
#[inline]
fn get_from_all(&self, idx: CorpusId) -> Result<&RefCell<Testcase<Self::Input>>, Error> {
let testcase = { self.inner.get_from_all(idx)? };
self.cache_testcase(testcase, idx)?;
fn get_from_all(&self, id: CorpusId) -> Result<&RefCell<Testcase<Self::Input>>, Error> {
let testcase = { self.inner.get_from_all(id)? };
self.cache_testcase(testcase, id)?;
Ok(testcase)
}
@ -142,8 +142,8 @@ where
}
#[inline]
fn next(&self, idx: CorpusId) -> Option<CorpusId> {
self.inner.next(idx)
fn next(&self, id: CorpusId) -> Option<CorpusId> {
self.inner.next(id)
}
/// Peek the next free corpus id
@ -153,8 +153,8 @@ where
}
#[inline]
fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
self.inner.prev(idx)
fn prev(&self, id: CorpusId) -> Option<CorpusId> {
self.inner.prev(id)
}
#[inline]

View File

@ -43,12 +43,12 @@ where
pub map: alloc::collections::btree_map::BTreeMap<CorpusId, RefCell<Testcase<I>>>,
/// The keys in order (use `Vec::binary_search`)
pub keys: Vec<CorpusId>,
/// First inserted idx
/// First inserted id
#[cfg(not(feature = "corpus_btreemap"))]
first_idx: Option<CorpusId>,
/// Last inserted idx
first_id: Option<CorpusId>,
/// Last inserted id
#[cfg(not(feature = "corpus_btreemap"))]
last_idx: Option<CorpusId>,
last_id: Option<CorpusId>,
}
impl<I> TestcaseStorageMap<I>
@ -71,8 +71,8 @@ where
/// Replace a testcase given a `CorpusId`
#[cfg(not(feature = "corpus_btreemap"))]
pub fn replace(&mut self, idx: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
if let Some(entry) = self.map.get_mut(&idx) {
pub fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
if let Some(entry) = self.map.get_mut(&id) {
Some(entry.testcase.replace(testcase))
} else {
None
@ -81,26 +81,26 @@ where
/// Replace a testcase given a `CorpusId`
#[cfg(feature = "corpus_btreemap")]
pub fn replace(&mut self, idx: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
self.map.get_mut(&idx).map(|entry| entry.replace(testcase))
pub fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
self.map.get_mut(&id).map(|entry| entry.replace(testcase))
}
/// Remove a testcase given a `CorpusId`
/// Remove a testcase given a [`CorpusId`]
#[cfg(not(feature = "corpus_btreemap"))]
pub fn remove(&mut self, idx: CorpusId) -> Option<RefCell<Testcase<I>>> {
if let Some(item) = self.map.remove(&idx) {
self.remove_key(idx);
pub fn remove(&mut self, id: CorpusId) -> Option<RefCell<Testcase<I>>> {
if let Some(item) = self.map.remove(&id) {
self.remove_key(id);
if let Some(prev) = item.prev {
self.map.get_mut(&prev).unwrap().next = item.next;
} else {
// first elem
self.first_idx = item.next;
self.first_id = item.next;
}
if let Some(next) = item.next {
self.map.get_mut(&next).unwrap().prev = item.prev;
} else {
// last elem
self.last_idx = item.prev;
self.last_id = item.prev;
}
Some(item.testcase)
} else {
@ -108,32 +108,32 @@ where
}
}
/// Remove a testcase given a `CorpusId`
/// Remove a testcase given a [`CorpusId`]
#[cfg(feature = "corpus_btreemap")]
pub fn remove(&mut self, idx: CorpusId) -> Option<RefCell<Testcase<I>>> {
self.remove_key(idx);
self.map.remove(&idx)
pub fn remove(&mut self, id: CorpusId) -> Option<RefCell<Testcase<I>>> {
self.remove_key(id);
self.map.remove(&id)
}
/// Get a testcase given a `CorpusId`
#[cfg(not(feature = "corpus_btreemap"))]
#[must_use]
pub fn get(&self, idx: CorpusId) -> Option<&RefCell<Testcase<I>>> {
self.map.get(&idx).as_ref().map(|x| &x.testcase)
pub fn get(&self, id: CorpusId) -> Option<&RefCell<Testcase<I>>> {
self.map.get(&id).as_ref().map(|x| &x.testcase)
}
/// Get a testcase given a `CorpusId`
#[cfg(feature = "corpus_btreemap")]
#[must_use]
pub fn get(&self, idx: CorpusId) -> Option<&RefCell<Testcase<I>>> {
self.map.get(&idx)
pub fn get(&self, id: CorpusId) -> Option<&RefCell<Testcase<I>>> {
self.map.get(&id)
}
/// Get the next id given a `CorpusId` (creation order)
#[cfg(not(feature = "corpus_btreemap"))]
#[must_use]
pub fn next(&self, idx: CorpusId) -> Option<CorpusId> {
if let Some(item) = self.map.get(&idx) {
pub fn next(&self, id: CorpusId) -> Option<CorpusId> {
if let Some(item) = self.map.get(&id) {
item.next
} else {
None
@ -143,13 +143,13 @@ where
/// Get the next id given a `CorpusId` (creation order)
#[cfg(feature = "corpus_btreemap")]
#[must_use]
pub fn next(&self, idx: CorpusId) -> Option<CorpusId> {
pub fn next(&self, id: CorpusId) -> Option<CorpusId> {
// TODO see if using self.keys is faster
let mut range = self
.map
.range((core::ops::Bound::Included(idx), core::ops::Bound::Unbounded));
.range((core::ops::Bound::Included(id), core::ops::Bound::Unbounded));
if let Some((this_id, _)) = range.next() {
if idx != *this_id {
if id != *this_id {
return None;
}
}
@ -163,8 +163,8 @@ where
/// Get the previous id given a `CorpusId` (creation order)
#[cfg(not(feature = "corpus_btreemap"))]
#[must_use]
pub fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
if let Some(item) = self.map.get(&idx) {
pub fn prev(&self, id: CorpusId) -> Option<CorpusId> {
if let Some(item) = self.map.get(&id) {
item.prev
} else {
None
@ -174,13 +174,13 @@ where
/// Get the previous id given a `CorpusId` (creation order)
#[cfg(feature = "corpus_btreemap")]
#[must_use]
pub fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
pub fn prev(&self, id: CorpusId) -> Option<CorpusId> {
// TODO see if using self.keys is faster
let mut range = self
.map
.range((core::ops::Bound::Unbounded, core::ops::Bound::Included(idx)));
.range((core::ops::Bound::Unbounded, core::ops::Bound::Included(id)));
if let Some((this_id, _)) = range.next_back() {
if idx != *this_id {
if id != *this_id {
return None;
}
}
@ -195,7 +195,7 @@ where
#[cfg(not(feature = "corpus_btreemap"))]
#[must_use]
pub fn first(&self) -> Option<CorpusId> {
self.first_idx
self.first_id
}
/// Get the first created id
@ -209,7 +209,7 @@ where
#[cfg(not(feature = "corpus_btreemap"))]
#[must_use]
pub fn last(&self) -> Option<CorpusId> {
self.last_idx
self.last_id
}
/// Get the last created id
@ -227,9 +227,9 @@ where
map: alloc::collections::BTreeMap::default(),
keys: Vec::default(),
#[cfg(not(feature = "corpus_btreemap"))]
first_idx: None,
first_id: None,
#[cfg(not(feature = "corpus_btreemap"))]
last_idx: None,
last_id: None,
}
}
}
@ -244,8 +244,8 @@ where
pub enabled: TestcaseStorageMap<I>,
/// The map in which disabled testcases are stored
pub disabled: TestcaseStorageMap<I>,
/// The progressive idx for both maps
progressive_idx: usize,
/// The progressive id for both maps
progressive_id: usize,
}
impl<I> UsesInput for TestcaseStorage<I>
@ -267,58 +267,59 @@ where
#[must_use]
/// Peek the next free corpus id
pub fn peek_free_id(&self) -> CorpusId {
CorpusId::from(self.progressive_idx)
CorpusId::from(self.progressive_id)
}
/// Insert a testcase assigning a `CorpusId` to it
pub fn insert_disabled(&mut self, testcase: RefCell<Testcase<I>>) -> CorpusId {
self._insert(testcase, true)
}
/// Insert a testcase assigning a `CorpusId` to it
#[cfg(not(feature = "corpus_btreemap"))]
fn _insert(&mut self, testcase: RefCell<Testcase<I>>, is_disabled: bool) -> CorpusId {
let idx = CorpusId::from(self.progressive_idx);
self.progressive_idx += 1;
let id = CorpusId::from(self.progressive_id);
self.progressive_id += 1;
let corpus = if is_disabled {
&mut self.disabled
} else {
&mut self.enabled
};
let prev = if let Some(last_idx) = corpus.last_idx {
corpus.map.get_mut(&last_idx).unwrap().next = Some(idx);
Some(last_idx)
let prev = if let Some(last_id) = corpus.last_id {
corpus.map.get_mut(&last_id).unwrap().next = Some(id);
Some(last_id)
} else {
None
};
if corpus.first_idx.is_none() {
corpus.first_idx = Some(idx);
if corpus.first_id.is_none() {
corpus.first_id = Some(id);
}
corpus.last_idx = Some(idx);
corpus.insert_key(idx);
corpus.last_id = Some(id);
corpus.insert_key(id);
corpus.map.insert(
idx,
id,
TestcaseStorageItem {
testcase,
prev,
next: None,
},
);
idx
id
}
/// Insert a testcase assigning a `CorpusId` to it
#[cfg(feature = "corpus_btreemap")]
fn _insert(&mut self, testcase: RefCell<Testcase<I>>, is_disabled: bool) -> CorpusId {
let idx = CorpusId::from(self.progressive_idx);
self.progressive_idx += 1;
let id = CorpusId::from(self.progressive_id);
self.progressive_id += 1;
let corpus = if is_disabled {
&mut self.disabled
} else {
&mut self.enabled
};
corpus.insert_key(idx);
corpus.map.insert(idx, testcase);
idx
corpus.insert_key(id);
corpus.map.insert(id, testcase);
id
}
/// Create new `TestcaseStorage`
@ -327,7 +328,7 @@ where
Self {
enabled: TestcaseStorageMap::new(),
disabled: TestcaseStorageMap::new(),
progressive_idx: 0,
progressive_id: 0,
}
}
}
@ -387,43 +388,42 @@ where
Ok(self.storage.insert_disabled(RefCell::new(testcase)))
}
/// Replaces the testcase at the given idx
/// Replaces the testcase at the given id
#[inline]
fn replace(&mut self, idx: CorpusId, testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
self.storage
.enabled
.replace(idx, testcase)
.ok_or_else(|| Error::key_not_found(format!("Index {idx} not found")))
fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
self.storage.enabled.replace(id, testcase).ok_or_else(|| {
Error::key_not_found(format!("Index {id} not found, could not replace."))
})
}
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases
#[inline]
fn remove(&mut self, idx: CorpusId) -> Result<Testcase<Self::Input>, Error> {
let mut testcase = self.storage.enabled.remove(idx);
fn remove(&mut self, id: CorpusId) -> Result<Testcase<Self::Input>, Error> {
let mut testcase = self.storage.enabled.remove(id);
if testcase.is_none() {
testcase = self.storage.disabled.remove(idx);
testcase = self.storage.disabled.remove(id);
}
testcase
.map(|x| x.take())
.ok_or_else(|| Error::key_not_found(format!("Index {idx} not found")))
.ok_or_else(|| Error::key_not_found(format!("Index {id} not found")))
}
/// Get by id; considers only enabled testcases
#[inline]
fn get(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
fn get(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.storage
.enabled
.get(idx)
.ok_or_else(|| Error::key_not_found(format!("Index {idx} not found")))
.get(id)
.ok_or_else(|| Error::key_not_found(format!("Index {id} not found")))
}
/// Get by id; considers both enabled and disabled testcases
#[inline]
fn get_from_all(&self, idx: CorpusId) -> Result<&RefCell<Testcase<Self::Input>>, Error> {
let mut testcase = self.storage.enabled.get(idx);
fn get_from_all(&self, id: CorpusId) -> Result<&RefCell<Testcase<Self::Input>>, Error> {
let mut testcase = self.storage.enabled.get(id);
if testcase.is_none() {
testcase = self.storage.disabled.get(idx);
testcase = self.storage.disabled.get(id);
}
testcase.ok_or_else(|| Error::key_not_found(format!("Index {idx} not found")))
testcase.ok_or_else(|| Error::key_not_found(format!("Index {id} not found")))
}
/// Current testcase scheduled
@ -445,13 +445,13 @@ where
}
#[inline]
fn next(&self, idx: CorpusId) -> Option<CorpusId> {
self.storage.enabled.next(idx)
fn next(&self, id: CorpusId) -> Option<CorpusId> {
self.storage.enabled.next(id)
}
#[inline]
fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
self.storage.enabled.prev(idx)
fn prev(&self, id: CorpusId) -> Option<CorpusId> {
self.storage.enabled.prev(id)
}
#[inline]

View File

@ -74,52 +74,52 @@ where
/// Add an enabled testcase to the corpus and return its index
#[inline]
fn add(&mut self, testcase: Testcase<I>) -> Result<CorpusId, Error> {
let idx = self.inner.add(testcase)?;
let testcase = &mut self.get(idx).unwrap().borrow_mut();
self.save_testcase(testcase, idx)?;
let id = self.inner.add(testcase)?;
let testcase = &mut self.get(id).unwrap().borrow_mut();
self.save_testcase(testcase, id)?;
*testcase.input_mut() = None;
Ok(idx)
Ok(id)
}
/// Add a disabled testcase to the corpus and return its index
#[inline]
fn add_disabled(&mut self, testcase: Testcase<I>) -> Result<CorpusId, Error> {
let idx = self.inner.add_disabled(testcase)?;
let testcase = &mut self.get_from_all(idx).unwrap().borrow_mut();
self.save_testcase(testcase, idx)?;
let id = self.inner.add_disabled(testcase)?;
let testcase = &mut self.get_from_all(id).unwrap().borrow_mut();
self.save_testcase(testcase, id)?;
*testcase.input_mut() = None;
Ok(idx)
Ok(id)
}
/// Replaces the testcase at the given idx
#[inline]
fn replace(&mut self, idx: CorpusId, testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
let entry = self.inner.replace(idx, testcase)?;
fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
let entry = self.inner.replace(id, testcase)?;
self.remove_testcase(&entry)?;
let testcase = &mut self.get(idx).unwrap().borrow_mut();
self.save_testcase(testcase, idx)?;
let testcase = &mut self.get(id).unwrap().borrow_mut();
self.save_testcase(testcase, id)?;
*testcase.input_mut() = None;
Ok(entry)
}
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled corpus
#[inline]
fn remove(&mut self, idx: CorpusId) -> Result<Testcase<I>, Error> {
let entry = self.inner.remove(idx)?;
fn remove(&mut self, id: CorpusId) -> Result<Testcase<I>, Error> {
let entry = self.inner.remove(id)?;
self.remove_testcase(&entry)?;
Ok(entry)
}
/// Get by id; considers only enabled testcases
#[inline]
fn get(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.inner.get(idx)
fn get(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.inner.get(id)
}
/// Get by id; considers both enabled and disabled testcases
#[inline]
fn get_from_all(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.inner.get_from_all(idx)
fn get_from_all(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.inner.get_from_all(id)
}
/// Current testcase scheduled
@ -135,8 +135,8 @@ where
}
#[inline]
fn next(&self, idx: CorpusId) -> Option<CorpusId> {
self.inner.next(idx)
fn next(&self, id: CorpusId) -> Option<CorpusId> {
self.inner.next(id)
}
/// Peek the next free corpus id
@ -146,8 +146,8 @@ where
}
#[inline]
fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
self.inner.prev(idx)
fn prev(&self, id: CorpusId) -> Option<CorpusId> {
self.inner.prev(id)
}
#[inline]
@ -372,10 +372,10 @@ where
}
}
fn save_testcase(&self, testcase: &mut Testcase<I>, idx: CorpusId) -> Result<(), Error> {
fn save_testcase(&self, testcase: &mut Testcase<I>, id: CorpusId) -> Result<(), Error> {
let file_name_orig = testcase.filename_mut().take().unwrap_or_else(|| {
// TODO walk entry metadata to ask for pieces of filename (e.g. :havoc in AFL)
testcase.input().as_ref().unwrap().generate_name(idx.0)
testcase.input().as_ref().unwrap().generate_name(Some(id))
});
// New testcase, we need to save it.

View File

@ -116,9 +116,9 @@ where
let total = state.corpus().count() as u64;
let mut curr = 0;
while let Some(idx) = cur_id {
while let Some(id) = cur_id {
let (weight, input) = {
let mut testcase = state.corpus().get(idx)?.borrow_mut();
let mut testcase = state.corpus().get(id)?.borrow_mut();
let weight = TS::compute(state, &mut *testcase)?
.to_u64()
.expect("Weight must be computable.");
@ -177,9 +177,9 @@ where
}
// Keep track of that seed's index and weight
seed_exprs.insert(seed_expr, (idx, weight));
seed_exprs.insert(seed_expr, (id, weight));
cur_id = state.corpus().next(idx);
cur_id = state.corpus().next(id);
}
manager.log(
@ -215,21 +215,21 @@ where
let res = if let Some(model) = opt.get_model() {
let mut removed = Vec::with_capacity(state.corpus().count());
for (seed, (idx, _)) in seed_exprs {
for (seed, (id, _)) in seed_exprs {
// if the model says the seed isn't there, mark it for deletion
if !model.eval(&seed, true).unwrap().as_bool().unwrap() {
removed.push(idx);
removed.push(id);
}
}
// reverse order; if indexes are stored in a vec, we need to remove from back to front
removed.sort_unstable_by(|idx1, idx2| idx2.cmp(idx1));
for idx in removed {
let removed = state.corpus_mut().remove(idx)?;
removed.sort_unstable_by(|id1, id2| id2.cmp(id1));
for id in removed {
let removed = state.corpus_mut().remove(id)?;
// scheduler needs to know we've removed the input, or it will continue to try
// to use now-missing inputs
fuzzer
.scheduler_mut()
.on_remove(state, idx, &Some(removed))?;
.on_remove(state, id, &Some(removed))?;
}
Ok(())
} else {

View File

@ -36,7 +36,7 @@ use crate::{inputs::UsesInput, Error};
/// An abstraction for the index that identify a testcase in the corpus
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[repr(transparent)]
pub struct CorpusId(pub(crate) usize);
pub struct CorpusId(pub usize);
impl fmt::Display for CorpusId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -109,7 +109,7 @@ pub trait Corpus: UsesInput + Serialize + for<'de> Deserialize<'de> {
/// Replaces the [`Testcase`] at the given idx, returning the existing.
fn replace(
&mut self,
idx: CorpusId,
id: CorpusId,
testcase: Testcase<Self::Input>,
) -> Result<Testcase<Self::Input>, Error>;
@ -171,8 +171,8 @@ pub trait Corpus: UsesInput + Serialize + for<'de> Deserialize<'de> {
fn store_input_from(&self, testcase: &Testcase<Self::Input>) -> Result<(), Error>;
/// Loads the `Input` for a given [`CorpusId`] from the [`Corpus`], and returns the clone.
fn cloned_input_for_id(&self, idx: CorpusId) -> Result<Self::Input, Error> {
let mut testcase = self.get(idx)?.borrow_mut();
fn cloned_input_for_id(&self, id: CorpusId) -> Result<Self::Input, Error> {
let mut testcase = self.get(id)?.borrow_mut();
Ok(testcase.load_input(self)?.clone())
}
}
@ -180,10 +180,10 @@ pub trait Corpus: UsesInput + Serialize + for<'de> Deserialize<'de> {
/// Trait for types which track the current corpus index
pub trait HasCurrentCorpusId {
/// Set the current corpus index; we have started processing this corpus entry
fn set_corpus_idx(&mut self, idx: CorpusId) -> Result<(), Error>;
fn set_corpus_id(&mut self, id: CorpusId) -> Result<(), Error>;
/// Clear the current corpus index; we are done with this entry
fn clear_corpus_idx(&mut self) -> Result<(), Error>;
fn clear_corpus_id(&mut self) -> Result<(), Error>;
/// Fetch the current corpus index -- typically used after a state recovery or transfer
fn current_corpus_id(&self) -> Result<Option<CorpusId>, Error>;

View File

@ -57,27 +57,27 @@ where
Err(Error::unsupported("Unsupported by NopCorpus"))
}
/// Replaces the testcase at the given idx
/// Replaces the testcase with the given id
#[inline]
fn replace(&mut self, _idx: CorpusId, _testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
fn replace(&mut self, _id: CorpusId, _testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
Err(Error::unsupported("Unsupported by NopCorpus"))
}
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases
#[inline]
fn remove(&mut self, _idx: CorpusId) -> Result<Testcase<I>, Error> {
fn remove(&mut self, _id: CorpusId) -> Result<Testcase<I>, Error> {
Err(Error::unsupported("Unsupported by NopCorpus"))
}
/// Get by id; considers only enabled testcases
#[inline]
fn get(&self, _idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
fn get(&self, _id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
Err(Error::unsupported("Unsupported by NopCorpus"))
}
/// Get by id; considers both enabled and disabled testcases
#[inline]
fn get_from_all(&self, _idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
fn get_from_all(&self, _id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
Err(Error::unsupported("Unsupported by NopCorpus"))
}
@ -100,12 +100,12 @@ where
}
#[inline]
fn next(&self, _idx: CorpusId) -> Option<CorpusId> {
fn next(&self, _id: CorpusId) -> Option<CorpusId> {
None
}
#[inline]
fn prev(&self, _idx: CorpusId) -> Option<CorpusId> {
fn prev(&self, _id: CorpusId) -> Option<CorpusId> {
None
}

View File

@ -102,8 +102,8 @@ where
/// Replaces the testcase at the given idx
#[inline]
fn replace(&mut self, idx: CorpusId, testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
self.inner.replace(idx, testcase)
fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Result<Testcase<I>, Error> {
self.inner.replace(id, testcase)
}
/// Peek the next free corpus id
@ -114,20 +114,20 @@ where
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases
#[inline]
fn remove(&mut self, idx: CorpusId) -> Result<Testcase<I>, Error> {
self.inner.remove(idx)
fn remove(&mut self, id: CorpusId) -> Result<Testcase<I>, Error> {
self.inner.remove(id)
}
/// Get by id; will check the disabled corpus if not available in the enabled
#[inline]
fn get(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.inner.get(idx)
fn get(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.inner.get(id)
}
/// Get by id; considers both enabled and disabled testcases
#[inline]
fn get_from_all(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.inner.get_from_all(idx)
fn get_from_all(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
self.inner.get_from_all(id)
}
/// Current testcase scheduled
@ -143,13 +143,13 @@ where
}
#[inline]
fn next(&self, idx: CorpusId) -> Option<CorpusId> {
self.inner.next(idx)
fn next(&self, id: CorpusId) -> Option<CorpusId> {
self.inner.next(id)
}
#[inline]
fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
self.inner.prev(idx)
fn prev(&self, id: CorpusId) -> Option<CorpusId> {
self.inner.prev(id)
}
#[inline]

View File

@ -383,7 +383,7 @@ where
fn name_detailed(&self) -> String {
match self {
Event::NewTestcase { input, .. } => {
format!("Testcase {}", input.generate_name(0))
format!("Testcase {}", input.generate_name(None))
}
Event::UpdateExecStats { .. } => "Client Heartbeat".to_string(),
Event::UpdateUserStats { .. } => "UserStats".to_string(),

View File

@ -204,7 +204,7 @@ pub mod unix_signal_handler {
let mut bsod = Vec::new();
{
let mut writer = std::io::BufWriter::new(&mut bsod);
let _ = writeln!(writer, "input: {:?}", input.generate_name(0));
let _ = writeln!(writer, "input: {:?}", input.generate_name(None));
let bsod = libafl_bolts::minibsod::generate_minibsod(
&mut writer,
signal,

View File

@ -400,7 +400,7 @@ pub mod windows_exception_handler {
let mut bsod = Vec::new();
{
let mut writer = std::io::BufWriter::new(&mut bsod);
writeln!(writer, "input: {:?}", input.generate_name(0)).unwrap();
writeln!(writer, "input: {:?}", input.generate_name(None)).unwrap();
libafl_bolts::minibsod::generate_minibsod(&mut writer, exception_pointers)
.unwrap();
writer.flush().unwrap();

View File

@ -413,7 +413,7 @@ where
EM: EventFirer<State = Self::State>,
{
let exec_res = self.execute_no_process(state, manager, &input, observers, exit_kind)?;
let corpus_idx = self.process_execution(
let corpus_id = self.process_execution(
state,
manager,
input,
@ -422,7 +422,7 @@ where
exit_kind,
send_events,
)?;
Ok((exec_res, corpus_idx))
Ok((exec_res, corpus_id))
}
/// Evaluate if a set of observation channels has an interesting state
@ -456,8 +456,8 @@ where
.append_hit_feedbacks(testcase.hit_feedbacks_mut())?;
self.feedback_mut()
.append_metadata(state, manager, observers, &mut testcase)?;
let idx = state.corpus_mut().add(testcase)?;
self.scheduler_mut().on_add(state, idx)?;
let id = state.corpus_mut().add(testcase)?;
self.scheduler_mut().on_add(state, id)?;
if send_events && manager.should_send() {
// TODO set None for fast targets
@ -485,7 +485,7 @@ where
// This testcase is from the other fuzzers.
*state.imported_mut() += 1;
}
Ok(Some(idx))
Ok(Some(id))
}
ExecuteInputResult::Solution => {
// Not interesting
@ -583,8 +583,8 @@ where
let mut testcase = Testcase::with_executions(input.clone(), *state.executions());
testcase.set_disabled(true);
// Add the disabled input to the main corpus
let idx = state.corpus_mut().add_disabled(testcase)?;
Ok(idx)
let id = state.corpus_mut().add_disabled(testcase)?;
Ok(id)
}
/// Adds an input, even if it's not considered `interesting` by any of the executors
fn add_input(
@ -620,7 +620,7 @@ where
.append_hit_feedbacks(testcase.hit_objectives_mut())?;
self.objective_mut()
.append_metadata(state, manager, &*observers, &mut testcase)?;
let idx = state.solutions_mut().add(testcase)?;
let id = state.solutions_mut().add(testcase)?;
let executions = *state.executions();
manager.fire(
@ -631,7 +631,7 @@ where
time: current_time(),
},
)?;
return Ok(idx);
return Ok(id);
}
// Not a solution
@ -659,8 +659,8 @@ where
// Add the input to the main corpus
self.feedback_mut()
.append_metadata(state, manager, &*observers, &mut testcase)?;
let idx = state.corpus_mut().add(testcase)?;
self.scheduler_mut().on_add(state, idx)?;
let id = state.corpus_mut().add(testcase)?;
self.scheduler_mut().on_add(state, id)?;
let observers_buf = if manager.configuration() == EventConfig::AlwaysUnique {
None
@ -682,7 +682,7 @@ where
node_id: None,
},
)?;
Ok(idx)
Ok(id)
}
}
@ -715,12 +715,12 @@ where
state.introspection_monitor_mut().start_timer();
// Get the next index from the scheduler
let idx = if let Some(idx) = state.current_corpus_id()? {
idx // we are resuming
let id = if let Some(id) = state.current_corpus_id()? {
id // we are resuming
} else {
let idx = self.scheduler.next(state)?;
state.set_corpus_idx(idx)?; // set up for resume
idx
let id = self.scheduler.next(state)?;
state.set_corpus_id(id)?; // set up for resume
id
};
// Mark the elapsed time for the scheduler
@ -746,16 +746,16 @@ where
state.introspection_monitor_mut().mark_manager_time();
{
if let Ok(mut testcase) = state.testcase_mut(idx) {
if let Ok(mut testcase) = state.testcase_mut(id) {
let scheduled_count = testcase.scheduled_count();
// increase scheduled count, this was fuzz_level in afl
testcase.set_scheduled_count(scheduled_count + 1);
}
}
state.clear_corpus_idx()?;
state.clear_corpus_id()?;
Ok(idx)
Ok(id)
}
}

View File

@ -15,7 +15,10 @@ use libafl_bolts::{fs::write_file_atomic, Error};
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
use serde::{Deserialize, Serialize};
use crate::inputs::{HasMutatorBytes, HasTargetBytes, Input};
use crate::{
corpus::CorpusId,
inputs::{HasMutatorBytes, HasTargetBytes, Input},
};
/// A bytes input is the basic input
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
@ -47,7 +50,7 @@ impl Input for BytesInput {
}
/// Generate a name for this input
fn generate_name(&self, _idx: usize) -> String {
fn generate_name(&self, _id: Option<CorpusId>) -> String {
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
hasher.write(self.bytes());
format!("{:016x}", hasher.finish())

View File

@ -19,7 +19,7 @@ use libafl_bolts::{Error, HasLen};
use regex::Regex;
use serde::{Deserialize, Serialize};
use crate::inputs::Input;
use crate::{corpus::CorpusId, inputs::Input};
/// Trait to encode bytes to an [`EncodedInput`] using the given [`Tokenizer`]
pub trait InputEncoder<T>
@ -202,7 +202,7 @@ pub struct EncodedInput {
impl Input for EncodedInput {
/// Generate a name for this input
#[must_use]
fn generate_name(&self, _idx: usize) -> String {
fn generate_name(&self, _id: Option<CorpusId>) -> String {
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
for code in &self.codes {
hasher.write(&code.to_le_bytes());

View File

@ -9,7 +9,7 @@ use ahash::RandomState;
use libafl_bolts::{Error, HasLen};
use serde::{Deserialize, Serialize};
use crate::inputs::Input;
use crate::{corpus::CorpusId, inputs::Input};
/// A terminal for gramatron grammar fuzzing
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
@ -44,7 +44,7 @@ pub struct GramatronInput {
impl Input for GramatronInput {
/// Generate a name for this input
#[must_use]
fn generate_name(&self, _idx: usize) -> String {
fn generate_name(&self, _id: Option<CorpusId>) -> String {
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
for term in &self.terms {
hasher.write(term.symbol.as_bytes());

View File

@ -39,6 +39,8 @@ use libafl_bolts::{ownedref::OwnedSlice, Error, HasLen};
pub use nautilus::*;
use serde::{Deserialize, Serialize};
use crate::corpus::CorpusId;
/// An input for the target
#[cfg(not(feature = "std"))]
pub trait Input: Clone + Serialize + serde::de::DeserializeOwned + Debug {
@ -53,7 +55,7 @@ pub trait Input: Clone + Serialize + serde::de::DeserializeOwned + Debug {
}
/// Generate a name for this input
fn generate_name(&self, idx: usize) -> String;
fn generate_name(&self, id: Option<CorpusId>) -> String;
/// An hook executed if the input is stored as `Testcase`
fn wrapped_as_testcase(&mut self) {}
@ -82,7 +84,7 @@ pub trait Input: Clone + Serialize + serde::de::DeserializeOwned + Debug {
}
/// Generate a name for this input, the user is responsible for making each name of testcase unique.
fn generate_name(&self, idx: usize) -> String;
fn generate_name(&self, id: Option<CorpusId>) -> String;
/// An hook executed if the input is stored as `Testcase`
fn wrapped_as_testcase(&mut self) {}
@ -111,7 +113,7 @@ macro_rules! none_input_converter {
#[derive(Copy, Clone, Serialize, Deserialize, Debug, Hash)]
pub struct NopInput {}
impl Input for NopInput {
fn generate_name(&self, _idx: usize) -> String {
fn generate_name(&self, _id: Option<CorpusId>) -> String {
"nop-input".to_string()
}
}

View File

@ -12,7 +12,7 @@ use alloc::{
use arrayvec::ArrayVec;
use serde::{Deserialize, Serialize};
use crate::inputs::Input;
use crate::{corpus::CorpusId, inputs::Input};
/// An input composed of multiple parts. Use in situations where subcomponents are not necessarily
/// related, or represent distinct parts of the input.
@ -153,11 +153,11 @@ impl<I> Input for MultipartInput<I>
where
I: Input,
{
fn generate_name(&self, idx: usize) -> String {
fn generate_name(&self, id: Option<CorpusId>) -> String {
self.names
.iter()
.cloned()
.zip(self.parts.iter().map(|i| i.generate_name(idx)))
.zip(self.parts.iter().map(|i| i.generate_name(id)))
.map(|(name, generated)| format!("{name}-{generated}"))
.collect::<Vec<_>>()
.join(",")

View File

@ -1,9 +1,6 @@
//! Input for the [`Nautilus`](https://github.com/RUB-SysSec/nautilus) grammar fuzzer methods
//!
//use ahash::AHasher;
//use core::hash::Hasher;
//!
use alloc::{rc::Rc, string::String, vec::Vec};
use core::cell::RefCell;
use std::hash::{Hash, Hasher};
@ -17,6 +14,7 @@ use crate::{
rule::RuleIdOrCustom,
tree::{Tree, TreeLike},
},
corpus::CorpusId,
generators::nautilus::NautilusContext,
inputs::{BytesInput, Input, InputConverter},
Error,
@ -32,13 +30,18 @@ pub struct NautilusInput {
impl Input for NautilusInput {
/// Generate a name for this input
#[must_use]
fn generate_name(&self, idx: usize) -> String {
fn generate_name(&self, id: Option<CorpusId>) -> String {
/*let mut hasher = AHasher::new_with_keys(0, 0);
for term in &self.terms {
hasher.write(term.symbol.as_bytes());
}
format!("{:016x}", hasher.finish())*/
format!("id:{idx}")
if let Some(id) = id {
format!("id_{}", id.0)
} else {
"id_unknown".into()
}
}
}

View File

@ -292,16 +292,16 @@ where
fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> {
let size = input.codes().len();
let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
// We don't want to use the testcase we're already using for splicing
let idx = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
if let Some(cur) = state.corpus().current() {
if idx == *cur {
if id == *cur {
return Ok(MutationResult::Skipped);
}
}
let other_size = {
let mut other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
other_testcase.load_input(state.corpus())?.codes().len()
};
@ -322,7 +322,7 @@ where
}
}
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
// no need to `load_input` again - we did that above already.
let other = other_testcase.input().as_ref().unwrap();
@ -365,17 +365,17 @@ where
return Ok(MutationResult::Skipped);
}
let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
// We don't want to use the testcase we're already using for splicing
let idx = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
if let Some(cur) = state.corpus().current() {
if idx == *cur {
if id == *cur {
return Ok(MutationResult::Skipped);
}
}
let other_size = {
// new scope to make the borrow checker happy
let mut other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
other_testcase.load_input(state.corpus())?.codes().len()
};
@ -387,7 +387,7 @@ where
let len = state.rand_mut().below(min(other_size - from, size));
let to = state.rand_mut().below(size - len);
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
// no need to load the input again, it'll already be present at this point.
let other = other_testcase.input().as_ref().unwrap();

View File

@ -117,13 +117,13 @@ where
return Ok(MutationResult::Skipped);
}
let idx = random_corpus_id!(state.corpus(), state.rand_mut());
let id = random_corpus_id!(state.corpus(), state.rand_mut());
let insert_at = state.rand_mut().below(input.terminals().len());
let rand_num = state.rand_mut().next();
let mut other_testcase = state.corpus().get(idx)?.borrow_mut();
let mut other_testcase = state.corpus().get(id)?.borrow_mut();
if !other_testcase.has_metadata::<GramatronIdxMapMetadata>() {
let meta = GramatronIdxMapMetadata::new(other_testcase.load_input(state.corpus())?);

View File

@ -30,14 +30,14 @@ fn extend_with_random_generalized<S>(
where
S: HasMetadata + HasRand + HasCorpus,
{
let idx = random_corpus_id!(state.corpus(), state.rand_mut());
let id = random_corpus_id!(state.corpus(), state.rand_mut());
if state.rand_mut().coinflip(CHOOSE_SUBINPUT_PROB) {
if state.rand_mut().coinflip(0.5) {
let rand1 = state.rand_mut().next();
let rand2 = state.rand_mut().next();
let other_testcase = state.corpus().get(idx)?.borrow();
let other_testcase = state.corpus().get(id)?.borrow();
if let Some(other) = other_testcase
.metadata_map()
.get::<GeneralizedInputMetadata>()
@ -88,7 +88,7 @@ where
}
}
let other_testcase = state.corpus().get(idx)?.borrow();
let other_testcase = state.corpus().get(id)?.borrow();
if let Some(other) = other_testcase
.metadata_map()
.get::<GeneralizedInputMetadata>()

View File

@ -94,13 +94,9 @@ pub trait Mutator<I, S>: Named {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error>;
/// Post-process given the outcome of the execution
/// `new_corpus_idx` will be `Some` if a new [`crate::corpus::Testcase`] was created this execution.
/// `new_corpus_id` will be `Some` if a new [`crate::corpus::Testcase`] was created this execution.
#[inline]
fn post_exec(
&mut self,
_state: &mut S,
_new_corpus_idx: Option<CorpusId>,
) -> Result<(), Error> {
fn post_exec(&mut self, _state: &mut S, _new_corpus_id: Option<CorpusId>) -> Result<(), Error> {
Ok(())
}
}
@ -118,12 +114,12 @@ pub trait MultiMutator<I, S>: Named {
) -> Result<Vec<I>, Error>;
/// Post-process given the outcome of the execution
/// `new_corpus_idx` will be `Some` if a new `Testcase` was created this execution.
/// `new_corpus_id` will be `Some` if a new `Testcase` was created this execution.
#[inline]
fn multi_post_exec(
&mut self,
_state: &mut S,
_new_corpus_idx: Option<CorpusId>,
_new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
Ok(())
}
@ -135,11 +131,11 @@ pub trait MutatorsTuple<I, S>: HasLen {
fn mutate_all(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error>;
/// Runs the [`Mutator::post_exec`] function on all [`Mutator`]`s` in this `Tuple`.
/// `new_corpus_idx` will be `Some` if a new `Testcase` was created this execution.
/// `new_corpus_id` will be `Some` if a new `Testcase` was created this execution.
fn post_exec_all(
&mut self,
state: &mut S,
new_corpus_idx: Option<CorpusId>,
new_corpus_id: Option<CorpusId>,
) -> Result<(), Error>;
/// Gets the [`Mutator`] at the given index and runs the `mutate` function on it.
@ -151,13 +147,13 @@ pub trait MutatorsTuple<I, S>: HasLen {
) -> Result<MutationResult, Error>;
/// Gets the [`Mutator`] at the given index and runs the `post_exec` function on it.
/// `new_corpus_idx` will be `Some` if a new `Testcase` was created this execution.
/// `new_corpus_id` will be `Some` if a new `Testcase` was created this execution.
fn get_and_post_exec(
&mut self,
index: usize,
state: &mut S,
corpus_idx: Option<CorpusId>,
corpus_id: Option<CorpusId>,
) -> Result<(), Error>;
/// Gets all names of the wrapped [`Mutator`]`s`, reversed.
@ -177,7 +173,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
fn post_exec_all(
&mut self,
_state: &mut S,
_new_corpus_idx: Option<CorpusId>,
_new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
Ok(())
}
@ -197,7 +193,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
&mut self,
_index: usize,
_state: &mut S,
_new_corpus_idx: Option<CorpusId>,
_new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
Ok(())
}
@ -230,10 +226,10 @@ where
fn post_exec_all(
&mut self,
state: &mut S,
new_corpus_idx: Option<CorpusId>,
new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
self.0.post_exec(state, new_corpus_idx)?;
self.1.post_exec_all(state, new_corpus_idx)
self.0.post_exec(state, new_corpus_id)?;
self.1.post_exec_all(state, new_corpus_id)
}
fn get_and_mutate(
@ -253,12 +249,12 @@ where
&mut self,
index: usize,
state: &mut S,
new_corpus_idx: Option<CorpusId>,
new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
if index == 0 {
self.0.post_exec(state, new_corpus_idx)
self.0.post_exec(state, new_corpus_id)
} else {
self.1.get_and_post_exec(index - 1, state, new_corpus_idx)
self.1.get_and_post_exec(index - 1, state, new_corpus_id)
}
}
@ -305,9 +301,9 @@ where
fn post_exec_all(
&mut self,
state: &mut S,
new_corpus_idx: Option<CorpusId>,
new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
self.0.post_exec_all(state, new_corpus_idx)
self.0.post_exec_all(state, new_corpus_id)
}
fn get_and_mutate(
@ -323,9 +319,9 @@ where
&mut self,
index: usize,
state: &mut S,
new_corpus_idx: Option<CorpusId>,
new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
self.0.get_and_post_exec(index, state, new_corpus_idx)
self.0.get_and_post_exec(index, state, new_corpus_id)
}
fn names(&self) -> Vec<&str> {
@ -361,10 +357,10 @@ impl<I, S> MutatorsTuple<I, S> for Vec<Box<dyn Mutator<I, S>>> {
fn post_exec_all(
&mut self,
state: &mut S,
new_corpus_idx: Option<CorpusId>,
new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
for mutator in self.iter_mut() {
mutator.post_exec(state, new_corpus_idx)?;
mutator.post_exec(state, new_corpus_id)?;
}
Ok(())
}
@ -385,12 +381,12 @@ impl<I, S> MutatorsTuple<I, S> for Vec<Box<dyn Mutator<I, S>>> {
&mut self,
index: usize,
state: &mut S,
new_corpus_idx: Option<CorpusId>,
new_corpus_id: Option<CorpusId>,
) -> Result<(), Error> {
let mutator = self
.get_mut(index)
.ok_or_else(|| Error::key_not_found("Mutator with id {index:?} not found."))?;
mutator.post_exec(state, new_corpus_idx)
mutator.post_exec(state, new_corpus_id)
}
fn names_reversed(&self) -> Vec<&str> {

View File

@ -399,7 +399,7 @@ where
}
#[allow(clippy::cast_precision_loss)]
fn post_exec(&mut self, state: &mut S, _new_corpus_idx: Option<CorpusId>) -> Result<(), Error> {
fn post_exec(&mut self, state: &mut S, _new_corpus_id: Option<CorpusId>) -> Result<(), Error> {
let before = self.finds_before;
let after = state.corpus().count() + state.solutions().count();

View File

@ -50,8 +50,8 @@ where
}
}
fn post_exec(&mut self, state: &mut S, new_corpus_idx: Option<CorpusId>) -> Result<(), Error> {
M::post_exec(self, state, new_corpus_idx)
fn post_exec(&mut self, state: &mut S, new_corpus_id: Option<CorpusId>) -> Result<(), Error> {
M::post_exec(self, state, new_corpus_id)
}
}
@ -129,9 +129,9 @@ where
let part_choice = state.rand_mut().next() as usize;
// We special-case crossover with self
let idx = random_corpus_id!(state.corpus(), state.rand_mut());
let id = random_corpus_id!(state.corpus(), state.rand_mut());
if let Some(cur) = state.corpus().current() {
if idx == *cur {
if id == *cur {
let choice = name_choice % input.names().len();
let name = input.names()[choice].clone();
@ -150,7 +150,7 @@ where
.parts_by_name(&name)
.filter(|&(p, _)| p != choice)
.nth(part_choice % parts)
.map(|(idx, part)| (idx, part.bytes().len()));
.map(|(id, part)| (id, part.bytes().len()));
if let Some((part_idx, size)) = maybe_size {
let target = state.rand_mut().below(size);
@ -174,7 +174,7 @@ where
}
}
let mut other_testcase = state.corpus().get(idx)?.borrow_mut();
let mut other_testcase = state.corpus().get(id)?.borrow_mut();
let other = other_testcase.load_input(state.corpus())?;
let choice = name_choice % other.names().len();
@ -198,7 +198,7 @@ where
let target = state.rand_mut().below(size);
let range = rand_range(state, other_size, min(other_size, size - target));
let other_testcase = state.corpus().get(idx)?.borrow_mut();
let other_testcase = state.corpus().get(id)?.borrow_mut();
// No need to load the input again, it'll still be cached.
let other = other_testcase.input().as_ref().unwrap();
@ -233,9 +233,9 @@ where
let part_choice = state.rand_mut().next() as usize;
// We special-case crossover with self
let idx = random_corpus_id!(state.corpus(), state.rand_mut());
let id = random_corpus_id!(state.corpus(), state.rand_mut());
if let Some(cur) = state.corpus().current() {
if idx == *cur {
if id == *cur {
let choice = name_choice % input.names().len();
let name = input.names()[choice].clone();
@ -254,7 +254,7 @@ where
.parts_by_name(&name)
.filter(|&(p, _)| p != choice)
.nth(part_choice % parts)
.map(|(idx, part)| (idx, part.bytes().len()));
.map(|(id, part)| (id, part.bytes().len()));
if let Some((part_idx, size)) = maybe_size {
let target = state.rand_mut().below(size);
@ -278,7 +278,7 @@ where
}
}
let mut other_testcase = state.corpus().get(idx)?.borrow_mut();
let mut other_testcase = state.corpus().get(id)?.borrow_mut();
let other = other_testcase.load_input(state.corpus())?;
let choice = name_choice % other.names().len();
@ -302,7 +302,7 @@ where
let target = state.rand_mut().below(size);
let range = rand_range(state, other_size, min(other_size, size - target));
let other_testcase = state.corpus().get(idx)?.borrow_mut();
let other_testcase = state.corpus().get(id)?.borrow_mut();
// No need to load the input again, it'll still be cached.
let other = other_testcase.input().as_ref().unwrap();

View File

@ -1073,17 +1073,16 @@ where
return Ok(MutationResult::Skipped);
}
let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
// We don't want to use the testcase we're already using for splicing
let idx = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
if let Some(cur) = state.corpus().current() {
if idx == *cur {
if id == *cur {
return Ok(MutationResult::Skipped);
}
}
let other_size = {
let mut other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
other_testcase.load_input(state.corpus())?.bytes().len()
};
@ -1094,7 +1093,7 @@ where
let range = rand_range(state, other_size, min(other_size, max_size - size));
let target = state.rand_mut().below(size); // TODO: fix bug if size is 0
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
// No need to load the input again, it'll still be cached.
let other = other_testcase.input().as_ref().unwrap();
@ -1157,16 +1156,16 @@ where
return Ok(MutationResult::Skipped);
}
let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
// We don't want to use the testcase we're already using for splicing
let idx = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
if let Some(cur) = state.corpus().current() {
if idx == *cur {
if id == *cur {
return Ok(MutationResult::Skipped);
}
}
let other_size = {
let mut testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let mut testcase = state.corpus().get_from_all(id)?.borrow_mut();
testcase.load_input(state.corpus())?.bytes().len()
};
@ -1177,7 +1176,7 @@ where
let target = state.rand_mut().below(size);
let range = rand_range(state, other_size, min(other_size, size - target));
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
// No need to load the input again, it'll still be cached.
let other = other_testcase.input().as_ref().unwrap();
@ -1230,16 +1229,16 @@ where
{
#[allow(clippy::cast_sign_loss)]
fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> {
let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
// We don't want to use the testcase we're already using for splicing
let idx = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
if let Some(cur) = state.corpus().current() {
if idx == *cur {
if id == *cur {
return Ok(MutationResult::Skipped);
}
}
let (first_diff, last_diff) = {
let mut other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
let other = other_testcase.load_input(state.corpus())?;
let (f, l) = locate_diffs(input.bytes(), other.bytes());
@ -1253,7 +1252,7 @@ where
let split_at = state.rand_mut().between(first_diff, last_diff);
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
// Input will already be loaded.
let other = other_testcase.input().as_ref().unwrap();

View File

@ -388,9 +388,9 @@ where
self.scheduled_mutate(state, input)
}
fn post_exec(&mut self, state: &mut S, corpus_idx: Option<CorpusId>) -> Result<(), Error> {
if let Some(idx) = corpus_idx {
let mut testcase = (*state.corpus_mut().get(idx)?).borrow_mut();
fn post_exec(&mut self, state: &mut S, corpus_id: Option<CorpusId>) -> Result<(), Error> {
if let Some(id) = corpus_id {
let mut testcase = (*state.corpus_mut().get(id)?).borrow_mut();
let mut log = Vec::<Cow<'static, str>>::new();
while let Some(idx) = self.mutation_log.pop() {
let name = self.scheduled.mutations().name(idx.0).unwrap().clone(); // TODO maybe return an Error on None

View File

@ -618,9 +618,9 @@ pub struct AFLppRedQueen {
enable_transform: bool,
enable_arith: bool,
text_type: TextType,
/// We use this variable to check if we scheduled a new `corpus_idx`
/// We use this variable to check if we scheduled a new `corpus_id`
/// - and, hence, need to recalculate `text_type`
last_corpus_idx: Option<CorpusId>,
last_corpus_id: Option<CorpusId>,
}
impl AFLppRedQueen {
@ -1135,10 +1135,10 @@ where
// println!("orig: {:#?} new: {:#?}", orig_cmpvals, new_cmpvals);
// Compute when mutating it for the 1st time.
let current_corpus_id = state.current_corpus_id()?.ok_or_else(|| Error::key_not_found("No corpus-idx is currently being fuzzed, but called AFLppRedQueen::multi_mutated()."))?;
if self.last_corpus_idx.is_none() || self.last_corpus_idx.unwrap() != current_corpus_id {
let current_corpus_id = state.current_corpus_id()?.ok_or_else(|| Error::key_not_found("No corpus-id is currently being fuzzed, but called AFLppRedQueen::multi_mutated()."))?;
if self.last_corpus_id.is_none() || self.last_corpus_id.unwrap() != current_corpus_id {
self.text_type = check_if_text(orig_bytes, orig_bytes.len());
self.last_corpus_idx = Some(current_corpus_id);
self.last_corpus_id = Some(current_corpus_id);
}
// println!("approximate size: {cmp_len} x {input_len}");
for cmp_idx in 0..cmp_len {
@ -1690,7 +1690,7 @@ impl AFLppRedQueen {
enable_transform: false,
enable_arith: false,
text_type: TextType::None,
last_corpus_idx: None,
last_corpus_id: None,
}
}
@ -1701,7 +1701,7 @@ impl AFLppRedQueen {
enable_transform: transform,
enable_arith: arith,
text_type: TextType::None,
last_corpus_idx: None,
last_corpus_id: None,
}
}

View File

@ -51,9 +51,9 @@ impl<S> MutatedTransformPost<S> for UnicodeIdentificationMetadata
where
S: HasTestcase,
{
fn post_exec(self, state: &mut S, corpus_idx: Option<CorpusId>) -> Result<(), Error> {
if let Some(corpus_idx) = corpus_idx {
let mut tc = state.testcase_mut(corpus_idx)?;
fn post_exec(self, state: &mut S, corpus_id: Option<CorpusId>) -> Result<(), Error> {
if let Some(corpus_id) = corpus_id {
let mut tc = state.testcase_mut(corpus_id)?;
tc.add_metadata(self);
}
Ok(())

View File

@ -136,9 +136,9 @@ where
<Self::State as UsesInput>::Input: HasLen,
O: CanTrack,
{
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
self.update_accounting_score(state, idx)?;
self.inner.on_add(state, idx)
fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
self.update_accounting_score(state, id)?;
self.inner.on_add(state, id)
}
fn on_evaluation<OT>(
@ -163,29 +163,29 @@ where
} else {
self.inner.cull(state)?;
}
let mut idx = self.inner.base_mut().next(state)?;
let mut id = self.inner.base_mut().next(state)?;
while {
let has = !state
.corpus()
.get(idx)?
.get(id)?
.borrow()
.has_metadata::<IsFavoredMetadata>();
has
} && state.rand_mut().coinflip(self.skip_non_favored_prob)
{
idx = self.inner.base_mut().next(state)?;
id = self.inner.base_mut().next(state)?;
}
// Don't add corpus.curret(). The inner scheduler will take care of it
Ok(idx)
Ok(id)
}
/// Set current fuzzed corpus id and `scheduled_count`
fn set_current_scheduled(
&mut self,
_state: &mut Self::State,
_next_idx: Option<CorpusId>,
_next_id: Option<CorpusId>,
) -> Result<(), Error> {
// We do nothing here, the inner scheduler will take care of it
Ok(())
@ -205,7 +205,7 @@ where
pub fn update_accounting_score(
&self,
state: &mut CS::State,
idx: CorpusId,
id: CorpusId,
) -> Result<(), Error> {
let mut indexes = vec![];
let mut new_favoreds = vec![];
@ -220,7 +220,7 @@ where
{
let top_acc = state.metadata_map().get::<TopAccountingMetadata>().unwrap();
if let Some(old_idx) = top_acc.map.get(&idx) {
if let Some(old_id) = top_acc.map.get(&idx) {
if top_acc.max_accounting[idx] > self.accounting_map[idx] {
continue;
}
@ -229,11 +229,11 @@ where
equal_score = true;
}
let mut old = state.corpus().get(*old_idx)?.borrow_mut();
let mut old = state.corpus().get_from_all(*old_id)?.borrow_mut();
let must_remove = {
let old_meta = old.metadata_map_mut().get_mut::<AccountingIndexesMetadata>().ok_or_else(|| {
Error::key_not_found(format!(
"AccountingIndexesMetadata, needed by CoverageAccountingScheduler, not found in testcase #{old_idx}"
"AccountingIndexesMetadata, needed by CoverageAccountingScheduler, not found in testcase #{old_id}"
))
})?;
*old_meta.refcnt_mut() -= 1;
@ -268,7 +268,7 @@ where
state
.corpus()
.get(idx)?
.get(id)?
.borrow_mut()
.metadata_map_mut()
.insert(AccountingIndexesMetadata::with_tcref(
@ -283,7 +283,7 @@ where
top_acc.changed = true;
for elem in new_favoreds {
top_acc.map.insert(elem, idx);
top_acc.map.insert(elem, id);
}
Ok(())
@ -296,8 +296,8 @@ where
return Ok(());
};
for (_key, idx) in &top_rated.map {
let mut entry = state.corpus().get(*idx)?.borrow_mut();
for (_key, id) in &top_rated.map {
let mut entry = state.corpus().get(*id)?.borrow_mut();
if entry.scheduled_count() > 0 {
continue;
}

View File

@ -93,30 +93,30 @@ where
<Self as UsesState>::State: HasCorpus + HasMetadata + HasRand,
O: CanTrack,
{
/// Replaces the testcase at the given idx
/// Replaces the testcase at the given id
fn on_replace(
&mut self,
state: &mut <Self as UsesState>::State,
idx: CorpusId,
id: CorpusId,
testcase: &Testcase<<<Self as UsesState>::State as UsesInput>::Input>,
) -> Result<(), Error> {
self.base.on_replace(state, idx, testcase)?;
self.update_score(state, idx)
self.base.on_replace(state, id, testcase)?;
self.update_score(state, id)
}
/// Removes an entry from the corpus
fn on_remove(
&mut self,
state: &mut <Self as UsesState>::State,
idx: CorpusId,
id: CorpusId,
testcase: &Option<Testcase<<<Self as UsesState>::State as UsesInput>::Input>>,
) -> Result<(), Error> {
self.base.on_remove(state, idx, testcase)?;
self.base.on_remove(state, id, testcase)?;
let mut entries =
if let Some(meta) = state.metadata_map_mut().get_mut::<TopRatedsMetadata>() {
let entries = meta
.map
.extract_if(|_, other_idx| *other_idx == idx)
.extract_if(|_, other_id| *other_id == id)
.map(|(entry, _)| entry)
.collect::<Vec<_>>();
entries
@ -125,8 +125,8 @@ where
};
entries.sort_unstable(); // this should already be sorted, but just in case
let mut map = HashMap::new();
for i in state.corpus().ids() {
let mut old = state.corpus().get(i)?.borrow_mut();
for current_id in state.corpus().ids() {
let mut old = state.corpus().get(current_id)?.borrow_mut();
let factor = F::compute(state, &mut *old)?;
if let Some(old_map) = old.metadata_map_mut().get_mut::<M>() {
let mut e_iter = entries.iter();
@ -144,13 +144,13 @@ where
Ordering::Equal => {
// if we found a better factor, prefer it
map.entry(*e)
.and_modify(|(f, idx)| {
.and_modify(|(f, id)| {
if *f > factor {
*f = factor;
*idx = i;
*id = current_id;
}
})
.or_insert((factor, i));
.or_insert((factor, current_id));
entry = e_iter.next();
map_entry = map_iter.next();
}
@ -174,16 +174,16 @@ where
};
meta.map.reserve(reserve);
for (entry, (_, new_idx)) in map_iter {
let mut new = state.corpus().get(*new_idx)?.borrow_mut();
for (entry, (_, new_id)) in map_iter {
let mut new = state.corpus().get(*new_id)?.borrow_mut();
let new_meta = new.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
Error::key_not_found(format!(
"{} needed for MinimizerScheduler not found in testcase #{new_idx}",
"{} needed for MinimizerScheduler not found in testcase #{new_id}",
type_name::<M>()
))
})?;
*new_meta.refcnt_mut() += 1;
meta.map.insert(*entry, *new_idx);
meta.map.insert(*entry, *new_id);
}
// Put back the metadata
@ -202,9 +202,9 @@ where
O: CanTrack,
{
/// Called when a [`Testcase`] is added to the corpus
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
self.base.on_add(state, idx)?;
self.update_score(state, idx)
fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
self.base.on_add(state, id)?;
self.update_score(state, id)
}
/// An input has been evaluated
@ -223,26 +223,26 @@ where
/// Gets the next entry
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
self.cull(state)?;
let mut idx = self.base.next(state)?;
let mut id = self.base.next(state)?;
while {
let has = !state
.corpus()
.get(idx)?
.get(id)?
.borrow()
.has_metadata::<IsFavoredMetadata>();
has
} && state.rand_mut().coinflip(self.skip_non_favored_prob)
{
idx = self.base.next(state)?;
id = self.base.next(state)?;
}
Ok(idx)
Ok(id)
}
/// Set current fuzzed corpus id and `scheduled_count`
fn set_current_scheduled(
&mut self,
_state: &mut Self::State,
_next_idx: Option<CorpusId>,
_next_id: Option<CorpusId>,
) -> Result<(), Error> {
// We do nothing here, the inner scheduler will take care of it
Ok(())
@ -263,7 +263,7 @@ where
pub fn update_score(
&self,
state: &mut <Self as UsesState>::State,
idx: CorpusId,
id: CorpusId,
) -> Result<(), Error> {
// Create a new top rated meta if not existing
if state.metadata_map().get::<TopRatedsMetadata>().is_none() {
@ -272,21 +272,21 @@ where
let mut new_favoreds = vec![];
{
let mut entry = state.corpus().get(idx)?.borrow_mut();
let mut entry = state.corpus().get(id)?.borrow_mut();
let factor = F::compute(state, &mut *entry)?;
let meta = entry.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
Error::key_not_found(format!(
"Metadata needed for MinimizerScheduler not found in testcase #{idx}"
"Metadata needed for MinimizerScheduler not found in testcase #{id}"
))
})?;
let top_rateds = state.metadata_map().get::<TopRatedsMetadata>().unwrap();
for elem in meta.as_iter() {
if let Some(old_idx) = top_rateds.map.get(&*elem) {
if *old_idx == idx {
if let Some(old_id) = top_rateds.map.get(&*elem) {
if *old_id == id {
new_favoreds.push(*elem); // always retain current; we'll drop it later otherwise
continue;
}
let mut old = state.corpus().get(*old_idx)?.borrow_mut();
let mut old = state.corpus().get(*old_id)?.borrow_mut();
if factor > F::compute(state, &mut *old)? {
continue;
}
@ -294,7 +294,7 @@ where
let must_remove = {
let old_meta = old.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
Error::key_not_found(format!(
"{} needed for MinimizerScheduler not found in testcase #{old_idx}",
"{} needed for MinimizerScheduler not found in testcase #{old_id}",
type_name::<M>()
))
})?;
@ -317,7 +317,7 @@ where
drop(
state
.corpus()
.get(idx)?
.get(id)?
.borrow_mut()
.metadata_map_mut()
.remove::<M>(),
@ -331,7 +331,7 @@ where
.get_mut::<TopRatedsMetadata>()
.unwrap()
.map
.insert(elem, idx);
.insert(elem, id);
}
Ok(())
}
@ -345,12 +345,12 @@ where
let mut acc = HashSet::new();
for (key, idx) in &top_rated.map {
for (key, id) in &top_rated.map {
if !acc.contains(key) {
let mut entry = state.corpus().get(*idx)?.borrow_mut();
let mut entry = state.corpus().get(*id)?.borrow_mut();
let meta = entry.metadata_map().get::<M>().ok_or_else(|| {
Error::key_not_found(format!(
"{} needed for MinimizerScheduler not found in testcase #{idx}",
"{} needed for MinimizerScheduler not found in testcase #{id}",
type_name::<M>()
))
})?;

View File

@ -51,7 +51,7 @@ where
fn on_remove(
&mut self,
_state: &mut Self::State,
_idx: CorpusId,
_id: CorpusId,
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
) -> Result<(), Error> {
Ok(())
@ -61,7 +61,7 @@ where
fn on_replace(
&mut self,
_state: &mut Self::State,
_idx: CorpusId,
_id: CorpusId,
_prev: &Testcase<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
Ok(())
@ -85,10 +85,10 @@ where
fn map_observer_handle(&self) -> &Handle<C>;
/// Called when a [`Testcase`] is added to the corpus
fn on_add_metadata(&self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
let current_idx = *state.corpus().current();
fn on_add_metadata(&self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
let current_id = *state.corpus().current();
let mut depth = match current_idx {
let mut depth = match current_id {
Some(parent_idx) => state
.testcase(parent_idx)?
.metadata::<SchedulerTestcaseMetadata>()?
@ -101,12 +101,12 @@ where
// Attach a `SchedulerTestcaseMetadata` to the queue entry.
depth += 1;
let mut testcase = state.testcase_mut(idx)?;
let mut testcase = state.testcase_mut(id)?;
testcase.add_metadata(SchedulerTestcaseMetadata::with_n_fuzz_entry(
depth,
self.last_hash(),
));
testcase.set_parent_id_optional(current_idx);
testcase.set_parent_id_optional(current_id);
Ok(())
}
@ -142,12 +142,12 @@ where
fn on_next_metadata(
&mut self,
state: &mut Self::State,
_next_idx: Option<CorpusId>,
_next_id: Option<CorpusId>,
) -> Result<(), Error> {
let current_idx = *state.corpus().current();
let current_id = *state.corpus().current();
if let Some(idx) = current_idx {
let mut testcase = state.testcase_mut(idx)?;
if let Some(id) = current_id {
let mut testcase = state.testcase_mut(id)?;
let tcmeta = testcase.metadata_mut::<SchedulerTestcaseMetadata>()?;
if tcmeta.handicap() >= 4 {
@ -168,7 +168,7 @@ where
Self::State: HasCorpus,
{
/// Called when a [`Testcase`] is added to the corpus
fn on_add(&mut self, _state: &mut Self::State, _idx: CorpusId) -> Result<(), Error>;
fn on_add(&mut self, _state: &mut Self::State, _id: CorpusId) -> Result<(), Error>;
// Add parent_id here if it has no inner
/// An input has been evaluated
@ -192,9 +192,9 @@ where
fn set_current_scheduled(
&mut self,
state: &mut Self::State,
next_idx: Option<CorpusId>,
next_id: Option<CorpusId>,
) -> Result<(), Error> {
*state.corpus_mut().current_mut() = next_idx;
*state.corpus_mut().current_mut() = next_id;
Ok(())
}
}
@ -216,14 +216,14 @@ impl<S> Scheduler for RandScheduler<S>
where
S: HasCorpus + HasRand + HasTestcase + State,
{
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
// Set parent id
let current_idx = *state.corpus().current();
let current_id = *state.corpus().current();
state
.corpus()
.get(idx)?
.get(id)?
.borrow_mut()
.set_parent_id_optional(current_idx);
.set_parent_id_optional(current_id);
Ok(())
}

View File

@ -200,7 +200,7 @@ where
fn on_remove(
&mut self,
_state: &mut Self::State,
_idx: CorpusId,
_id: CorpusId,
_prev: &Option<Testcase<<Self::State as UsesInput>::Input>>,
) -> Result<(), Error> {
Ok(())
@ -210,7 +210,7 @@ where
fn on_replace(
&mut self,
_state: &mut Self::State,
_idx: CorpusId,
_id: CorpusId,
_prev: &Testcase<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
Ok(())
@ -243,8 +243,8 @@ where
C: AsRef<O>,
{
/// Called when a [`Testcase`] is added to the corpus
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
self.on_add_metadata(state, idx)
fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
self.on_add_metadata(state, id)
}
fn on_evaluation<OT>(
@ -287,11 +287,11 @@ where
fn set_current_scheduled(
&mut self,
state: &mut Self::State,
next_idx: Option<CorpusId>,
next_id: Option<CorpusId>,
) -> Result<(), Error> {
self.on_next_metadata(state, next_idx)?;
self.on_next_metadata(state, next_id)?;
*state.corpus_mut().current_mut() = next_idx;
*state.corpus_mut().current_mut() = next_id;
Ok(())
}
}

View File

@ -73,8 +73,8 @@ where
/// Calculate the score and store in `ProbabilityMetadata`
#[allow(clippy::cast_precision_loss)]
#[allow(clippy::unused_self)]
pub fn store_probability(&self, state: &mut S, idx: CorpusId) -> Result<(), Error> {
let prob = F::compute(state, &mut *state.corpus().get(idx)?.borrow_mut())?;
pub fn store_probability(&self, state: &mut S, id: CorpusId) -> Result<(), Error> {
let prob = F::compute(state, &mut *state.corpus().get(id)?.borrow_mut())?;
debug_assert!(
prob >= 0.0 && prob.is_finite(),
"scheduler probability is {prob}; to work correctly it must be >= 0.0 and finite"
@ -83,7 +83,7 @@ where
.metadata_map_mut()
.get_mut::<ProbabilityMetadata>()
.unwrap();
meta.map.insert(idx, prob);
meta.map.insert(id, prob);
meta.total_probability += prob;
Ok(())
}
@ -97,14 +97,14 @@ where
fn on_remove(
&mut self,
state: &mut Self::State,
idx: CorpusId,
id: CorpusId,
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
) -> Result<(), Error> {
let meta = state
.metadata_map_mut()
.get_mut::<ProbabilityMetadata>()
.unwrap();
if let Some(prob) = meta.map.remove(&idx) {
if let Some(prob) = meta.map.remove(&id) {
meta.total_probability -= prob;
}
Ok(())
@ -113,18 +113,18 @@ where
fn on_replace(
&mut self,
state: &mut Self::State,
idx: CorpusId,
id: CorpusId,
_prev: &Testcase<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
let meta = state
.metadata_map_mut()
.get_mut::<ProbabilityMetadata>()
.unwrap();
if let Some(prob) = meta.map.remove(&idx) {
if let Some(prob) = meta.map.remove(&id) {
meta.total_probability -= prob;
}
self.store_probability(state, idx)
self.store_probability(state, id)
}
}
@ -140,18 +140,18 @@ where
F: TestcaseScore<S>,
S: HasCorpus + HasMetadata + HasRand + HasTestcase + State,
{
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
let current_idx = *state.corpus().current();
fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
let current_id = *state.corpus().current();
state
.corpus()
.get(idx)?
.get(id)?
.borrow_mut()
.set_parent_id_optional(current_idx);
.set_parent_id_optional(current_id);
if state.metadata_map().get::<ProbabilityMetadata>().is_none() {
state.add_metadata(ProbabilityMetadata::new());
}
self.store_probability(state, idx)
self.store_probability(state, id)
}
/// Gets the next entry
@ -262,10 +262,10 @@ mod tests {
.unwrap();
scheduler.on_add(state.borrow_mut(), idx1).unwrap();
scheduler.on_add(state.borrow_mut(), idx2).unwrap();
let next_idx1 = scheduler.next(&mut state).unwrap();
let next_idx2 = scheduler.next(&mut state).unwrap();
let next_idx3 = scheduler.next(&mut state).unwrap();
assert_eq!(next_idx1, next_idx2);
assert_ne!(next_idx1, next_idx3);
let next_id1 = scheduler.next(&mut state).unwrap();
let next_id2 = scheduler.next(&mut state).unwrap();
let next_id3 = scheduler.next(&mut state).unwrap();
assert_eq!(next_id1, next_id2);
assert_ne!(next_id1, next_id3);
}
}

View File

@ -29,14 +29,14 @@ impl<S> Scheduler for QueueScheduler<S>
where
S: HasCorpus + HasTestcase + State,
{
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
// Set parent id
let current_idx = *state.corpus().current();
let current_id = *state.corpus().current();
state
.corpus()
.get(idx)?
.get(id)?
.borrow_mut()
.set_parent_id_optional(current_idx);
.set_parent_id_optional(current_id);
Ok(())
}
@ -112,10 +112,10 @@ mod tests {
let mut state = StdState::new(rand, q, objective_q, &mut feedback, &mut objective).unwrap();
let next_idx = scheduler.next(&mut state).unwrap();
let next_id = scheduler.next(&mut state).unwrap();
let filename = state
.corpus()
.get(next_idx)
.get(next_id)
.unwrap()
.borrow()
.filename()

View File

@ -76,14 +76,14 @@ where
let mut n_paths = 0;
let mut v = 0.0;
let cur_index = state.corpus().current().unwrap();
for idx in corpus.ids() {
let n_fuzz_entry = if cur_index == idx {
for id in corpus.ids() {
let n_fuzz_entry = if cur_index == id {
entry
.metadata::<SchedulerTestcaseMetadata>()?
.n_fuzz_entry()
} else {
corpus
.get(idx)?
.get(id)?
.borrow()
.metadata::<SchedulerTestcaseMetadata>()?
.n_fuzz_entry()

View File

@ -104,14 +104,14 @@ impl<S> Scheduler for TuneableScheduler<S>
where
S: HasCorpus + HasMetadata + HasTestcase + State,
{
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
// Set parent id
let current_idx = *state.corpus().current();
let current_id = *state.corpus().current();
state
.corpus()
.get(idx)?
.get(id)?
.borrow_mut()
.set_parent_id_optional(current_idx);
.set_parent_id_optional(current_id);
Ok(())
}

View File

@ -268,7 +268,7 @@ where
fn on_remove(
&mut self,
_state: &mut Self::State,
_idx: CorpusId,
_id: CorpusId,
_prev: &Option<Testcase<<Self::State as UsesInput>::Input>>,
) -> Result<(), Error> {
self.table_invalidated = true;
@ -279,7 +279,7 @@ where
fn on_replace(
&mut self,
_state: &mut Self::State,
_idx: CorpusId,
_id: CorpusId,
_prev: &Testcase<<Self::State as UsesInput>::Input>,
) -> Result<(), Error> {
self.table_invalidated = true;
@ -315,8 +315,8 @@ where
C: AsRef<O> + Named,
{
/// Called when a [`Testcase`] is added to the corpus
fn on_add(&mut self, state: &mut S, idx: CorpusId) -> Result<(), Error> {
self.on_add_metadata(state, idx)?;
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
self.on_add_metadata(state, id)?;
self.table_invalidated = true;
Ok(())
}
@ -385,11 +385,11 @@ where
fn set_current_scheduled(
&mut self,
state: &mut Self::State,
next_idx: Option<CorpusId>,
next_id: Option<CorpusId>,
) -> Result<(), Error> {
self.on_next_metadata(state, next_idx)?;
self.on_next_metadata(state, next_id)?;
*state.corpus_mut().current_mut() = next_idx;
*state.corpus_mut().current_mut() = next_id;
Ok(())
}
}

View File

@ -60,7 +60,7 @@ where
state: &mut Self::State,
_manager: &mut EM,
) -> Result<(), Error> {
let (mut corpus_idx, mut solutions_idx) =
let (mut corpus_id, mut solutions_id) =
if let Some(meta) = state.metadata_map().get::<DumpToDiskMetadata>() {
(
meta.last_corpus.and_then(|x| state.corpus().next(x)),
@ -70,7 +70,7 @@ where
(state.corpus().first(), state.solutions().first())
};
while let Some(i) = corpus_idx {
while let Some(i) = corpus_id {
let mut testcase = state.corpus().get(i)?.borrow_mut();
state.corpus().load_input_into(&mut testcase)?;
let bytes = (self.to_bytes)(testcase.input().as_ref().unwrap(), state);
@ -85,16 +85,16 @@ where
let mut f = File::create(fname)?;
drop(f.write_all(&bytes));
corpus_idx = state.corpus().next(i);
corpus_id = state.corpus().next(i);
}
while let Some(i) = solutions_idx {
let mut testcase = state.solutions().get(i)?.borrow_mut();
while let Some(current_id) = solutions_id {
let mut testcase = state.solutions().get(current_id)?.borrow_mut();
state.solutions().load_input_into(&mut testcase)?;
let bytes = (self.to_bytes)(testcase.input().as_ref().unwrap(), state);
let fname = self.solutions_dir.join(format!(
"id_{i}_{}",
"id_{current_id}_{}",
testcase
.filename()
.as_ref()
@ -103,7 +103,7 @@ where
let mut f = File::create(fname)?;
drop(f.write_all(&bytes));
solutions_idx = state.solutions().next(i);
solutions_id = state.solutions().next(current_id);
}
state.add_metadata(DumpToDiskMetadata {

View File

@ -81,7 +81,7 @@ where
state: &mut Self::State,
manager: &mut EM,
) -> Result<(), Error> {
let Some(corpus_idx) = state.current_corpus_id()? else {
let Some(corpus_id) = state.current_corpus_id()? else {
return Err(Error::illegal_state(
"state is not currently processing a corpus index",
));
@ -91,7 +91,7 @@ where
start_timer!(state);
{
let corpus = state.corpus();
let mut testcase = corpus.get(corpus_idx)?.borrow_mut();
let mut testcase = corpus.get(corpus_id)?.borrow_mut();
if testcase.scheduled_count() > 0 {
return Ok(());
}
@ -99,14 +99,14 @@ where
corpus.load_input_into(&mut testcase)?;
}
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
let mut entry = state.corpus().get(corpus_idx)?.borrow_mut();
let mut entry = state.corpus().get(corpus_id)?.borrow_mut();
let input = entry.input_mut().as_mut().unwrap();
let payload: Vec<_> = input.bytes().iter().map(|&x| Some(x)).collect();
let original = input.clone();
let meta = entry.metadata_map().get::<MapNoveltiesMetadata>().ok_or_else(|| {
Error::key_not_found(format!(
"MapNoveltiesMetadata needed for GeneralizationStage not found in testcase #{corpus_idx} (check the arguments of MapFeedback::new(...))"
"MapNoveltiesMetadata needed for GeneralizationStage not found in testcase #{corpus_id} (check the arguments of MapFeedback::new(...))"
))
})?;
if meta.as_slice().is_empty() {
@ -311,7 +311,7 @@ where
assert!(meta.generalized().first() == Some(&GeneralizedItem::Gap));
assert!(meta.generalized().last() == Some(&GeneralizedItem::Gap));
let mut entry = state.corpus().get(corpus_idx)?.borrow_mut();
let mut entry = state.corpus().get(corpus_id)?.borrow_mut();
entry.metadata_map_mut().insert(meta);
}
}

View File

@ -410,13 +410,13 @@ where
) -> Result<(), Error> {
let push_stage = &mut self.push_stage;
let Some(corpus_idx) = state.current_corpus_id()? else {
let Some(corpus_id) = state.current_corpus_id()? else {
return Err(Error::illegal_state(
"state is not currently processing a corpus index",
));
};
push_stage.set_current_corpus_id(corpus_idx);
push_stage.set_current_corpus_id(corpus_id);
push_stage.init(fuzzer, state, event_mgr, &mut *executor.observers_mut())?;
@ -480,7 +480,7 @@ impl RetryRestartHelper {
S: HasNamedMetadata + HasCurrentCorpusId,
ST: Named,
{
let corpus_idx = state.current_corpus_id()?.ok_or_else(|| {
let corpus_id = state.current_corpus_id()?.ok_or_else(|| {
Error::illegal_state(
"No current_corpus_id set in State, but called RetryRestartHelper::should_skip",
)
@ -504,9 +504,9 @@ impl RetryRestartHelper {
metadata.tries_remaining = Some(tries_remaining);
Ok(if tries_remaining == 0 {
metadata.skipped.insert(corpus_idx);
metadata.skipped.insert(corpus_id);
false
} else if metadata.skipped.contains(&corpus_idx) {
} else if metadata.skipped.contains(&corpus_id) {
// skip this testcase, we already retried it often enough...
false
} else {
@ -757,9 +757,9 @@ pub mod test {
let mut state = test_std_state();
let stage = StageWithOneTry;
let corpus_idx = state.corpus_mut().add(Testcase::new(NopInput {}))?;
let corpus_id = state.corpus_mut().add(Testcase::new(NopInput {}))?;
state.set_corpus_idx(corpus_idx)?;
state.set_corpus_id(corpus_id)?;
for _ in 0..10 {
// used normally, no retries means we never skip

View File

@ -27,7 +27,7 @@ use crate::{monitors::PerfFeature, state::HasClientPerfMonitor};
pub trait MutatedTransformPost<S>: Sized {
/// Perform any post-execution steps necessary for the transformed input (e.g., updating metadata)
#[inline]
fn post_exec(self, state: &mut S, new_corpus_idx: Option<CorpusId>) -> Result<(), Error> {
fn post_exec(self, state: &mut S, new_corpus_id: Option<CorpusId>) -> Result<(), Error> {
Ok(())
}
}
@ -136,11 +136,11 @@ where
// 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)?;
let (_, corpus_id) = fuzzer.evaluate_input(state, executor, manager, untransformed)?;
start_timer!(state);
self.mutator_mut().post_exec(state, corpus_idx)?;
post.post_exec(state, corpus_idx)?;
self.mutator_mut().post_exec(state, corpus_id)?;
post.post_exec(state, corpus_id)?;
mark_feature_time!(state, PerfFeature::MutatePostExec);
}
@ -347,9 +347,9 @@ where
for new_input in generated {
// Time is measured directly the `evaluate_input` function
let (untransformed, post) = new_input.try_transform_into(state)?;
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, untransformed)?;
self.mutator.multi_post_exec(state, corpus_idx)?;
post.post_exec(state, corpus_idx)?;
let (_, corpus_id) = fuzzer.evaluate_input(state, executor, manager, untransformed)?;
self.mutator.multi_post_exec(state, corpus_id)?;
post.post_exec(state, corpus_id)?;
}
// println!("Found {}", found);

View File

@ -193,8 +193,8 @@ where
fn push_stage_helper_mut(&mut self) -> &mut PushStageHelper<CS, EM, OT, Z>;
/// Set the current corpus index this stage works on
fn set_current_corpus_id(&mut self, corpus_idx: CorpusId) {
self.push_stage_helper_mut().current_corpus_id = Some(corpus_idx);
fn set_current_corpus_id(&mut self, corpus_id: CorpusId) {
self.push_stage_helper_mut().current_corpus_id = Some(corpus_id);
}
/// Called by `next_std` when this stage is being initialized.

View File

@ -71,7 +71,7 @@ where
{
/// Gets the number of iterations as a random number
#[allow(clippy::unused_self, clippy::unnecessary_wraps)] // TODO: we should put this function into a trait later
fn iterations(&self, state: &mut CS::State, _corpus_idx: CorpusId) -> Result<usize, Error> {
fn iterations(&self, state: &mut CS::State, _corpus_id: CorpusId) -> Result<usize, Error> {
Ok(1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS))
}
@ -112,8 +112,8 @@ where
_observers: &mut OT,
) -> Result<(), Error> {
// Find a testcase to work on, unless someone already set it
self.current_corpus_id = Some(if let Some(corpus_idx) = self.current_corpus_id {
corpus_idx
self.current_corpus_id = Some(if let Some(corpus_id) = self.current_corpus_id {
corpus_id
} else {
fuzzer.scheduler_mut().next(state)?
});

View File

@ -62,7 +62,7 @@ where
state: &mut Self::State,
_manager: &mut EM,
) -> Result<(), Error> {
let Some(corpus_idx) = state.current_corpus_id()? else {
let Some(corpus_id) = state.current_corpus_id()? else {
return Err(Error::illegal_state(
"state is not currently processing a corpus index",
));
@ -71,7 +71,7 @@ where
// Report your stats every `STATS_REPORT_INTERVAL`
// compute pending, pending_favored, imported, own_finds
{
let testcase = state.corpus().get(corpus_idx)?.borrow();
let testcase = state.corpus().get(corpus_id)?.borrow();
if testcase.scheduled_count() == 0 {
self.has_fuzzed_size += 1;
if testcase.has_metadata::<IsFavoredMetadata>() {

View File

@ -71,7 +71,7 @@ where
state: &mut Self::State,
manager: &mut EM,
) -> Result<(), Error> {
let Some(base_corpus_idx) = state.current_corpus_id()? else {
let Some(base_corpus_id) = state.current_corpus_id()? else {
return Err(Error::illegal_state(
"state is not currently processing a corpus index",
));
@ -118,7 +118,7 @@ where
}
let (input, post) = input_transformed.try_transform_into(state)?;
let corpus_idx = if input.len() < before_len {
let corpus_id = if input.len() < before_len {
// run the input
let exit_kind = fuzzer.execute_input(state, executor, manager, &input)?;
let observers = executor.observers();
@ -129,7 +129,7 @@ where
// TODO replace if process_execution adds a return value for solution index
let solution_count = state.solutions().count();
let corpus_count = state.corpus().count();
let (_, corpus_idx) = fuzzer.execute_and_process(
let (_, corpus_id) = fuzzer.execute_and_process(
state,
manager,
input.clone(),
@ -152,7 +152,7 @@ where
}
}
corpus_idx
corpus_id
} else {
// we can't guarantee that the mutators provided will necessarily reduce size, so
// skip any mutations that actually increase size so we don't waste eval time
@ -160,8 +160,8 @@ where
};
start_timer!(state);
self.mutator_mut().post_exec(state, corpus_idx)?;
post.post_exec(state, corpus_idx)?;
self.mutator_mut().post_exec(state, corpus_id)?;
post.post_exec(state, corpus_id)?;
mark_feature_time!(state, PerfFeature::MutatePostExec);
i = next_i;
@ -180,15 +180,15 @@ where
fuzzer
.feedback_mut()
.append_metadata(state, manager, &*observers, &mut testcase)?;
let prev = state.corpus_mut().replace(base_corpus_idx, testcase)?;
let prev = state.corpus_mut().replace(base_corpus_id, testcase)?;
fuzzer
.scheduler_mut()
.on_replace(state, base_corpus_idx, &prev)?;
.on_replace(state, base_corpus_id, &prev)?;
// perform the post operation for the new testcase, e.g. to update metadata.
// base_post should be updated along with the base (and is no longer None)
base_post
.ok_or_else(|| Error::empty_optional("Failed to get the MutatedTransformPost"))?
.post_exec(state, Some(base_corpus_idx))?;
.post_exec(state, Some(base_corpus_id))?;
}
state.set_max_size(orig_max_size);

View File

@ -456,11 +456,11 @@ where
// 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)?;
let (_, corpus_id) = fuzzer.evaluate_input(state, executor, manager, untransformed)?;
start_timer!(state);
self.mutator_mut().post_exec(state, corpus_idx)?;
post.post_exec(state, corpus_idx)?;
self.mutator_mut().post_exec(state, corpus_id)?;
post.post_exec(state, corpus_id)?;
mark_feature_time!(state, PerfFeature::MutatePostExec);
Ok(())

View File

@ -260,7 +260,7 @@ pub struct StdState<I, C, R, SC> {
/// This information is used by fuzzer `maybe_report_progress`.
last_report_time: Option<Duration>,
/// The current index of the corpus; used to record for resumable fuzzing.
corpus_idx: Option<CorpusId>,
corpus_id: Option<CorpusId>,
stage_stack: StageStack,
phantom: PhantomData<I>,
}
@ -459,18 +459,18 @@ impl<I, C, R, SC> HasStartTime for StdState<I, C, R, SC> {
}
impl<I, C, R, SC> HasCurrentCorpusId for StdState<I, C, R, SC> {
fn set_corpus_idx(&mut self, idx: CorpusId) -> Result<(), Error> {
self.corpus_idx = Some(idx);
fn set_corpus_id(&mut self, id: CorpusId) -> Result<(), Error> {
self.corpus_id = Some(id);
Ok(())
}
fn clear_corpus_idx(&mut self) -> Result<(), Error> {
self.corpus_idx = None;
fn clear_corpus_id(&mut self) -> Result<(), Error> {
self.corpus_id = None;
Ok(())
}
fn current_corpus_id(&self) -> Result<Option<CorpusId>, Error> {
Ok(self.corpus_idx)
Ok(self.corpus_id)
}
}
@ -481,19 +481,19 @@ where
{
/// Gets the current [`Testcase`] we are fuzzing
///
/// Will return [`Error::key_not_found`] if no `corpus_idx` is currently set.
/// Will return [`Error::key_not_found`] if no `corpus_id` is currently set.
fn current_testcase(&self) -> Result<Ref<'_, Testcase<I>>, Error>;
//fn current_testcase(&self) -> Result<&Testcase<I>, Error>;
/// Gets the current [`Testcase`] we are fuzzing (mut)
///
/// Will return [`Error::key_not_found`] if no `corpus_idx` is currently set.
/// Will return [`Error::key_not_found`] if no `corpus_id` is currently set.
fn current_testcase_mut(&self) -> Result<RefMut<'_, Testcase<I>>, Error>;
//fn current_testcase_mut(&self) -> Result<&mut Testcase<I>, Error>;
/// Gets a cloned representation of the current [`Testcase`].
///
/// Will return [`Error::key_not_found`] if no `corpus_idx` is currently set.
/// Will return [`Error::key_not_found`] if no `corpus_id` is currently set.
///
/// # Note
/// This allocates memory and copies the contents!
@ -1096,7 +1096,7 @@ where
#[cfg(feature = "std")]
dont_reenter: None,
last_report_time: None,
corpus_idx: None,
corpus_id: None,
stage_stack: StageStack::default(),
phantom: PhantomData,
#[cfg(feature = "std")]
@ -1214,11 +1214,11 @@ impl<I> HasRand for NopState<I> {
impl<I> State for NopState<I> where I: Input {}
impl<I> HasCurrentCorpusId for NopState<I> {
fn set_corpus_idx(&mut self, _idx: CorpusId) -> Result<(), Error> {
fn set_corpus_id(&mut self, _id: CorpusId) -> Result<(), Error> {
Ok(())
}
fn clear_corpus_idx(&mut self) -> Result<(), Error> {
fn clear_corpus_id(&mut self) -> Result<(), Error> {
Ok(())
}

View File

@ -12,6 +12,7 @@
// For `std::simd`
#![cfg_attr(nightly, feature(portable_simd))]
// For `core::error`
#![cfg_attr(nightly, feature(error_in_core))]
#![warn(clippy::cargo)]
#![allow(ambiguous_glob_reexports)]
#![deny(clippy::cargo_common_metadata)]

View File

@ -54,28 +54,28 @@ where
}
/// Touch this index and maybe evict an entry if we have touched an input which was unloaded.
fn touch(&self, idx: CorpusId, corpus: &TestcaseStorageMap<I>) -> Result<(), Error> {
fn touch(&self, id: CorpusId, corpus: &TestcaseStorageMap<I>) -> Result<(), Error> {
let mut loaded_mapping = self.loaded_mapping.borrow_mut();
let mut loaded_entries = self.loaded_entries.borrow_mut();
match loaded_mapping.entry(idx) {
match loaded_mapping.entry(id) {
Entry::Occupied(mut e) => {
let &old = e.get();
let new = self.next_recency.fetch_add(1, Ordering::Relaxed);
e.insert(new);
loaded_entries.remove(&old);
loaded_entries.insert(new, idx);
loaded_entries.insert(new, id);
}
Entry::Vacant(e) => {
// new entry! send it in
let new = self.next_recency.fetch_add(1, Ordering::Relaxed);
e.insert(new);
loaded_entries.insert(new, idx);
loaded_entries.insert(new, id);
}
}
if loaded_entries.len() > self.max_len {
let idx = loaded_entries.pop_first().unwrap().1; // cannot panic
let cell = corpus.get(idx).ok_or_else(|| {
Error::key_not_found(format!("Tried to evict non-existent entry {idx}"))
let id = loaded_entries.pop_first().unwrap().1; // cannot panic
let cell = corpus.get(id).ok_or_else(|| {
Error::key_not_found(format!("Tried to evict non-existent entry {id}"))
})?;
let mut tc = cell.try_borrow_mut()?;
let _ = tc.input_mut().take();
@ -97,7 +97,7 @@ where
testcase: RefCell<Testcase<I>>,
is_disabled: bool,
) -> Result<CorpusId, Error> {
let idx = if is_disabled {
let id = if is_disabled {
self.mapping.insert_disabled(testcase)
} else {
self.mapping.insert(testcase)
@ -107,7 +107,7 @@ where
} else {
&self.mapping.enabled
};
let mut testcase = corpus.get(idx).unwrap().borrow_mut();
let mut testcase = corpus.get(id).unwrap().borrow_mut();
match testcase.file_path() {
Some(path) if path.canonicalize()?.starts_with(&self.corpus_dir) => {
// if it's already in the correct dir, we retain it
@ -118,7 +118,7 @@ where
"The testcase, when added to the corpus, must have an input present!",
)
})?;
let name = input.generate_name(idx.into());
let name = input.generate_name(Some(id));
let path = self.corpus_dir.join(&name);
match input.to_file(&path) {
@ -134,8 +134,8 @@ where
testcase.file_path_mut().replace(path);
}
};
self.touch(idx, corpus)?;
Ok(idx)
self.touch(id, corpus)?;
Ok(id)
}
}
@ -171,7 +171,7 @@ where
fn replace(
&mut self,
_idx: CorpusId,
_id: CorpusId,
_testcase: Testcase<Self::Input>,
) -> Result<Testcase<Self::Input>, Error> {
unimplemented!("It is unsafe to use this corpus variant with replace!");
@ -335,7 +335,7 @@ where
fn replace(
&mut self,
_idx: CorpusId,
_id: CorpusId,
_testcase: Testcase<Self::Input>,
) -> Result<Testcase<Self::Input>, Error> {
unimplemented!("Artifact prefix is thin and cannot get, replace, or remove.")

View File

@ -108,7 +108,7 @@ impl LibfuzzerCrashCauseFeedback {
let base = if let Some(filename) = testcase.filename() {
filename.clone()
} else {
let name = testcase.input().as_ref().unwrap().generate_name(0);
let name = testcase.input().as_ref().unwrap().generate_name(None);
name
};
let file_path = self.artifact_prefix.dir().join(format!(

View File

@ -206,15 +206,15 @@ pub fn merge(
});
}
for idx in fuzzer.scheduler().removable() {
let testcase = state.corpus_mut().remove(idx)?;
for id in fuzzer.scheduler().removable() {
let testcase = state.corpus_mut().remove(id)?;
fuzzer
.scheduler_mut()
.on_remove(&mut state, idx, &Some(testcase))?;
.on_remove(&mut state, id, &Some(testcase))?;
}
for idx in fuzzer.scheduler().current().clone() {
let mut testcase = state.corpus_mut().get(idx)?.borrow_mut();
for id in fuzzer.scheduler().current().clone() {
let mut testcase = state.corpus_mut().get(id)?.borrow_mut();
let file_path = testcase
.file_path_mut()
.as_mut()
@ -231,10 +231,10 @@ pub fn merge(
new_file_path.push(base);
if new_file_path.exists() {
drop(testcase);
let testcase = state.corpus_mut().remove(idx)?;
let testcase = state.corpus_mut().remove(id)?;
fuzzer
.scheduler_mut()
.on_remove(&mut state, idx, &Some(testcase))?;
.on_remove(&mut state, id, &Some(testcase))?;
} else {
// False-positive: file_path is used just below
#[allow(clippy::needless_borrows_for_generic_args)]

View File

@ -33,10 +33,10 @@ where
fn on_remove(
&mut self,
_state: &mut Self::State,
idx: CorpusId,
id: CorpusId,
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
) -> Result<(), Error> {
self.all.remove(&idx);
self.all.remove(&id);
Ok(())
}
}
@ -45,12 +45,12 @@ impl<S> Scheduler for MergeScheduler<S>
where
S: State + HasCorpus,
{
fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
self.all.insert(idx);
let testcase = state.corpus().get(idx)?.borrow();
fn on_add(&mut self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
self.all.insert(id);
let testcase = state.corpus().get(id)?.borrow();
let meta = testcase.metadata::<MapNoveltiesMetadata>()?;
for cov_idx in &meta.list {
self.mapping.insert(*cov_idx, idx);
for cov_ in &meta.list {
self.mapping.insert(*cov_, id);
}
Ok(())
}

View File

@ -396,15 +396,15 @@ where
state: &mut S,
input: &mut S::Input,
) -> Result<MutationResult, Error> {
let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
// We don't want to use the testcase we're already using for splicing
let idx = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
if let Some(cur) = state.corpus().current() {
if idx == *cur {
if id == *cur {
return Ok(MutationResult::Skipped);
}
}
let mut other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
let mut other_testcase = state.corpus().get_from_all(id)?.borrow_mut();
let other = other_testcase.load_input(state.corpus())?;
let data2 = Vec::from(other.bytes());
drop(other_testcase);

View File

@ -1,3 +1,5 @@
//! Stub out syscalls. Linux only.
use std::ptr;
use libc::{c_int, c_void, off_t, size_t};
@ -41,6 +43,7 @@ extern "C" {
/// Call to functions using syscalls
#[no_mangle]
#[allow(clippy::too_many_lines)]
#[cfg(not(windows))]
pub unsafe extern "C" fn mmap(
addr: Pointer,
length: size_t,
@ -57,7 +60,10 @@ pub unsafe extern "C" fn mmap(
// validity checks
if length == 0 || length % PAGE_SIZE != 0 || (addr as usize) % PAGE_SIZE != 0 {
*libc::__errno_location() = libc::EINVAL;
#[cfg(target_os = "linux")]
{
*libc::__errno_location() = libc::EINVAL;
}
return libc::MAP_FAILED as Pointer;
}
@ -231,7 +237,10 @@ pub unsafe extern "C" fn munmap(addr: *mut c_void, length: size_t) -> c_int {
// validity checks
if length == 0 || (addr as usize) % PAGE_SIZE != 0 {
*libc::__errno_location() = libc::EINVAL;
#[cfg(target_os = "linux")]
{
*libc::__errno_location() = libc::EINVAL;
}
return -1;
}
let aligned_length = if length % PAGE_SIZE != 0 {
@ -435,9 +444,9 @@ pub unsafe extern "C" fn mprotect(addr: *mut c_void, length: size_t, prot: c_int
/// # Safety
/// Call to functions using syscalls
#[no_mangle]
#[cfg(not(windows))]
pub unsafe extern "C" fn madvise(addr: *mut c_void, length: size_t, advice: c_int) -> c_int {
let ctx = Context::get();
if ctx.enabled && advice == libc::MADV_DONTNEED {
0
} else {
@ -445,7 +454,7 @@ pub unsafe extern "C" fn madvise(addr: *mut c_void, length: size_t, advice: c_in
}
}
#[cfg(test)]
#[cfg(all(test, target_os = "linux"))]
mod tests {
use rusty_fork::rusty_fork_test;