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:
parent
a2da080fa6
commit
042840dba1
@ -138,7 +138,9 @@ pub fn main() -> Result<(), Error> {
|
|||||||
|
|
||||||
state.load_initial_inputs_forced(&mut fuzzer, &mut executor, &mut mgr, &[solution_dir])?;
|
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)?;
|
stages.perform_all(&mut fuzzer, &mut executor, &mut state, &mut mgr)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use lain::prelude::*;
|
use lain::prelude::*;
|
||||||
use libafl::inputs::{HasTargetBytes, Input};
|
use libafl::{
|
||||||
|
corpus::CorpusId,
|
||||||
|
inputs::{HasTargetBytes, Input},
|
||||||
|
};
|
||||||
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
|
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -45,8 +48,12 @@ pub enum PacketType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Input for PacketData {
|
impl Input for PacketData {
|
||||||
fn generate_name(&self, idx: usize) -> String {
|
fn generate_name(&self, id: Option<CorpusId>) -> String {
|
||||||
format!("id_{idx}")
|
if let Some(id) = id {
|
||||||
|
format!("id_{}", id.0)
|
||||||
|
} else {
|
||||||
|
"id_unknown".into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ where
|
|||||||
fn cache_testcase<'a>(
|
fn cache_testcase<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
testcase: &'a RefCell<Testcase<I>>,
|
testcase: &'a RefCell<Testcase<I>>,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if testcase.borrow().input().is_none() {
|
if testcase.borrow().input().is_none() {
|
||||||
self.load_input_into(&mut testcase.borrow_mut())?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -102,30 +102,30 @@ where
|
|||||||
|
|
||||||
/// Replaces the testcase at the given idx
|
/// Replaces the testcase at the given idx
|
||||||
#[inline]
|
#[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
|
// 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.
|
/// 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> {
|
fn remove(&mut self, id: CorpusId) -> Result<Testcase<Self::Input>, Error> {
|
||||||
let testcase = self.inner.remove(idx)?;
|
let testcase = self.inner.remove(id)?;
|
||||||
self.cached_indexes.borrow_mut().retain(|e| *e != idx);
|
self.cached_indexes.borrow_mut().retain(|e| *e != id);
|
||||||
Ok(testcase)
|
Ok(testcase)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get by id; considers only enabled testcases
|
/// Get by id; considers only enabled testcases
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
|
fn get(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
|
||||||
let testcase = { self.inner.get(idx)? };
|
let testcase = { self.inner.get(id)? };
|
||||||
self.cache_testcase(testcase, idx)?;
|
self.cache_testcase(testcase, id)?;
|
||||||
Ok(testcase)
|
Ok(testcase)
|
||||||
}
|
}
|
||||||
/// Get by id; considers both enabled and disabled testcases
|
/// Get by id; considers both enabled and disabled testcases
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_from_all(&self, idx: CorpusId) -> Result<&RefCell<Testcase<Self::Input>>, Error> {
|
fn get_from_all(&self, id: CorpusId) -> Result<&RefCell<Testcase<Self::Input>>, Error> {
|
||||||
let testcase = { self.inner.get_from_all(idx)? };
|
let testcase = { self.inner.get_from_all(id)? };
|
||||||
self.cache_testcase(testcase, idx)?;
|
self.cache_testcase(testcase, id)?;
|
||||||
Ok(testcase)
|
Ok(testcase)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,8 +142,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&self, idx: CorpusId) -> Option<CorpusId> {
|
fn next(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
self.inner.next(idx)
|
self.inner.next(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peek the next free corpus id
|
/// Peek the next free corpus id
|
||||||
@ -153,8 +153,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
|
fn prev(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
self.inner.prev(idx)
|
self.inner.prev(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -43,12 +43,12 @@ where
|
|||||||
pub map: alloc::collections::btree_map::BTreeMap<CorpusId, RefCell<Testcase<I>>>,
|
pub map: alloc::collections::btree_map::BTreeMap<CorpusId, RefCell<Testcase<I>>>,
|
||||||
/// The keys in order (use `Vec::binary_search`)
|
/// The keys in order (use `Vec::binary_search`)
|
||||||
pub keys: Vec<CorpusId>,
|
pub keys: Vec<CorpusId>,
|
||||||
/// First inserted idx
|
/// First inserted id
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
first_idx: Option<CorpusId>,
|
first_id: Option<CorpusId>,
|
||||||
/// Last inserted idx
|
/// Last inserted id
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
last_idx: Option<CorpusId>,
|
last_id: Option<CorpusId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> TestcaseStorageMap<I>
|
impl<I> TestcaseStorageMap<I>
|
||||||
@ -71,8 +71,8 @@ where
|
|||||||
|
|
||||||
/// Replace a testcase given a `CorpusId`
|
/// Replace a testcase given a `CorpusId`
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
pub fn replace(&mut self, idx: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
|
pub fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
|
||||||
if let Some(entry) = self.map.get_mut(&idx) {
|
if let Some(entry) = self.map.get_mut(&id) {
|
||||||
Some(entry.testcase.replace(testcase))
|
Some(entry.testcase.replace(testcase))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -81,26 +81,26 @@ where
|
|||||||
|
|
||||||
/// Replace a testcase given a `CorpusId`
|
/// Replace a testcase given a `CorpusId`
|
||||||
#[cfg(feature = "corpus_btreemap")]
|
#[cfg(feature = "corpus_btreemap")]
|
||||||
pub fn replace(&mut self, idx: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
|
pub fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
|
||||||
self.map.get_mut(&idx).map(|entry| entry.replace(testcase))
|
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"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
pub fn remove(&mut self, idx: CorpusId) -> Option<RefCell<Testcase<I>>> {
|
pub fn remove(&mut self, id: CorpusId) -> Option<RefCell<Testcase<I>>> {
|
||||||
if let Some(item) = self.map.remove(&idx) {
|
if let Some(item) = self.map.remove(&id) {
|
||||||
self.remove_key(idx);
|
self.remove_key(id);
|
||||||
if let Some(prev) = item.prev {
|
if let Some(prev) = item.prev {
|
||||||
self.map.get_mut(&prev).unwrap().next = item.next;
|
self.map.get_mut(&prev).unwrap().next = item.next;
|
||||||
} else {
|
} else {
|
||||||
// first elem
|
// first elem
|
||||||
self.first_idx = item.next;
|
self.first_id = item.next;
|
||||||
}
|
}
|
||||||
if let Some(next) = item.next {
|
if let Some(next) = item.next {
|
||||||
self.map.get_mut(&next).unwrap().prev = item.prev;
|
self.map.get_mut(&next).unwrap().prev = item.prev;
|
||||||
} else {
|
} else {
|
||||||
// last elem
|
// last elem
|
||||||
self.last_idx = item.prev;
|
self.last_id = item.prev;
|
||||||
}
|
}
|
||||||
Some(item.testcase)
|
Some(item.testcase)
|
||||||
} else {
|
} else {
|
||||||
@ -108,32 +108,32 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a testcase given a `CorpusId`
|
/// Remove a testcase given a [`CorpusId`]
|
||||||
#[cfg(feature = "corpus_btreemap")]
|
#[cfg(feature = "corpus_btreemap")]
|
||||||
pub fn remove(&mut self, idx: CorpusId) -> Option<RefCell<Testcase<I>>> {
|
pub fn remove(&mut self, id: CorpusId) -> Option<RefCell<Testcase<I>>> {
|
||||||
self.remove_key(idx);
|
self.remove_key(id);
|
||||||
self.map.remove(&idx)
|
self.map.remove(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a testcase given a `CorpusId`
|
/// Get a testcase given a `CorpusId`
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get(&self, idx: CorpusId) -> Option<&RefCell<Testcase<I>>> {
|
pub fn get(&self, id: CorpusId) -> Option<&RefCell<Testcase<I>>> {
|
||||||
self.map.get(&idx).as_ref().map(|x| &x.testcase)
|
self.map.get(&id).as_ref().map(|x| &x.testcase)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a testcase given a `CorpusId`
|
/// Get a testcase given a `CorpusId`
|
||||||
#[cfg(feature = "corpus_btreemap")]
|
#[cfg(feature = "corpus_btreemap")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get(&self, idx: CorpusId) -> Option<&RefCell<Testcase<I>>> {
|
pub fn get(&self, id: CorpusId) -> Option<&RefCell<Testcase<I>>> {
|
||||||
self.map.get(&idx)
|
self.map.get(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next id given a `CorpusId` (creation order)
|
/// Get the next id given a `CorpusId` (creation order)
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn next(&self, idx: CorpusId) -> Option<CorpusId> {
|
pub fn next(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
if let Some(item) = self.map.get(&idx) {
|
if let Some(item) = self.map.get(&id) {
|
||||||
item.next
|
item.next
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -143,13 +143,13 @@ where
|
|||||||
/// Get the next id given a `CorpusId` (creation order)
|
/// Get the next id given a `CorpusId` (creation order)
|
||||||
#[cfg(feature = "corpus_btreemap")]
|
#[cfg(feature = "corpus_btreemap")]
|
||||||
#[must_use]
|
#[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
|
// TODO see if using self.keys is faster
|
||||||
let mut range = self
|
let mut range = self
|
||||||
.map
|
.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 let Some((this_id, _)) = range.next() {
|
||||||
if idx != *this_id {
|
if id != *this_id {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,8 +163,8 @@ where
|
|||||||
/// Get the previous id given a `CorpusId` (creation order)
|
/// Get the previous id given a `CorpusId` (creation order)
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
|
pub fn prev(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
if let Some(item) = self.map.get(&idx) {
|
if let Some(item) = self.map.get(&id) {
|
||||||
item.prev
|
item.prev
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -174,13 +174,13 @@ where
|
|||||||
/// Get the previous id given a `CorpusId` (creation order)
|
/// Get the previous id given a `CorpusId` (creation order)
|
||||||
#[cfg(feature = "corpus_btreemap")]
|
#[cfg(feature = "corpus_btreemap")]
|
||||||
#[must_use]
|
#[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
|
// TODO see if using self.keys is faster
|
||||||
let mut range = self
|
let mut range = self
|
||||||
.map
|
.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 let Some((this_id, _)) = range.next_back() {
|
||||||
if idx != *this_id {
|
if id != *this_id {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ where
|
|||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn first(&self) -> Option<CorpusId> {
|
pub fn first(&self) -> Option<CorpusId> {
|
||||||
self.first_idx
|
self.first_id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the first created id
|
/// Get the first created id
|
||||||
@ -209,7 +209,7 @@ where
|
|||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn last(&self) -> Option<CorpusId> {
|
pub fn last(&self) -> Option<CorpusId> {
|
||||||
self.last_idx
|
self.last_id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the last created id
|
/// Get the last created id
|
||||||
@ -227,9 +227,9 @@ where
|
|||||||
map: alloc::collections::BTreeMap::default(),
|
map: alloc::collections::BTreeMap::default(),
|
||||||
keys: Vec::default(),
|
keys: Vec::default(),
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
first_idx: None,
|
first_id: None,
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
last_idx: None,
|
last_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,8 +244,8 @@ where
|
|||||||
pub enabled: TestcaseStorageMap<I>,
|
pub enabled: TestcaseStorageMap<I>,
|
||||||
/// The map in which disabled testcases are stored
|
/// The map in which disabled testcases are stored
|
||||||
pub disabled: TestcaseStorageMap<I>,
|
pub disabled: TestcaseStorageMap<I>,
|
||||||
/// The progressive idx for both maps
|
/// The progressive id for both maps
|
||||||
progressive_idx: usize,
|
progressive_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> UsesInput for TestcaseStorage<I>
|
impl<I> UsesInput for TestcaseStorage<I>
|
||||||
@ -267,58 +267,59 @@ where
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
/// Peek the next free corpus id
|
/// Peek the next free corpus id
|
||||||
pub fn peek_free_id(&self) -> CorpusId {
|
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
|
/// Insert a testcase assigning a `CorpusId` to it
|
||||||
pub fn insert_disabled(&mut self, testcase: RefCell<Testcase<I>>) -> CorpusId {
|
pub fn insert_disabled(&mut self, testcase: RefCell<Testcase<I>>) -> CorpusId {
|
||||||
self._insert(testcase, true)
|
self._insert(testcase, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a testcase assigning a `CorpusId` to it
|
/// Insert a testcase assigning a `CorpusId` to it
|
||||||
#[cfg(not(feature = "corpus_btreemap"))]
|
#[cfg(not(feature = "corpus_btreemap"))]
|
||||||
fn _insert(&mut self, testcase: RefCell<Testcase<I>>, is_disabled: bool) -> CorpusId {
|
fn _insert(&mut self, testcase: RefCell<Testcase<I>>, is_disabled: bool) -> CorpusId {
|
||||||
let idx = CorpusId::from(self.progressive_idx);
|
let id = CorpusId::from(self.progressive_id);
|
||||||
self.progressive_idx += 1;
|
self.progressive_id += 1;
|
||||||
let corpus = if is_disabled {
|
let corpus = if is_disabled {
|
||||||
&mut self.disabled
|
&mut self.disabled
|
||||||
} else {
|
} else {
|
||||||
&mut self.enabled
|
&mut self.enabled
|
||||||
};
|
};
|
||||||
let prev = if let Some(last_idx) = corpus.last_idx {
|
let prev = if let Some(last_id) = corpus.last_id {
|
||||||
corpus.map.get_mut(&last_idx).unwrap().next = Some(idx);
|
corpus.map.get_mut(&last_id).unwrap().next = Some(id);
|
||||||
Some(last_idx)
|
Some(last_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
if corpus.first_idx.is_none() {
|
if corpus.first_id.is_none() {
|
||||||
corpus.first_idx = Some(idx);
|
corpus.first_id = Some(id);
|
||||||
}
|
}
|
||||||
corpus.last_idx = Some(idx);
|
corpus.last_id = Some(id);
|
||||||
corpus.insert_key(idx);
|
corpus.insert_key(id);
|
||||||
corpus.map.insert(
|
corpus.map.insert(
|
||||||
idx,
|
id,
|
||||||
TestcaseStorageItem {
|
TestcaseStorageItem {
|
||||||
testcase,
|
testcase,
|
||||||
prev,
|
prev,
|
||||||
next: None,
|
next: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
idx
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a testcase assigning a `CorpusId` to it
|
/// Insert a testcase assigning a `CorpusId` to it
|
||||||
#[cfg(feature = "corpus_btreemap")]
|
#[cfg(feature = "corpus_btreemap")]
|
||||||
fn _insert(&mut self, testcase: RefCell<Testcase<I>>, is_disabled: bool) -> CorpusId {
|
fn _insert(&mut self, testcase: RefCell<Testcase<I>>, is_disabled: bool) -> CorpusId {
|
||||||
let idx = CorpusId::from(self.progressive_idx);
|
let id = CorpusId::from(self.progressive_id);
|
||||||
self.progressive_idx += 1;
|
self.progressive_id += 1;
|
||||||
let corpus = if is_disabled {
|
let corpus = if is_disabled {
|
||||||
&mut self.disabled
|
&mut self.disabled
|
||||||
} else {
|
} else {
|
||||||
&mut self.enabled
|
&mut self.enabled
|
||||||
};
|
};
|
||||||
corpus.insert_key(idx);
|
corpus.insert_key(id);
|
||||||
corpus.map.insert(idx, testcase);
|
corpus.map.insert(id, testcase);
|
||||||
idx
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new `TestcaseStorage`
|
/// Create new `TestcaseStorage`
|
||||||
@ -327,7 +328,7 @@ where
|
|||||||
Self {
|
Self {
|
||||||
enabled: TestcaseStorageMap::new(),
|
enabled: TestcaseStorageMap::new(),
|
||||||
disabled: TestcaseStorageMap::new(),
|
disabled: TestcaseStorageMap::new(),
|
||||||
progressive_idx: 0,
|
progressive_id: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,43 +388,42 @@ where
|
|||||||
Ok(self.storage.insert_disabled(RefCell::new(testcase)))
|
Ok(self.storage.insert_disabled(RefCell::new(testcase)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces the testcase at the given idx
|
/// Replaces the testcase at the given id
|
||||||
#[inline]
|
#[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> {
|
||||||
self.storage
|
self.storage.enabled.replace(id, testcase).ok_or_else(|| {
|
||||||
.enabled
|
Error::key_not_found(format!("Index {id} not found, could not replace."))
|
||||||
.replace(idx, testcase)
|
})
|
||||||
.ok_or_else(|| Error::key_not_found(format!("Index {idx} not found")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases
|
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases
|
||||||
#[inline]
|
#[inline]
|
||||||
fn remove(&mut self, idx: CorpusId) -> Result<Testcase<Self::Input>, Error> {
|
fn remove(&mut self, id: CorpusId) -> Result<Testcase<Self::Input>, Error> {
|
||||||
let mut testcase = self.storage.enabled.remove(idx);
|
let mut testcase = self.storage.enabled.remove(id);
|
||||||
if testcase.is_none() {
|
if testcase.is_none() {
|
||||||
testcase = self.storage.disabled.remove(idx);
|
testcase = self.storage.disabled.remove(id);
|
||||||
}
|
}
|
||||||
testcase
|
testcase
|
||||||
.map(|x| x.take())
|
.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
|
/// Get by id; considers only enabled testcases
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
|
fn get(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
|
||||||
self.storage
|
self.storage
|
||||||
.enabled
|
.enabled
|
||||||
.get(idx)
|
.get(id)
|
||||||
.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 both enabled and disabled testcases
|
/// Get by id; considers both enabled and disabled testcases
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_from_all(&self, idx: CorpusId) -> Result<&RefCell<Testcase<Self::Input>>, Error> {
|
fn get_from_all(&self, id: CorpusId) -> Result<&RefCell<Testcase<Self::Input>>, Error> {
|
||||||
let mut testcase = self.storage.enabled.get(idx);
|
let mut testcase = self.storage.enabled.get(id);
|
||||||
if testcase.is_none() {
|
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
|
/// Current testcase scheduled
|
||||||
@ -445,13 +445,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&self, idx: CorpusId) -> Option<CorpusId> {
|
fn next(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
self.storage.enabled.next(idx)
|
self.storage.enabled.next(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
|
fn prev(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
self.storage.enabled.prev(idx)
|
self.storage.enabled.prev(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -74,52 +74,52 @@ where
|
|||||||
/// Add an enabled testcase to the corpus and return its index
|
/// Add an enabled testcase to the corpus and return its index
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(&mut self, testcase: Testcase<I>) -> Result<CorpusId, Error> {
|
fn add(&mut self, testcase: Testcase<I>) -> Result<CorpusId, Error> {
|
||||||
let idx = self.inner.add(testcase)?;
|
let id = self.inner.add(testcase)?;
|
||||||
let testcase = &mut self.get(idx).unwrap().borrow_mut();
|
let testcase = &mut self.get(id).unwrap().borrow_mut();
|
||||||
self.save_testcase(testcase, idx)?;
|
self.save_testcase(testcase, id)?;
|
||||||
*testcase.input_mut() = None;
|
*testcase.input_mut() = None;
|
||||||
Ok(idx)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a disabled testcase to the corpus and return its index
|
/// Add a disabled testcase to the corpus and return its index
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_disabled(&mut self, testcase: Testcase<I>) -> Result<CorpusId, Error> {
|
fn add_disabled(&mut self, testcase: Testcase<I>) -> Result<CorpusId, Error> {
|
||||||
let idx = self.inner.add_disabled(testcase)?;
|
let id = self.inner.add_disabled(testcase)?;
|
||||||
let testcase = &mut self.get_from_all(idx).unwrap().borrow_mut();
|
let testcase = &mut self.get_from_all(id).unwrap().borrow_mut();
|
||||||
self.save_testcase(testcase, idx)?;
|
self.save_testcase(testcase, id)?;
|
||||||
*testcase.input_mut() = None;
|
*testcase.input_mut() = None;
|
||||||
Ok(idx)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces the testcase at the given idx
|
/// Replaces the testcase at the given idx
|
||||||
#[inline]
|
#[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> {
|
||||||
let entry = self.inner.replace(idx, testcase)?;
|
let entry = self.inner.replace(id, testcase)?;
|
||||||
self.remove_testcase(&entry)?;
|
self.remove_testcase(&entry)?;
|
||||||
let testcase = &mut self.get(idx).unwrap().borrow_mut();
|
let testcase = &mut self.get(id).unwrap().borrow_mut();
|
||||||
self.save_testcase(testcase, idx)?;
|
self.save_testcase(testcase, id)?;
|
||||||
*testcase.input_mut() = None;
|
*testcase.input_mut() = None;
|
||||||
Ok(entry)
|
Ok(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled corpus
|
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled corpus
|
||||||
#[inline]
|
#[inline]
|
||||||
fn remove(&mut self, idx: CorpusId) -> Result<Testcase<I>, Error> {
|
fn remove(&mut self, id: CorpusId) -> Result<Testcase<I>, Error> {
|
||||||
let entry = self.inner.remove(idx)?;
|
let entry = self.inner.remove(id)?;
|
||||||
self.remove_testcase(&entry)?;
|
self.remove_testcase(&entry)?;
|
||||||
Ok(entry)
|
Ok(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get by id; considers only enabled testcases
|
/// Get by id; considers only enabled testcases
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
|
fn get(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
|
||||||
self.inner.get(idx)
|
self.inner.get(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get by id; considers both enabled and disabled testcases
|
/// Get by id; considers both enabled and disabled testcases
|
||||||
#[inline]
|
#[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> {
|
||||||
self.inner.get_from_all(idx)
|
self.inner.get_from_all(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Current testcase scheduled
|
/// Current testcase scheduled
|
||||||
@ -135,8 +135,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&self, idx: CorpusId) -> Option<CorpusId> {
|
fn next(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
self.inner.next(idx)
|
self.inner.next(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peek the next free corpus id
|
/// Peek the next free corpus id
|
||||||
@ -146,8 +146,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
|
fn prev(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
self.inner.prev(idx)
|
self.inner.prev(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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(|| {
|
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)
|
// 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.
|
// New testcase, we need to save it.
|
||||||
|
@ -116,9 +116,9 @@ where
|
|||||||
|
|
||||||
let total = state.corpus().count() as u64;
|
let total = state.corpus().count() as u64;
|
||||||
let mut curr = 0;
|
let mut curr = 0;
|
||||||
while let Some(idx) = cur_id {
|
while let Some(id) = cur_id {
|
||||||
let (weight, input) = {
|
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)?
|
let weight = TS::compute(state, &mut *testcase)?
|
||||||
.to_u64()
|
.to_u64()
|
||||||
.expect("Weight must be computable.");
|
.expect("Weight must be computable.");
|
||||||
@ -177,9 +177,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keep track of that seed's index and weight
|
// 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(
|
manager.log(
|
||||||
@ -215,21 +215,21 @@ where
|
|||||||
|
|
||||||
let res = if let Some(model) = opt.get_model() {
|
let res = if let Some(model) = opt.get_model() {
|
||||||
let mut removed = Vec::with_capacity(state.corpus().count());
|
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 the model says the seed isn't there, mark it for deletion
|
||||||
if !model.eval(&seed, true).unwrap().as_bool().unwrap() {
|
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
|
// 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));
|
removed.sort_unstable_by(|id1, id2| id2.cmp(id1));
|
||||||
for idx in removed {
|
for id in removed {
|
||||||
let removed = state.corpus_mut().remove(idx)?;
|
let removed = state.corpus_mut().remove(id)?;
|
||||||
// scheduler needs to know we've removed the input, or it will continue to try
|
// scheduler needs to know we've removed the input, or it will continue to try
|
||||||
// to use now-missing inputs
|
// to use now-missing inputs
|
||||||
fuzzer
|
fuzzer
|
||||||
.scheduler_mut()
|
.scheduler_mut()
|
||||||
.on_remove(state, idx, &Some(removed))?;
|
.on_remove(state, id, &Some(removed))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,7 +36,7 @@ use crate::{inputs::UsesInput, Error};
|
|||||||
/// An abstraction for the index that identify a testcase in the corpus
|
/// An abstraction for the index that identify a testcase in the corpus
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct CorpusId(pub(crate) usize);
|
pub struct CorpusId(pub usize);
|
||||||
|
|
||||||
impl fmt::Display for CorpusId {
|
impl fmt::Display for CorpusId {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
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.
|
/// Replaces the [`Testcase`] at the given idx, returning the existing.
|
||||||
fn replace(
|
fn replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
testcase: Testcase<Self::Input>,
|
testcase: Testcase<Self::Input>,
|
||||||
) -> Result<Testcase<Self::Input>, Error>;
|
) -> 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>;
|
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.
|
/// 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> {
|
fn cloned_input_for_id(&self, id: CorpusId) -> Result<Self::Input, Error> {
|
||||||
let mut testcase = self.get(idx)?.borrow_mut();
|
let mut testcase = self.get(id)?.borrow_mut();
|
||||||
Ok(testcase.load_input(self)?.clone())
|
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
|
/// Trait for types which track the current corpus index
|
||||||
pub trait HasCurrentCorpusId {
|
pub trait HasCurrentCorpusId {
|
||||||
/// Set the current corpus index; we have started processing this corpus entry
|
/// 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
|
/// 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
|
/// Fetch the current corpus index -- typically used after a state recovery or transfer
|
||||||
fn current_corpus_id(&self) -> Result<Option<CorpusId>, Error>;
|
fn current_corpus_id(&self) -> Result<Option<CorpusId>, Error>;
|
||||||
|
@ -57,27 +57,27 @@ where
|
|||||||
Err(Error::unsupported("Unsupported by NopCorpus"))
|
Err(Error::unsupported("Unsupported by NopCorpus"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces the testcase at the given idx
|
/// Replaces the testcase with the given id
|
||||||
#[inline]
|
#[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"))
|
Err(Error::unsupported("Unsupported by NopCorpus"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases
|
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases
|
||||||
#[inline]
|
#[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"))
|
Err(Error::unsupported("Unsupported by NopCorpus"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get by id; considers only enabled testcases
|
/// Get by id; considers only enabled testcases
|
||||||
#[inline]
|
#[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"))
|
Err(Error::unsupported("Unsupported by NopCorpus"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get by id; considers both enabled and disabled testcases
|
/// Get by id; considers both enabled and disabled testcases
|
||||||
#[inline]
|
#[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"))
|
Err(Error::unsupported("Unsupported by NopCorpus"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,12 +100,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&self, _idx: CorpusId) -> Option<CorpusId> {
|
fn next(&self, _id: CorpusId) -> Option<CorpusId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn prev(&self, _idx: CorpusId) -> Option<CorpusId> {
|
fn prev(&self, _id: CorpusId) -> Option<CorpusId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +102,8 @@ where
|
|||||||
|
|
||||||
/// Replaces the testcase at the given idx
|
/// Replaces the testcase at the given idx
|
||||||
#[inline]
|
#[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> {
|
||||||
self.inner.replace(idx, testcase)
|
self.inner.replace(id, testcase)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peek the next free corpus id
|
/// 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
|
/// Removes an entry from the corpus, returning it if it was present; considers both enabled and disabled testcases
|
||||||
#[inline]
|
#[inline]
|
||||||
fn remove(&mut self, idx: CorpusId) -> Result<Testcase<I>, Error> {
|
fn remove(&mut self, id: CorpusId) -> Result<Testcase<I>, Error> {
|
||||||
self.inner.remove(idx)
|
self.inner.remove(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get by id; will check the disabled corpus if not available in the enabled
|
/// Get by id; will check the disabled corpus if not available in the enabled
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, idx: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
|
fn get(&self, id: CorpusId) -> Result<&RefCell<Testcase<I>>, Error> {
|
||||||
self.inner.get(idx)
|
self.inner.get(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get by id; considers both enabled and disabled testcases
|
/// Get by id; considers both enabled and disabled testcases
|
||||||
#[inline]
|
#[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> {
|
||||||
self.inner.get_from_all(idx)
|
self.inner.get_from_all(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Current testcase scheduled
|
/// Current testcase scheduled
|
||||||
@ -143,13 +143,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&self, idx: CorpusId) -> Option<CorpusId> {
|
fn next(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
self.inner.next(idx)
|
self.inner.next(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn prev(&self, idx: CorpusId) -> Option<CorpusId> {
|
fn prev(&self, id: CorpusId) -> Option<CorpusId> {
|
||||||
self.inner.prev(idx)
|
self.inner.prev(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -383,7 +383,7 @@ where
|
|||||||
fn name_detailed(&self) -> String {
|
fn name_detailed(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Event::NewTestcase { input, .. } => {
|
Event::NewTestcase { input, .. } => {
|
||||||
format!("Testcase {}", input.generate_name(0))
|
format!("Testcase {}", input.generate_name(None))
|
||||||
}
|
}
|
||||||
Event::UpdateExecStats { .. } => "Client Heartbeat".to_string(),
|
Event::UpdateExecStats { .. } => "Client Heartbeat".to_string(),
|
||||||
Event::UpdateUserStats { .. } => "UserStats".to_string(),
|
Event::UpdateUserStats { .. } => "UserStats".to_string(),
|
||||||
|
@ -204,7 +204,7 @@ pub mod unix_signal_handler {
|
|||||||
let mut bsod = Vec::new();
|
let mut bsod = Vec::new();
|
||||||
{
|
{
|
||||||
let mut writer = std::io::BufWriter::new(&mut bsod);
|
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(
|
let bsod = libafl_bolts::minibsod::generate_minibsod(
|
||||||
&mut writer,
|
&mut writer,
|
||||||
signal,
|
signal,
|
||||||
|
@ -400,7 +400,7 @@ pub mod windows_exception_handler {
|
|||||||
let mut bsod = Vec::new();
|
let mut bsod = Vec::new();
|
||||||
{
|
{
|
||||||
let mut writer = std::io::BufWriter::new(&mut bsod);
|
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)
|
libafl_bolts::minibsod::generate_minibsod(&mut writer, exception_pointers)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
writer.flush().unwrap();
|
writer.flush().unwrap();
|
||||||
|
@ -413,7 +413,7 @@ where
|
|||||||
EM: EventFirer<State = Self::State>,
|
EM: EventFirer<State = Self::State>,
|
||||||
{
|
{
|
||||||
let exec_res = self.execute_no_process(state, manager, &input, observers, exit_kind)?;
|
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,
|
state,
|
||||||
manager,
|
manager,
|
||||||
input,
|
input,
|
||||||
@ -422,7 +422,7 @@ where
|
|||||||
exit_kind,
|
exit_kind,
|
||||||
send_events,
|
send_events,
|
||||||
)?;
|
)?;
|
||||||
Ok((exec_res, corpus_idx))
|
Ok((exec_res, corpus_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate if a set of observation channels has an interesting state
|
/// Evaluate if a set of observation channels has an interesting state
|
||||||
@ -456,8 +456,8 @@ where
|
|||||||
.append_hit_feedbacks(testcase.hit_feedbacks_mut())?;
|
.append_hit_feedbacks(testcase.hit_feedbacks_mut())?;
|
||||||
self.feedback_mut()
|
self.feedback_mut()
|
||||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
.append_metadata(state, manager, observers, &mut testcase)?;
|
||||||
let idx = state.corpus_mut().add(testcase)?;
|
let id = state.corpus_mut().add(testcase)?;
|
||||||
self.scheduler_mut().on_add(state, idx)?;
|
self.scheduler_mut().on_add(state, id)?;
|
||||||
|
|
||||||
if send_events && manager.should_send() {
|
if send_events && manager.should_send() {
|
||||||
// TODO set None for fast targets
|
// TODO set None for fast targets
|
||||||
@ -485,7 +485,7 @@ where
|
|||||||
// This testcase is from the other fuzzers.
|
// This testcase is from the other fuzzers.
|
||||||
*state.imported_mut() += 1;
|
*state.imported_mut() += 1;
|
||||||
}
|
}
|
||||||
Ok(Some(idx))
|
Ok(Some(id))
|
||||||
}
|
}
|
||||||
ExecuteInputResult::Solution => {
|
ExecuteInputResult::Solution => {
|
||||||
// Not interesting
|
// Not interesting
|
||||||
@ -583,8 +583,8 @@ where
|
|||||||
let mut testcase = Testcase::with_executions(input.clone(), *state.executions());
|
let mut testcase = Testcase::with_executions(input.clone(), *state.executions());
|
||||||
testcase.set_disabled(true);
|
testcase.set_disabled(true);
|
||||||
// Add the disabled input to the main corpus
|
// Add the disabled input to the main corpus
|
||||||
let idx = state.corpus_mut().add_disabled(testcase)?;
|
let id = state.corpus_mut().add_disabled(testcase)?;
|
||||||
Ok(idx)
|
Ok(id)
|
||||||
}
|
}
|
||||||
/// Adds an input, even if it's not considered `interesting` by any of the executors
|
/// Adds an input, even if it's not considered `interesting` by any of the executors
|
||||||
fn add_input(
|
fn add_input(
|
||||||
@ -620,7 +620,7 @@ where
|
|||||||
.append_hit_feedbacks(testcase.hit_objectives_mut())?;
|
.append_hit_feedbacks(testcase.hit_objectives_mut())?;
|
||||||
self.objective_mut()
|
self.objective_mut()
|
||||||
.append_metadata(state, manager, &*observers, &mut testcase)?;
|
.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();
|
let executions = *state.executions();
|
||||||
manager.fire(
|
manager.fire(
|
||||||
@ -631,7 +631,7 @@ where
|
|||||||
time: current_time(),
|
time: current_time(),
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
return Ok(idx);
|
return Ok(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not a solution
|
// Not a solution
|
||||||
@ -659,8 +659,8 @@ where
|
|||||||
// Add the input to the main corpus
|
// Add the input to the main corpus
|
||||||
self.feedback_mut()
|
self.feedback_mut()
|
||||||
.append_metadata(state, manager, &*observers, &mut testcase)?;
|
.append_metadata(state, manager, &*observers, &mut testcase)?;
|
||||||
let idx = state.corpus_mut().add(testcase)?;
|
let id = state.corpus_mut().add(testcase)?;
|
||||||
self.scheduler_mut().on_add(state, idx)?;
|
self.scheduler_mut().on_add(state, id)?;
|
||||||
|
|
||||||
let observers_buf = if manager.configuration() == EventConfig::AlwaysUnique {
|
let observers_buf = if manager.configuration() == EventConfig::AlwaysUnique {
|
||||||
None
|
None
|
||||||
@ -682,7 +682,7 @@ where
|
|||||||
node_id: None,
|
node_id: None,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
Ok(idx)
|
Ok(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,12 +715,12 @@ where
|
|||||||
state.introspection_monitor_mut().start_timer();
|
state.introspection_monitor_mut().start_timer();
|
||||||
|
|
||||||
// Get the next index from the scheduler
|
// Get the next index from the scheduler
|
||||||
let idx = if let Some(idx) = state.current_corpus_id()? {
|
let id = if let Some(id) = state.current_corpus_id()? {
|
||||||
idx // we are resuming
|
id // we are resuming
|
||||||
} else {
|
} else {
|
||||||
let idx = self.scheduler.next(state)?;
|
let id = self.scheduler.next(state)?;
|
||||||
state.set_corpus_idx(idx)?; // set up for resume
|
state.set_corpus_id(id)?; // set up for resume
|
||||||
idx
|
id
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mark the elapsed time for the scheduler
|
// Mark the elapsed time for the scheduler
|
||||||
@ -746,16 +746,16 @@ where
|
|||||||
state.introspection_monitor_mut().mark_manager_time();
|
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();
|
let scheduled_count = testcase.scheduled_count();
|
||||||
// increase scheduled count, this was fuzz_level in afl
|
// increase scheduled count, this was fuzz_level in afl
|
||||||
testcase.set_scheduled_count(scheduled_count + 1);
|
testcase.set_scheduled_count(scheduled_count + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.clear_corpus_idx()?;
|
state.clear_corpus_id()?;
|
||||||
|
|
||||||
Ok(idx)
|
Ok(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,10 @@ use libafl_bolts::{fs::write_file_atomic, Error};
|
|||||||
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
|
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
|
||||||
use serde::{Deserialize, Serialize};
|
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
|
/// A bytes input is the basic input
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
@ -47,7 +50,7 @@ impl Input for BytesInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a name for this input
|
/// 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();
|
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
|
||||||
hasher.write(self.bytes());
|
hasher.write(self.bytes());
|
||||||
format!("{:016x}", hasher.finish())
|
format!("{:016x}", hasher.finish())
|
||||||
|
@ -19,7 +19,7 @@ use libafl_bolts::{Error, HasLen};
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
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`]
|
/// Trait to encode bytes to an [`EncodedInput`] using the given [`Tokenizer`]
|
||||||
pub trait InputEncoder<T>
|
pub trait InputEncoder<T>
|
||||||
@ -202,7 +202,7 @@ pub struct EncodedInput {
|
|||||||
impl Input for EncodedInput {
|
impl Input for EncodedInput {
|
||||||
/// Generate a name for this input
|
/// Generate a name for this input
|
||||||
#[must_use]
|
#[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();
|
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
|
||||||
for code in &self.codes {
|
for code in &self.codes {
|
||||||
hasher.write(&code.to_le_bytes());
|
hasher.write(&code.to_le_bytes());
|
||||||
|
@ -9,7 +9,7 @@ use ahash::RandomState;
|
|||||||
use libafl_bolts::{Error, HasLen};
|
use libafl_bolts::{Error, HasLen};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::inputs::Input;
|
use crate::{corpus::CorpusId, inputs::Input};
|
||||||
|
|
||||||
/// A terminal for gramatron grammar fuzzing
|
/// A terminal for gramatron grammar fuzzing
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
@ -44,7 +44,7 @@ pub struct GramatronInput {
|
|||||||
impl Input for GramatronInput {
|
impl Input for GramatronInput {
|
||||||
/// Generate a name for this input
|
/// Generate a name for this input
|
||||||
#[must_use]
|
#[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();
|
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
|
||||||
for term in &self.terms {
|
for term in &self.terms {
|
||||||
hasher.write(term.symbol.as_bytes());
|
hasher.write(term.symbol.as_bytes());
|
||||||
|
@ -39,6 +39,8 @@ use libafl_bolts::{ownedref::OwnedSlice, Error, HasLen};
|
|||||||
pub use nautilus::*;
|
pub use nautilus::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::corpus::CorpusId;
|
||||||
|
|
||||||
/// An input for the target
|
/// An input for the target
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
pub trait Input: Clone + Serialize + serde::de::DeserializeOwned + Debug {
|
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
|
/// 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`
|
/// An hook executed if the input is stored as `Testcase`
|
||||||
fn wrapped_as_testcase(&mut self) {}
|
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.
|
/// 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`
|
/// An hook executed if the input is stored as `Testcase`
|
||||||
fn wrapped_as_testcase(&mut self) {}
|
fn wrapped_as_testcase(&mut self) {}
|
||||||
@ -111,7 +113,7 @@ macro_rules! none_input_converter {
|
|||||||
#[derive(Copy, Clone, Serialize, Deserialize, Debug, Hash)]
|
#[derive(Copy, Clone, Serialize, Deserialize, Debug, Hash)]
|
||||||
pub struct NopInput {}
|
pub struct NopInput {}
|
||||||
impl Input for NopInput {
|
impl Input for NopInput {
|
||||||
fn generate_name(&self, _idx: usize) -> String {
|
fn generate_name(&self, _id: Option<CorpusId>) -> String {
|
||||||
"nop-input".to_string()
|
"nop-input".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ use alloc::{
|
|||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use serde::{Deserialize, Serialize};
|
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
|
/// An input composed of multiple parts. Use in situations where subcomponents are not necessarily
|
||||||
/// related, or represent distinct parts of the input.
|
/// related, or represent distinct parts of the input.
|
||||||
@ -153,11 +153,11 @@ impl<I> Input for MultipartInput<I>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn generate_name(&self, idx: usize) -> String {
|
fn generate_name(&self, id: Option<CorpusId>) -> String {
|
||||||
self.names
|
self.names
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.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}"))
|
.map(|(name, generated)| format!("{name}-{generated}"))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(",")
|
.join(",")
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
//! Input for the [`Nautilus`](https://github.com/RUB-SysSec/nautilus) grammar fuzzer methods
|
//! 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 alloc::{rc::Rc, string::String, vec::Vec};
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
@ -17,6 +14,7 @@ use crate::{
|
|||||||
rule::RuleIdOrCustom,
|
rule::RuleIdOrCustom,
|
||||||
tree::{Tree, TreeLike},
|
tree::{Tree, TreeLike},
|
||||||
},
|
},
|
||||||
|
corpus::CorpusId,
|
||||||
generators::nautilus::NautilusContext,
|
generators::nautilus::NautilusContext,
|
||||||
inputs::{BytesInput, Input, InputConverter},
|
inputs::{BytesInput, Input, InputConverter},
|
||||||
Error,
|
Error,
|
||||||
@ -32,13 +30,18 @@ pub struct NautilusInput {
|
|||||||
impl Input for NautilusInput {
|
impl Input for NautilusInput {
|
||||||
/// Generate a name for this input
|
/// Generate a name for this input
|
||||||
#[must_use]
|
#[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);
|
/*let mut hasher = AHasher::new_with_keys(0, 0);
|
||||||
for term in &self.terms {
|
for term in &self.terms {
|
||||||
hasher.write(term.symbol.as_bytes());
|
hasher.write(term.symbol.as_bytes());
|
||||||
}
|
}
|
||||||
format!("{:016x}", hasher.finish())*/
|
format!("{:016x}", hasher.finish())*/
|
||||||
format!("id:{idx}")
|
|
||||||
|
if let Some(id) = id {
|
||||||
|
format!("id_{}", id.0)
|
||||||
|
} else {
|
||||||
|
"id_unknown".into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,16 +292,16 @@ where
|
|||||||
fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> {
|
fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> {
|
||||||
let size = input.codes().len();
|
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
|
// 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 let Some(cur) = state.corpus().current() {
|
||||||
if idx == *cur {
|
if id == *cur {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let other_size = {
|
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()
|
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.
|
// no need to `load_input` again - we did that above already.
|
||||||
let other = other_testcase.input().as_ref().unwrap();
|
let other = other_testcase.input().as_ref().unwrap();
|
||||||
|
|
||||||
@ -365,17 +365,17 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
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
|
// 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 let Some(cur) = state.corpus().current() {
|
||||||
if idx == *cur {
|
if id == *cur {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let other_size = {
|
let other_size = {
|
||||||
// new scope to make the borrow checker happy
|
// 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()
|
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 len = state.rand_mut().below(min(other_size - from, size));
|
||||||
let to = state.rand_mut().below(size - len);
|
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.
|
// no need to load the input again, it'll already be present at this point.
|
||||||
let other = other_testcase.input().as_ref().unwrap();
|
let other = other_testcase.input().as_ref().unwrap();
|
||||||
|
|
||||||
|
@ -117,13 +117,13 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
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 insert_at = state.rand_mut().below(input.terminals().len());
|
||||||
|
|
||||||
let rand_num = state.rand_mut().next();
|
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>() {
|
if !other_testcase.has_metadata::<GramatronIdxMapMetadata>() {
|
||||||
let meta = GramatronIdxMapMetadata::new(other_testcase.load_input(state.corpus())?);
|
let meta = GramatronIdxMapMetadata::new(other_testcase.load_input(state.corpus())?);
|
||||||
|
@ -30,14 +30,14 @@ fn extend_with_random_generalized<S>(
|
|||||||
where
|
where
|
||||||
S: HasMetadata + HasRand + HasCorpus,
|
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(CHOOSE_SUBINPUT_PROB) {
|
||||||
if state.rand_mut().coinflip(0.5) {
|
if state.rand_mut().coinflip(0.5) {
|
||||||
let rand1 = state.rand_mut().next();
|
let rand1 = state.rand_mut().next();
|
||||||
let rand2 = 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
|
if let Some(other) = other_testcase
|
||||||
.metadata_map()
|
.metadata_map()
|
||||||
.get::<GeneralizedInputMetadata>()
|
.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
|
if let Some(other) = other_testcase
|
||||||
.metadata_map()
|
.metadata_map()
|
||||||
.get::<GeneralizedInputMetadata>()
|
.get::<GeneralizedInputMetadata>()
|
||||||
|
@ -94,13 +94,9 @@ pub trait Mutator<I, S>: Named {
|
|||||||
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error>;
|
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error>;
|
||||||
|
|
||||||
/// Post-process given the outcome of the execution
|
/// 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]
|
#[inline]
|
||||||
fn post_exec(
|
fn post_exec(&mut self, _state: &mut S, _new_corpus_id: Option<CorpusId>) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_state: &mut S,
|
|
||||||
_new_corpus_idx: Option<CorpusId>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,12 +114,12 @@ pub trait MultiMutator<I, S>: Named {
|
|||||||
) -> Result<Vec<I>, Error>;
|
) -> Result<Vec<I>, Error>;
|
||||||
|
|
||||||
/// Post-process given the outcome of the execution
|
/// 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]
|
#[inline]
|
||||||
fn multi_post_exec(
|
fn multi_post_exec(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
_new_corpus_idx: Option<CorpusId>,
|
_new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Ok(())
|
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>;
|
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`.
|
/// 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(
|
fn post_exec_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
new_corpus_idx: Option<CorpusId>,
|
new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Gets the [`Mutator`] at the given index and runs the `mutate` function on it.
|
/// 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>;
|
) -> Result<MutationResult, Error>;
|
||||||
|
|
||||||
/// Gets the [`Mutator`] at the given index and runs the `post_exec` function on it.
|
/// 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(
|
fn get_and_post_exec(
|
||||||
&mut self,
|
&mut self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
|
||||||
corpus_idx: Option<CorpusId>,
|
corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Gets all names of the wrapped [`Mutator`]`s`, reversed.
|
/// Gets all names of the wrapped [`Mutator`]`s`, reversed.
|
||||||
@ -177,7 +173,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
|
|||||||
fn post_exec_all(
|
fn post_exec_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
_new_corpus_idx: Option<CorpusId>,
|
_new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -197,7 +193,7 @@ impl<I, S> MutatorsTuple<I, S> for () {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_index: usize,
|
_index: usize,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
_new_corpus_idx: Option<CorpusId>,
|
_new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -230,10 +226,10 @@ where
|
|||||||
fn post_exec_all(
|
fn post_exec_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
new_corpus_idx: Option<CorpusId>,
|
new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.0.post_exec(state, new_corpus_idx)?;
|
self.0.post_exec(state, new_corpus_id)?;
|
||||||
self.1.post_exec_all(state, new_corpus_idx)
|
self.1.post_exec_all(state, new_corpus_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_and_mutate(
|
fn get_and_mutate(
|
||||||
@ -253,12 +249,12 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
new_corpus_idx: Option<CorpusId>,
|
new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
self.0.post_exec(state, new_corpus_idx)
|
self.0.post_exec(state, new_corpus_id)
|
||||||
} else {
|
} 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(
|
fn post_exec_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
new_corpus_idx: Option<CorpusId>,
|
new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.0.post_exec_all(state, new_corpus_idx)
|
self.0.post_exec_all(state, new_corpus_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_and_mutate(
|
fn get_and_mutate(
|
||||||
@ -323,9 +319,9 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
new_corpus_idx: Option<CorpusId>,
|
new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> 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> {
|
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(
|
fn post_exec_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
new_corpus_idx: Option<CorpusId>,
|
new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
for mutator in self.iter_mut() {
|
for mutator in self.iter_mut() {
|
||||||
mutator.post_exec(state, new_corpus_idx)?;
|
mutator.post_exec(state, new_corpus_id)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -385,12 +381,12 @@ impl<I, S> MutatorsTuple<I, S> for Vec<Box<dyn Mutator<I, S>>> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
new_corpus_idx: Option<CorpusId>,
|
new_corpus_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mutator = self
|
let mutator = self
|
||||||
.get_mut(index)
|
.get_mut(index)
|
||||||
.ok_or_else(|| Error::key_not_found("Mutator with id {index:?} not found."))?;
|
.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> {
|
fn names_reversed(&self) -> Vec<&str> {
|
||||||
|
@ -399,7 +399,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_precision_loss)]
|
#[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 before = self.finds_before;
|
||||||
let after = state.corpus().count() + state.solutions().count();
|
let after = state.corpus().count() + state.solutions().count();
|
||||||
|
|
||||||
|
@ -50,8 +50,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
||||||
M::post_exec(self, state, new_corpus_idx)
|
M::post_exec(self, state, new_corpus_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,9 +129,9 @@ where
|
|||||||
let part_choice = state.rand_mut().next() as usize;
|
let part_choice = state.rand_mut().next() as usize;
|
||||||
|
|
||||||
// We special-case crossover with self
|
// 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 let Some(cur) = state.corpus().current() {
|
||||||
if idx == *cur {
|
if id == *cur {
|
||||||
let choice = name_choice % input.names().len();
|
let choice = name_choice % input.names().len();
|
||||||
let name = input.names()[choice].clone();
|
let name = input.names()[choice].clone();
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ where
|
|||||||
.parts_by_name(&name)
|
.parts_by_name(&name)
|
||||||
.filter(|&(p, _)| p != choice)
|
.filter(|&(p, _)| p != choice)
|
||||||
.nth(part_choice % parts)
|
.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 {
|
if let Some((part_idx, size)) = maybe_size {
|
||||||
let target = state.rand_mut().below(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 other = other_testcase.load_input(state.corpus())?;
|
||||||
|
|
||||||
let choice = name_choice % other.names().len();
|
let choice = name_choice % other.names().len();
|
||||||
@ -198,7 +198,7 @@ where
|
|||||||
let target = state.rand_mut().below(size);
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, other_size, min(other_size, size - target));
|
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.
|
// No need to load the input again, it'll still be cached.
|
||||||
let other = other_testcase.input().as_ref().unwrap();
|
let other = other_testcase.input().as_ref().unwrap();
|
||||||
|
|
||||||
@ -233,9 +233,9 @@ where
|
|||||||
let part_choice = state.rand_mut().next() as usize;
|
let part_choice = state.rand_mut().next() as usize;
|
||||||
|
|
||||||
// We special-case crossover with self
|
// 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 let Some(cur) = state.corpus().current() {
|
||||||
if idx == *cur {
|
if id == *cur {
|
||||||
let choice = name_choice % input.names().len();
|
let choice = name_choice % input.names().len();
|
||||||
let name = input.names()[choice].clone();
|
let name = input.names()[choice].clone();
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ where
|
|||||||
.parts_by_name(&name)
|
.parts_by_name(&name)
|
||||||
.filter(|&(p, _)| p != choice)
|
.filter(|&(p, _)| p != choice)
|
||||||
.nth(part_choice % parts)
|
.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 {
|
if let Some((part_idx, size)) = maybe_size {
|
||||||
let target = state.rand_mut().below(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 other = other_testcase.load_input(state.corpus())?;
|
||||||
|
|
||||||
let choice = name_choice % other.names().len();
|
let choice = name_choice % other.names().len();
|
||||||
@ -302,7 +302,7 @@ where
|
|||||||
let target = state.rand_mut().below(size);
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, other_size, min(other_size, size - target));
|
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.
|
// No need to load the input again, it'll still be cached.
|
||||||
let other = other_testcase.input().as_ref().unwrap();
|
let other = other_testcase.input().as_ref().unwrap();
|
||||||
|
|
||||||
|
@ -1073,17 +1073,16 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
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
|
// 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 let Some(cur) = state.corpus().current() {
|
||||||
if idx == *cur {
|
if id == *cur {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let other_size = {
|
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()
|
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 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 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.
|
// No need to load the input again, it'll still be cached.
|
||||||
let other = other_testcase.input().as_ref().unwrap();
|
let other = other_testcase.input().as_ref().unwrap();
|
||||||
|
|
||||||
@ -1157,16 +1156,16 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
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
|
// 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 let Some(cur) = state.corpus().current() {
|
||||||
if idx == *cur {
|
if id == *cur {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let other_size = {
|
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()
|
testcase.load_input(state.corpus())?.bytes().len()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1177,7 +1176,7 @@ where
|
|||||||
let target = state.rand_mut().below(size);
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, other_size, min(other_size, size - target));
|
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.
|
// No need to load the input again, it'll still be cached.
|
||||||
let other = other_testcase.input().as_ref().unwrap();
|
let other = other_testcase.input().as_ref().unwrap();
|
||||||
|
|
||||||
@ -1230,16 +1229,16 @@ where
|
|||||||
{
|
{
|
||||||
#[allow(clippy::cast_sign_loss)]
|
#[allow(clippy::cast_sign_loss)]
|
||||||
fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> {
|
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
|
// 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 let Some(cur) = state.corpus().current() {
|
||||||
if idx == *cur {
|
if id == *cur {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (first_diff, last_diff) = {
|
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 other = other_testcase.load_input(state.corpus())?;
|
||||||
|
|
||||||
let (f, l) = locate_diffs(input.bytes(), other.bytes());
|
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 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.
|
// Input will already be loaded.
|
||||||
let other = other_testcase.input().as_ref().unwrap();
|
let other = other_testcase.input().as_ref().unwrap();
|
||||||
|
|
||||||
|
@ -388,9 +388,9 @@ where
|
|||||||
self.scheduled_mutate(state, input)
|
self.scheduled_mutate(state, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_exec(&mut self, state: &mut S, corpus_idx: Option<CorpusId>) -> Result<(), Error> {
|
fn post_exec(&mut self, state: &mut S, corpus_id: Option<CorpusId>) -> Result<(), Error> {
|
||||||
if let Some(idx) = corpus_idx {
|
if let Some(id) = corpus_id {
|
||||||
let mut testcase = (*state.corpus_mut().get(idx)?).borrow_mut();
|
let mut testcase = (*state.corpus_mut().get(id)?).borrow_mut();
|
||||||
let mut log = Vec::<Cow<'static, str>>::new();
|
let mut log = Vec::<Cow<'static, str>>::new();
|
||||||
while let Some(idx) = self.mutation_log.pop() {
|
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
|
let name = self.scheduled.mutations().name(idx.0).unwrap().clone(); // TODO maybe return an Error on None
|
||||||
|
@ -618,9 +618,9 @@ pub struct AFLppRedQueen {
|
|||||||
enable_transform: bool,
|
enable_transform: bool,
|
||||||
enable_arith: bool,
|
enable_arith: bool,
|
||||||
text_type: TextType,
|
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`
|
/// - and, hence, need to recalculate `text_type`
|
||||||
last_corpus_idx: Option<CorpusId>,
|
last_corpus_id: Option<CorpusId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AFLppRedQueen {
|
impl AFLppRedQueen {
|
||||||
@ -1135,10 +1135,10 @@ where
|
|||||||
// println!("orig: {:#?} new: {:#?}", orig_cmpvals, new_cmpvals);
|
// println!("orig: {:#?} new: {:#?}", orig_cmpvals, new_cmpvals);
|
||||||
|
|
||||||
// Compute when mutating it for the 1st time.
|
// 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()."))?;
|
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_idx.is_none() || self.last_corpus_idx.unwrap() != current_corpus_id {
|
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.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}");
|
// println!("approximate size: {cmp_len} x {input_len}");
|
||||||
for cmp_idx in 0..cmp_len {
|
for cmp_idx in 0..cmp_len {
|
||||||
@ -1690,7 +1690,7 @@ impl AFLppRedQueen {
|
|||||||
enable_transform: false,
|
enable_transform: false,
|
||||||
enable_arith: false,
|
enable_arith: false,
|
||||||
text_type: TextType::None,
|
text_type: TextType::None,
|
||||||
last_corpus_idx: None,
|
last_corpus_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1701,7 +1701,7 @@ impl AFLppRedQueen {
|
|||||||
enable_transform: transform,
|
enable_transform: transform,
|
||||||
enable_arith: arith,
|
enable_arith: arith,
|
||||||
text_type: TextType::None,
|
text_type: TextType::None,
|
||||||
last_corpus_idx: None,
|
last_corpus_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,9 +51,9 @@ impl<S> MutatedTransformPost<S> for UnicodeIdentificationMetadata
|
|||||||
where
|
where
|
||||||
S: HasTestcase,
|
S: HasTestcase,
|
||||||
{
|
{
|
||||||
fn post_exec(self, state: &mut S, corpus_idx: Option<CorpusId>) -> Result<(), Error> {
|
fn post_exec(self, state: &mut S, corpus_id: Option<CorpusId>) -> Result<(), Error> {
|
||||||
if let Some(corpus_idx) = corpus_idx {
|
if let Some(corpus_id) = corpus_id {
|
||||||
let mut tc = state.testcase_mut(corpus_idx)?;
|
let mut tc = state.testcase_mut(corpus_id)?;
|
||||||
tc.add_metadata(self);
|
tc.add_metadata(self);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -136,9 +136,9 @@ where
|
|||||||
<Self::State as UsesInput>::Input: HasLen,
|
<Self::State as UsesInput>::Input: HasLen,
|
||||||
O: CanTrack,
|
O: CanTrack,
|
||||||
{
|
{
|
||||||
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> {
|
||||||
self.update_accounting_score(state, idx)?;
|
self.update_accounting_score(state, id)?;
|
||||||
self.inner.on_add(state, idx)
|
self.inner.on_add(state, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_evaluation<OT>(
|
fn on_evaluation<OT>(
|
||||||
@ -163,29 +163,29 @@ where
|
|||||||
} else {
|
} else {
|
||||||
self.inner.cull(state)?;
|
self.inner.cull(state)?;
|
||||||
}
|
}
|
||||||
let mut idx = self.inner.base_mut().next(state)?;
|
let mut id = self.inner.base_mut().next(state)?;
|
||||||
while {
|
while {
|
||||||
let has = !state
|
let has = !state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow()
|
.borrow()
|
||||||
.has_metadata::<IsFavoredMetadata>();
|
.has_metadata::<IsFavoredMetadata>();
|
||||||
has
|
has
|
||||||
} && state.rand_mut().coinflip(self.skip_non_favored_prob)
|
} && 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
|
// 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`
|
/// Set current fuzzed corpus id and `scheduled_count`
|
||||||
fn set_current_scheduled(
|
fn set_current_scheduled(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
_next_idx: Option<CorpusId>,
|
_next_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// We do nothing here, the inner scheduler will take care of it
|
// We do nothing here, the inner scheduler will take care of it
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -205,7 +205,7 @@ where
|
|||||||
pub fn update_accounting_score(
|
pub fn update_accounting_score(
|
||||||
&self,
|
&self,
|
||||||
state: &mut CS::State,
|
state: &mut CS::State,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut indexes = vec![];
|
let mut indexes = vec![];
|
||||||
let mut new_favoreds = vec![];
|
let mut new_favoreds = vec![];
|
||||||
@ -220,7 +220,7 @@ where
|
|||||||
{
|
{
|
||||||
let top_acc = state.metadata_map().get::<TopAccountingMetadata>().unwrap();
|
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] {
|
if top_acc.max_accounting[idx] > self.accounting_map[idx] {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -229,11 +229,11 @@ where
|
|||||||
equal_score = true;
|
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 must_remove = {
|
||||||
let old_meta = old.metadata_map_mut().get_mut::<AccountingIndexesMetadata>().ok_or_else(|| {
|
let old_meta = old.metadata_map_mut().get_mut::<AccountingIndexesMetadata>().ok_or_else(|| {
|
||||||
Error::key_not_found(format!(
|
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;
|
*old_meta.refcnt_mut() -= 1;
|
||||||
@ -268,7 +268,7 @@ where
|
|||||||
|
|
||||||
state
|
state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.metadata_map_mut()
|
.metadata_map_mut()
|
||||||
.insert(AccountingIndexesMetadata::with_tcref(
|
.insert(AccountingIndexesMetadata::with_tcref(
|
||||||
@ -283,7 +283,7 @@ where
|
|||||||
top_acc.changed = true;
|
top_acc.changed = true;
|
||||||
|
|
||||||
for elem in new_favoreds {
|
for elem in new_favoreds {
|
||||||
top_acc.map.insert(elem, idx);
|
top_acc.map.insert(elem, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -296,8 +296,8 @@ where
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
for (_key, idx) in &top_rated.map {
|
for (_key, id) in &top_rated.map {
|
||||||
let mut entry = state.corpus().get(*idx)?.borrow_mut();
|
let mut entry = state.corpus().get(*id)?.borrow_mut();
|
||||||
if entry.scheduled_count() > 0 {
|
if entry.scheduled_count() > 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -93,30 +93,30 @@ where
|
|||||||
<Self as UsesState>::State: HasCorpus + HasMetadata + HasRand,
|
<Self as UsesState>::State: HasCorpus + HasMetadata + HasRand,
|
||||||
O: CanTrack,
|
O: CanTrack,
|
||||||
{
|
{
|
||||||
/// Replaces the testcase at the given idx
|
/// Replaces the testcase at the given id
|
||||||
fn on_replace(
|
fn on_replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut <Self as UsesState>::State,
|
state: &mut <Self as UsesState>::State,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
testcase: &Testcase<<<Self as UsesState>::State as UsesInput>::Input>,
|
testcase: &Testcase<<<Self as UsesState>::State as UsesInput>::Input>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.base.on_replace(state, idx, testcase)?;
|
self.base.on_replace(state, id, testcase)?;
|
||||||
self.update_score(state, idx)
|
self.update_score(state, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes an entry from the corpus
|
/// Removes an entry from the corpus
|
||||||
fn on_remove(
|
fn on_remove(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut <Self as UsesState>::State,
|
state: &mut <Self as UsesState>::State,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
testcase: &Option<Testcase<<<Self as UsesState>::State as UsesInput>::Input>>,
|
testcase: &Option<Testcase<<<Self as UsesState>::State as UsesInput>::Input>>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.base.on_remove(state, idx, testcase)?;
|
self.base.on_remove(state, id, testcase)?;
|
||||||
let mut entries =
|
let mut entries =
|
||||||
if let Some(meta) = state.metadata_map_mut().get_mut::<TopRatedsMetadata>() {
|
if let Some(meta) = state.metadata_map_mut().get_mut::<TopRatedsMetadata>() {
|
||||||
let entries = meta
|
let entries = meta
|
||||||
.map
|
.map
|
||||||
.extract_if(|_, other_idx| *other_idx == idx)
|
.extract_if(|_, other_id| *other_id == id)
|
||||||
.map(|(entry, _)| entry)
|
.map(|(entry, _)| entry)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
entries
|
entries
|
||||||
@ -125,8 +125,8 @@ where
|
|||||||
};
|
};
|
||||||
entries.sort_unstable(); // this should already be sorted, but just in case
|
entries.sort_unstable(); // this should already be sorted, but just in case
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
for i in state.corpus().ids() {
|
for current_id in state.corpus().ids() {
|
||||||
let mut old = state.corpus().get(i)?.borrow_mut();
|
let mut old = state.corpus().get(current_id)?.borrow_mut();
|
||||||
let factor = F::compute(state, &mut *old)?;
|
let factor = F::compute(state, &mut *old)?;
|
||||||
if let Some(old_map) = old.metadata_map_mut().get_mut::<M>() {
|
if let Some(old_map) = old.metadata_map_mut().get_mut::<M>() {
|
||||||
let mut e_iter = entries.iter();
|
let mut e_iter = entries.iter();
|
||||||
@ -144,13 +144,13 @@ where
|
|||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
// if we found a better factor, prefer it
|
// if we found a better factor, prefer it
|
||||||
map.entry(*e)
|
map.entry(*e)
|
||||||
.and_modify(|(f, idx)| {
|
.and_modify(|(f, id)| {
|
||||||
if *f > factor {
|
if *f > factor {
|
||||||
*f = factor;
|
*f = factor;
|
||||||
*idx = i;
|
*id = current_id;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.or_insert((factor, i));
|
.or_insert((factor, current_id));
|
||||||
entry = e_iter.next();
|
entry = e_iter.next();
|
||||||
map_entry = map_iter.next();
|
map_entry = map_iter.next();
|
||||||
}
|
}
|
||||||
@ -174,16 +174,16 @@ where
|
|||||||
};
|
};
|
||||||
meta.map.reserve(reserve);
|
meta.map.reserve(reserve);
|
||||||
|
|
||||||
for (entry, (_, new_idx)) in map_iter {
|
for (entry, (_, new_id)) in map_iter {
|
||||||
let mut new = state.corpus().get(*new_idx)?.borrow_mut();
|
let mut new = state.corpus().get(*new_id)?.borrow_mut();
|
||||||
let new_meta = new.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
|
let new_meta = new.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
|
||||||
Error::key_not_found(format!(
|
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>()
|
type_name::<M>()
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
*new_meta.refcnt_mut() += 1;
|
*new_meta.refcnt_mut() += 1;
|
||||||
meta.map.insert(*entry, *new_idx);
|
meta.map.insert(*entry, *new_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put back the metadata
|
// Put back the metadata
|
||||||
@ -202,9 +202,9 @@ where
|
|||||||
O: CanTrack,
|
O: CanTrack,
|
||||||
{
|
{
|
||||||
/// Called when a [`Testcase`] is added to the corpus
|
/// 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> {
|
||||||
self.base.on_add(state, idx)?;
|
self.base.on_add(state, id)?;
|
||||||
self.update_score(state, idx)
|
self.update_score(state, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An input has been evaluated
|
/// An input has been evaluated
|
||||||
@ -223,26 +223,26 @@ where
|
|||||||
/// Gets the next entry
|
/// Gets the next entry
|
||||||
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
|
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
|
||||||
self.cull(state)?;
|
self.cull(state)?;
|
||||||
let mut idx = self.base.next(state)?;
|
let mut id = self.base.next(state)?;
|
||||||
while {
|
while {
|
||||||
let has = !state
|
let has = !state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow()
|
.borrow()
|
||||||
.has_metadata::<IsFavoredMetadata>();
|
.has_metadata::<IsFavoredMetadata>();
|
||||||
has
|
has
|
||||||
} && state.rand_mut().coinflip(self.skip_non_favored_prob)
|
} && 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`
|
/// Set current fuzzed corpus id and `scheduled_count`
|
||||||
fn set_current_scheduled(
|
fn set_current_scheduled(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
_next_idx: Option<CorpusId>,
|
_next_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// We do nothing here, the inner scheduler will take care of it
|
// We do nothing here, the inner scheduler will take care of it
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -263,7 +263,7 @@ where
|
|||||||
pub fn update_score(
|
pub fn update_score(
|
||||||
&self,
|
&self,
|
||||||
state: &mut <Self as UsesState>::State,
|
state: &mut <Self as UsesState>::State,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Create a new top rated meta if not existing
|
// Create a new top rated meta if not existing
|
||||||
if state.metadata_map().get::<TopRatedsMetadata>().is_none() {
|
if state.metadata_map().get::<TopRatedsMetadata>().is_none() {
|
||||||
@ -272,21 +272,21 @@ where
|
|||||||
|
|
||||||
let mut new_favoreds = vec![];
|
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 factor = F::compute(state, &mut *entry)?;
|
||||||
let meta = entry.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
|
let meta = entry.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
|
||||||
Error::key_not_found(format!(
|
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();
|
let top_rateds = state.metadata_map().get::<TopRatedsMetadata>().unwrap();
|
||||||
for elem in meta.as_iter() {
|
for elem in meta.as_iter() {
|
||||||
if let Some(old_idx) = top_rateds.map.get(&*elem) {
|
if let Some(old_id) = top_rateds.map.get(&*elem) {
|
||||||
if *old_idx == idx {
|
if *old_id == id {
|
||||||
new_favoreds.push(*elem); // always retain current; we'll drop it later otherwise
|
new_favoreds.push(*elem); // always retain current; we'll drop it later otherwise
|
||||||
continue;
|
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)? {
|
if factor > F::compute(state, &mut *old)? {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -294,7 +294,7 @@ where
|
|||||||
let must_remove = {
|
let must_remove = {
|
||||||
let old_meta = old.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
|
let old_meta = old.metadata_map_mut().get_mut::<M>().ok_or_else(|| {
|
||||||
Error::key_not_found(format!(
|
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>()
|
type_name::<M>()
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -317,7 +317,7 @@ where
|
|||||||
drop(
|
drop(
|
||||||
state
|
state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.metadata_map_mut()
|
.metadata_map_mut()
|
||||||
.remove::<M>(),
|
.remove::<M>(),
|
||||||
@ -331,7 +331,7 @@ where
|
|||||||
.get_mut::<TopRatedsMetadata>()
|
.get_mut::<TopRatedsMetadata>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map
|
.map
|
||||||
.insert(elem, idx);
|
.insert(elem, id);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -345,12 +345,12 @@ where
|
|||||||
|
|
||||||
let mut acc = HashSet::new();
|
let mut acc = HashSet::new();
|
||||||
|
|
||||||
for (key, idx) in &top_rated.map {
|
for (key, id) in &top_rated.map {
|
||||||
if !acc.contains(key) {
|
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(|| {
|
let meta = entry.metadata_map().get::<M>().ok_or_else(|| {
|
||||||
Error::key_not_found(format!(
|
Error::key_not_found(format!(
|
||||||
"{} needed for MinimizerScheduler not found in testcase #{idx}",
|
"{} needed for MinimizerScheduler not found in testcase #{id}",
|
||||||
type_name::<M>()
|
type_name::<M>()
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
@ -51,7 +51,7 @@ where
|
|||||||
fn on_remove(
|
fn on_remove(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
_idx: CorpusId,
|
_id: CorpusId,
|
||||||
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -61,7 +61,7 @@ where
|
|||||||
fn on_replace(
|
fn on_replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
_idx: CorpusId,
|
_id: CorpusId,
|
||||||
_prev: &Testcase<<Self::State as UsesInput>::Input>,
|
_prev: &Testcase<<Self::State as UsesInput>::Input>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -85,10 +85,10 @@ where
|
|||||||
fn map_observer_handle(&self) -> &Handle<C>;
|
fn map_observer_handle(&self) -> &Handle<C>;
|
||||||
|
|
||||||
/// Called when a [`Testcase`] is added to the corpus
|
/// Called when a [`Testcase`] is added to the corpus
|
||||||
fn on_add_metadata(&self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
fn on_add_metadata(&self, state: &mut Self::State, id: CorpusId) -> Result<(), Error> {
|
||||||
let current_idx = *state.corpus().current();
|
let current_id = *state.corpus().current();
|
||||||
|
|
||||||
let mut depth = match current_idx {
|
let mut depth = match current_id {
|
||||||
Some(parent_idx) => state
|
Some(parent_idx) => state
|
||||||
.testcase(parent_idx)?
|
.testcase(parent_idx)?
|
||||||
.metadata::<SchedulerTestcaseMetadata>()?
|
.metadata::<SchedulerTestcaseMetadata>()?
|
||||||
@ -101,12 +101,12 @@ where
|
|||||||
|
|
||||||
// Attach a `SchedulerTestcaseMetadata` to the queue entry.
|
// Attach a `SchedulerTestcaseMetadata` to the queue entry.
|
||||||
depth += 1;
|
depth += 1;
|
||||||
let mut testcase = state.testcase_mut(idx)?;
|
let mut testcase = state.testcase_mut(id)?;
|
||||||
testcase.add_metadata(SchedulerTestcaseMetadata::with_n_fuzz_entry(
|
testcase.add_metadata(SchedulerTestcaseMetadata::with_n_fuzz_entry(
|
||||||
depth,
|
depth,
|
||||||
self.last_hash(),
|
self.last_hash(),
|
||||||
));
|
));
|
||||||
testcase.set_parent_id_optional(current_idx);
|
testcase.set_parent_id_optional(current_id);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,12 +142,12 @@ where
|
|||||||
fn on_next_metadata(
|
fn on_next_metadata(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
_next_idx: Option<CorpusId>,
|
_next_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let current_idx = *state.corpus().current();
|
let current_id = *state.corpus().current();
|
||||||
|
|
||||||
if let Some(idx) = current_idx {
|
if let Some(id) = current_id {
|
||||||
let mut testcase = state.testcase_mut(idx)?;
|
let mut testcase = state.testcase_mut(id)?;
|
||||||
let tcmeta = testcase.metadata_mut::<SchedulerTestcaseMetadata>()?;
|
let tcmeta = testcase.metadata_mut::<SchedulerTestcaseMetadata>()?;
|
||||||
|
|
||||||
if tcmeta.handicap() >= 4 {
|
if tcmeta.handicap() >= 4 {
|
||||||
@ -168,7 +168,7 @@ where
|
|||||||
Self::State: HasCorpus,
|
Self::State: HasCorpus,
|
||||||
{
|
{
|
||||||
/// Called when a [`Testcase`] is added to the corpus
|
/// 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
|
// Add parent_id here if it has no inner
|
||||||
|
|
||||||
/// An input has been evaluated
|
/// An input has been evaluated
|
||||||
@ -192,9 +192,9 @@ where
|
|||||||
fn set_current_scheduled(
|
fn set_current_scheduled(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
next_idx: Option<CorpusId>,
|
next_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
*state.corpus_mut().current_mut() = next_idx;
|
*state.corpus_mut().current_mut() = next_id;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,14 +216,14 @@ impl<S> Scheduler for RandScheduler<S>
|
|||||||
where
|
where
|
||||||
S: HasCorpus + HasRand + HasTestcase + State,
|
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
|
// Set parent id
|
||||||
let current_idx = *state.corpus().current();
|
let current_id = *state.corpus().current();
|
||||||
state
|
state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_parent_id_optional(current_idx);
|
.set_parent_id_optional(current_id);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ where
|
|||||||
fn on_remove(
|
fn on_remove(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
_idx: CorpusId,
|
_id: CorpusId,
|
||||||
_prev: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
_prev: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -210,7 +210,7 @@ where
|
|||||||
fn on_replace(
|
fn on_replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
_idx: CorpusId,
|
_id: CorpusId,
|
||||||
_prev: &Testcase<<Self::State as UsesInput>::Input>,
|
_prev: &Testcase<<Self::State as UsesInput>::Input>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -243,8 +243,8 @@ where
|
|||||||
C: AsRef<O>,
|
C: AsRef<O>,
|
||||||
{
|
{
|
||||||
/// Called when a [`Testcase`] is added to the corpus
|
/// 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> {
|
||||||
self.on_add_metadata(state, idx)
|
self.on_add_metadata(state, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_evaluation<OT>(
|
fn on_evaluation<OT>(
|
||||||
@ -287,11 +287,11 @@ where
|
|||||||
fn set_current_scheduled(
|
fn set_current_scheduled(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
next_idx: Option<CorpusId>,
|
next_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,8 +73,8 @@ where
|
|||||||
/// Calculate the score and store in `ProbabilityMetadata`
|
/// Calculate the score and store in `ProbabilityMetadata`
|
||||||
#[allow(clippy::cast_precision_loss)]
|
#[allow(clippy::cast_precision_loss)]
|
||||||
#[allow(clippy::unused_self)]
|
#[allow(clippy::unused_self)]
|
||||||
pub fn store_probability(&self, state: &mut S, idx: CorpusId) -> Result<(), Error> {
|
pub fn store_probability(&self, state: &mut S, id: CorpusId) -> Result<(), Error> {
|
||||||
let prob = F::compute(state, &mut *state.corpus().get(idx)?.borrow_mut())?;
|
let prob = F::compute(state, &mut *state.corpus().get(id)?.borrow_mut())?;
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
prob >= 0.0 && prob.is_finite(),
|
prob >= 0.0 && prob.is_finite(),
|
||||||
"scheduler probability is {prob}; to work correctly it must be >= 0.0 and finite"
|
"scheduler probability is {prob}; to work correctly it must be >= 0.0 and finite"
|
||||||
@ -83,7 +83,7 @@ where
|
|||||||
.metadata_map_mut()
|
.metadata_map_mut()
|
||||||
.get_mut::<ProbabilityMetadata>()
|
.get_mut::<ProbabilityMetadata>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
meta.map.insert(idx, prob);
|
meta.map.insert(id, prob);
|
||||||
meta.total_probability += prob;
|
meta.total_probability += prob;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -97,14 +97,14 @@ where
|
|||||||
fn on_remove(
|
fn on_remove(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let meta = state
|
let meta = state
|
||||||
.metadata_map_mut()
|
.metadata_map_mut()
|
||||||
.get_mut::<ProbabilityMetadata>()
|
.get_mut::<ProbabilityMetadata>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if let Some(prob) = meta.map.remove(&idx) {
|
if let Some(prob) = meta.map.remove(&id) {
|
||||||
meta.total_probability -= prob;
|
meta.total_probability -= prob;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -113,18 +113,18 @@ where
|
|||||||
fn on_replace(
|
fn on_replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
_prev: &Testcase<<Self::State as UsesInput>::Input>,
|
_prev: &Testcase<<Self::State as UsesInput>::Input>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let meta = state
|
let meta = state
|
||||||
.metadata_map_mut()
|
.metadata_map_mut()
|
||||||
.get_mut::<ProbabilityMetadata>()
|
.get_mut::<ProbabilityMetadata>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if let Some(prob) = meta.map.remove(&idx) {
|
if let Some(prob) = meta.map.remove(&id) {
|
||||||
meta.total_probability -= prob;
|
meta.total_probability -= prob;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.store_probability(state, idx)
|
self.store_probability(state, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,18 +140,18 @@ where
|
|||||||
F: TestcaseScore<S>,
|
F: TestcaseScore<S>,
|
||||||
S: HasCorpus + HasMetadata + HasRand + HasTestcase + State,
|
S: HasCorpus + HasMetadata + 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> {
|
||||||
let current_idx = *state.corpus().current();
|
let current_id = *state.corpus().current();
|
||||||
state
|
state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_parent_id_optional(current_idx);
|
.set_parent_id_optional(current_id);
|
||||||
|
|
||||||
if state.metadata_map().get::<ProbabilityMetadata>().is_none() {
|
if state.metadata_map().get::<ProbabilityMetadata>().is_none() {
|
||||||
state.add_metadata(ProbabilityMetadata::new());
|
state.add_metadata(ProbabilityMetadata::new());
|
||||||
}
|
}
|
||||||
self.store_probability(state, idx)
|
self.store_probability(state, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the next entry
|
/// Gets the next entry
|
||||||
@ -262,10 +262,10 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
scheduler.on_add(state.borrow_mut(), idx1).unwrap();
|
scheduler.on_add(state.borrow_mut(), idx1).unwrap();
|
||||||
scheduler.on_add(state.borrow_mut(), idx2).unwrap();
|
scheduler.on_add(state.borrow_mut(), idx2).unwrap();
|
||||||
let next_idx1 = scheduler.next(&mut state).unwrap();
|
let next_id1 = scheduler.next(&mut state).unwrap();
|
||||||
let next_idx2 = scheduler.next(&mut state).unwrap();
|
let next_id2 = scheduler.next(&mut state).unwrap();
|
||||||
let next_idx3 = scheduler.next(&mut state).unwrap();
|
let next_id3 = scheduler.next(&mut state).unwrap();
|
||||||
assert_eq!(next_idx1, next_idx2);
|
assert_eq!(next_id1, next_id2);
|
||||||
assert_ne!(next_idx1, next_idx3);
|
assert_ne!(next_id1, next_id3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,14 @@ impl<S> Scheduler for QueueScheduler<S>
|
|||||||
where
|
where
|
||||||
S: HasCorpus + HasTestcase + State,
|
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
|
// Set parent id
|
||||||
let current_idx = *state.corpus().current();
|
let current_id = *state.corpus().current();
|
||||||
state
|
state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_parent_id_optional(current_idx);
|
.set_parent_id_optional(current_id);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -112,10 +112,10 @@ mod tests {
|
|||||||
|
|
||||||
let mut state = StdState::new(rand, q, objective_q, &mut feedback, &mut objective).unwrap();
|
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
|
let filename = state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(next_idx)
|
.get(next_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow()
|
.borrow()
|
||||||
.filename()
|
.filename()
|
||||||
|
@ -76,14 +76,14 @@ where
|
|||||||
let mut n_paths = 0;
|
let mut n_paths = 0;
|
||||||
let mut v = 0.0;
|
let mut v = 0.0;
|
||||||
let cur_index = state.corpus().current().unwrap();
|
let cur_index = state.corpus().current().unwrap();
|
||||||
for idx in corpus.ids() {
|
for id in corpus.ids() {
|
||||||
let n_fuzz_entry = if cur_index == idx {
|
let n_fuzz_entry = if cur_index == id {
|
||||||
entry
|
entry
|
||||||
.metadata::<SchedulerTestcaseMetadata>()?
|
.metadata::<SchedulerTestcaseMetadata>()?
|
||||||
.n_fuzz_entry()
|
.n_fuzz_entry()
|
||||||
} else {
|
} else {
|
||||||
corpus
|
corpus
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow()
|
.borrow()
|
||||||
.metadata::<SchedulerTestcaseMetadata>()?
|
.metadata::<SchedulerTestcaseMetadata>()?
|
||||||
.n_fuzz_entry()
|
.n_fuzz_entry()
|
||||||
|
@ -104,14 +104,14 @@ impl<S> Scheduler for TuneableScheduler<S>
|
|||||||
where
|
where
|
||||||
S: HasCorpus + HasMetadata + HasTestcase + State,
|
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
|
// Set parent id
|
||||||
let current_idx = *state.corpus().current();
|
let current_id = *state.corpus().current();
|
||||||
state
|
state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(idx)?
|
.get(id)?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_parent_id_optional(current_idx);
|
.set_parent_id_optional(current_id);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,7 @@ where
|
|||||||
fn on_remove(
|
fn on_remove(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
_idx: CorpusId,
|
_id: CorpusId,
|
||||||
_prev: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
_prev: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.table_invalidated = true;
|
self.table_invalidated = true;
|
||||||
@ -279,7 +279,7 @@ where
|
|||||||
fn on_replace(
|
fn on_replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
_idx: CorpusId,
|
_id: CorpusId,
|
||||||
_prev: &Testcase<<Self::State as UsesInput>::Input>,
|
_prev: &Testcase<<Self::State as UsesInput>::Input>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.table_invalidated = true;
|
self.table_invalidated = true;
|
||||||
@ -315,8 +315,8 @@ where
|
|||||||
C: AsRef<O> + Named,
|
C: AsRef<O> + Named,
|
||||||
{
|
{
|
||||||
/// Called when a [`Testcase`] is added to the corpus
|
/// Called when a [`Testcase`] is added to the corpus
|
||||||
fn on_add(&mut self, state: &mut S, idx: CorpusId) -> Result<(), Error> {
|
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
|
||||||
self.on_add_metadata(state, idx)?;
|
self.on_add_metadata(state, id)?;
|
||||||
self.table_invalidated = true;
|
self.table_invalidated = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -385,11 +385,11 @@ where
|
|||||||
fn set_current_scheduled(
|
fn set_current_scheduled(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
next_idx: Option<CorpusId>,
|
next_id: Option<CorpusId>,
|
||||||
) -> Result<(), Error> {
|
) -> 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ where
|
|||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
_manager: &mut EM,
|
_manager: &mut EM,
|
||||||
) -> Result<(), Error> {
|
) -> 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>() {
|
if let Some(meta) = state.metadata_map().get::<DumpToDiskMetadata>() {
|
||||||
(
|
(
|
||||||
meta.last_corpus.and_then(|x| state.corpus().next(x)),
|
meta.last_corpus.and_then(|x| state.corpus().next(x)),
|
||||||
@ -70,7 +70,7 @@ where
|
|||||||
(state.corpus().first(), state.solutions().first())
|
(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();
|
let mut testcase = state.corpus().get(i)?.borrow_mut();
|
||||||
state.corpus().load_input_into(&mut testcase)?;
|
state.corpus().load_input_into(&mut testcase)?;
|
||||||
let bytes = (self.to_bytes)(testcase.input().as_ref().unwrap(), state);
|
let bytes = (self.to_bytes)(testcase.input().as_ref().unwrap(), state);
|
||||||
@ -85,16 +85,16 @@ where
|
|||||||
let mut f = File::create(fname)?;
|
let mut f = File::create(fname)?;
|
||||||
drop(f.write_all(&bytes));
|
drop(f.write_all(&bytes));
|
||||||
|
|
||||||
corpus_idx = state.corpus().next(i);
|
corpus_id = state.corpus().next(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(i) = solutions_idx {
|
while let Some(current_id) = solutions_id {
|
||||||
let mut testcase = state.solutions().get(i)?.borrow_mut();
|
let mut testcase = state.solutions().get(current_id)?.borrow_mut();
|
||||||
state.solutions().load_input_into(&mut testcase)?;
|
state.solutions().load_input_into(&mut testcase)?;
|
||||||
let bytes = (self.to_bytes)(testcase.input().as_ref().unwrap(), state);
|
let bytes = (self.to_bytes)(testcase.input().as_ref().unwrap(), state);
|
||||||
|
|
||||||
let fname = self.solutions_dir.join(format!(
|
let fname = self.solutions_dir.join(format!(
|
||||||
"id_{i}_{}",
|
"id_{current_id}_{}",
|
||||||
testcase
|
testcase
|
||||||
.filename()
|
.filename()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -103,7 +103,7 @@ where
|
|||||||
let mut f = File::create(fname)?;
|
let mut f = File::create(fname)?;
|
||||||
drop(f.write_all(&bytes));
|
drop(f.write_all(&bytes));
|
||||||
|
|
||||||
solutions_idx = state.solutions().next(i);
|
solutions_id = state.solutions().next(current_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.add_metadata(DumpToDiskMetadata {
|
state.add_metadata(DumpToDiskMetadata {
|
||||||
|
@ -81,7 +81,7 @@ where
|
|||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
) -> Result<(), Error> {
|
) -> 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(
|
return Err(Error::illegal_state(
|
||||||
"state is not currently processing a corpus index",
|
"state is not currently processing a corpus index",
|
||||||
));
|
));
|
||||||
@ -91,7 +91,7 @@ where
|
|||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
{
|
{
|
||||||
let corpus = state.corpus();
|
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 {
|
if testcase.scheduled_count() > 0 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -99,14 +99,14 @@ where
|
|||||||
corpus.load_input_into(&mut testcase)?;
|
corpus.load_input_into(&mut testcase)?;
|
||||||
}
|
}
|
||||||
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
|
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 input = entry.input_mut().as_mut().unwrap();
|
||||||
|
|
||||||
let payload: Vec<_> = input.bytes().iter().map(|&x| Some(x)).collect();
|
let payload: Vec<_> = input.bytes().iter().map(|&x| Some(x)).collect();
|
||||||
let original = input.clone();
|
let original = input.clone();
|
||||||
let meta = entry.metadata_map().get::<MapNoveltiesMetadata>().ok_or_else(|| {
|
let meta = entry.metadata_map().get::<MapNoveltiesMetadata>().ok_or_else(|| {
|
||||||
Error::key_not_found(format!(
|
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() {
|
if meta.as_slice().is_empty() {
|
||||||
@ -311,7 +311,7 @@ where
|
|||||||
assert!(meta.generalized().first() == Some(&GeneralizedItem::Gap));
|
assert!(meta.generalized().first() == Some(&GeneralizedItem::Gap));
|
||||||
assert!(meta.generalized().last() == 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);
|
entry.metadata_map_mut().insert(meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -410,13 +410,13 @@ where
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let push_stage = &mut self.push_stage;
|
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(
|
return Err(Error::illegal_state(
|
||||||
"state is not currently processing a corpus index",
|
"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())?;
|
push_stage.init(fuzzer, state, event_mgr, &mut *executor.observers_mut())?;
|
||||||
|
|
||||||
@ -480,7 +480,7 @@ impl RetryRestartHelper {
|
|||||||
S: HasNamedMetadata + HasCurrentCorpusId,
|
S: HasNamedMetadata + HasCurrentCorpusId,
|
||||||
ST: Named,
|
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(
|
Error::illegal_state(
|
||||||
"No current_corpus_id set in State, but called RetryRestartHelper::should_skip",
|
"No current_corpus_id set in State, but called RetryRestartHelper::should_skip",
|
||||||
)
|
)
|
||||||
@ -504,9 +504,9 @@ impl RetryRestartHelper {
|
|||||||
metadata.tries_remaining = Some(tries_remaining);
|
metadata.tries_remaining = Some(tries_remaining);
|
||||||
|
|
||||||
Ok(if tries_remaining == 0 {
|
Ok(if tries_remaining == 0 {
|
||||||
metadata.skipped.insert(corpus_idx);
|
metadata.skipped.insert(corpus_id);
|
||||||
false
|
false
|
||||||
} else if metadata.skipped.contains(&corpus_idx) {
|
} else if metadata.skipped.contains(&corpus_id) {
|
||||||
// skip this testcase, we already retried it often enough...
|
// skip this testcase, we already retried it often enough...
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -757,9 +757,9 @@ pub mod test {
|
|||||||
let mut state = test_std_state();
|
let mut state = test_std_state();
|
||||||
let stage = StageWithOneTry;
|
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 {
|
for _ in 0..10 {
|
||||||
// used normally, no retries means we never skip
|
// used normally, no retries means we never skip
|
||||||
|
@ -27,7 +27,7 @@ use crate::{monitors::PerfFeature, state::HasClientPerfMonitor};
|
|||||||
pub trait MutatedTransformPost<S>: Sized {
|
pub trait MutatedTransformPost<S>: Sized {
|
||||||
/// Perform any post-execution steps necessary for the transformed input (e.g., updating metadata)
|
/// Perform any post-execution steps necessary for the transformed input (e.g., updating metadata)
|
||||||
#[inline]
|
#[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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,11 +136,11 @@ where
|
|||||||
|
|
||||||
// Time is measured directly the `evaluate_input` function
|
// Time is measured directly the `evaluate_input` function
|
||||||
let (untransformed, post) = input.try_transform_into(state)?;
|
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);
|
start_timer!(state);
|
||||||
self.mutator_mut().post_exec(state, corpus_idx)?;
|
self.mutator_mut().post_exec(state, corpus_id)?;
|
||||||
post.post_exec(state, corpus_idx)?;
|
post.post_exec(state, corpus_id)?;
|
||||||
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,9 +347,9 @@ where
|
|||||||
for new_input in generated {
|
for new_input in generated {
|
||||||
// Time is measured directly the `evaluate_input` function
|
// Time is measured directly the `evaluate_input` function
|
||||||
let (untransformed, post) = new_input.try_transform_into(state)?;
|
let (untransformed, post) = new_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)?;
|
||||||
self.mutator.multi_post_exec(state, corpus_idx)?;
|
self.mutator.multi_post_exec(state, corpus_id)?;
|
||||||
post.post_exec(state, corpus_idx)?;
|
post.post_exec(state, corpus_id)?;
|
||||||
}
|
}
|
||||||
// println!("Found {}", found);
|
// println!("Found {}", found);
|
||||||
|
|
||||||
|
@ -193,8 +193,8 @@ where
|
|||||||
fn push_stage_helper_mut(&mut self) -> &mut PushStageHelper<CS, EM, OT, Z>;
|
fn push_stage_helper_mut(&mut self) -> &mut PushStageHelper<CS, EM, OT, Z>;
|
||||||
|
|
||||||
/// Set the current corpus index this stage works on
|
/// Set the current corpus index this stage works on
|
||||||
fn set_current_corpus_id(&mut self, corpus_idx: CorpusId) {
|
fn set_current_corpus_id(&mut self, corpus_id: CorpusId) {
|
||||||
self.push_stage_helper_mut().current_corpus_id = Some(corpus_idx);
|
self.push_stage_helper_mut().current_corpus_id = Some(corpus_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called by `next_std` when this stage is being initialized.
|
/// Called by `next_std` when this stage is being initialized.
|
||||||
|
@ -71,7 +71,7 @@ where
|
|||||||
{
|
{
|
||||||
/// Gets the number of iterations as a random number
|
/// 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
|
#[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))
|
Ok(1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +112,8 @@ where
|
|||||||
_observers: &mut OT,
|
_observers: &mut OT,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Find a testcase to work on, unless someone already set it
|
// 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 {
|
self.current_corpus_id = Some(if let Some(corpus_id) = self.current_corpus_id {
|
||||||
corpus_idx
|
corpus_id
|
||||||
} else {
|
} else {
|
||||||
fuzzer.scheduler_mut().next(state)?
|
fuzzer.scheduler_mut().next(state)?
|
||||||
});
|
});
|
||||||
|
@ -62,7 +62,7 @@ where
|
|||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
_manager: &mut EM,
|
_manager: &mut EM,
|
||||||
) -> Result<(), Error> {
|
) -> 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(
|
return Err(Error::illegal_state(
|
||||||
"state is not currently processing a corpus index",
|
"state is not currently processing a corpus index",
|
||||||
));
|
));
|
||||||
@ -71,7 +71,7 @@ where
|
|||||||
// Report your stats every `STATS_REPORT_INTERVAL`
|
// Report your stats every `STATS_REPORT_INTERVAL`
|
||||||
// compute pending, pending_favored, imported, own_finds
|
// 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 {
|
if testcase.scheduled_count() == 0 {
|
||||||
self.has_fuzzed_size += 1;
|
self.has_fuzzed_size += 1;
|
||||||
if testcase.has_metadata::<IsFavoredMetadata>() {
|
if testcase.has_metadata::<IsFavoredMetadata>() {
|
||||||
|
@ -71,7 +71,7 @@ where
|
|||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
) -> Result<(), Error> {
|
) -> 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(
|
return Err(Error::illegal_state(
|
||||||
"state is not currently processing a corpus index",
|
"state is not currently processing a corpus index",
|
||||||
));
|
));
|
||||||
@ -118,7 +118,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (input, post) = input_transformed.try_transform_into(state)?;
|
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
|
// run the input
|
||||||
let exit_kind = fuzzer.execute_input(state, executor, manager, &input)?;
|
let exit_kind = fuzzer.execute_input(state, executor, manager, &input)?;
|
||||||
let observers = executor.observers();
|
let observers = executor.observers();
|
||||||
@ -129,7 +129,7 @@ where
|
|||||||
// TODO replace if process_execution adds a return value for solution index
|
// TODO replace if process_execution adds a return value for solution index
|
||||||
let solution_count = state.solutions().count();
|
let solution_count = state.solutions().count();
|
||||||
let corpus_count = state.corpus().count();
|
let corpus_count = state.corpus().count();
|
||||||
let (_, corpus_idx) = fuzzer.execute_and_process(
|
let (_, corpus_id) = fuzzer.execute_and_process(
|
||||||
state,
|
state,
|
||||||
manager,
|
manager,
|
||||||
input.clone(),
|
input.clone(),
|
||||||
@ -152,7 +152,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
corpus_idx
|
corpus_id
|
||||||
} else {
|
} else {
|
||||||
// we can't guarantee that the mutators provided will necessarily reduce size, so
|
// 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
|
// skip any mutations that actually increase size so we don't waste eval time
|
||||||
@ -160,8 +160,8 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
self.mutator_mut().post_exec(state, corpus_idx)?;
|
self.mutator_mut().post_exec(state, corpus_id)?;
|
||||||
post.post_exec(state, corpus_idx)?;
|
post.post_exec(state, corpus_id)?;
|
||||||
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
||||||
|
|
||||||
i = next_i;
|
i = next_i;
|
||||||
@ -180,15 +180,15 @@ where
|
|||||||
fuzzer
|
fuzzer
|
||||||
.feedback_mut()
|
.feedback_mut()
|
||||||
.append_metadata(state, manager, &*observers, &mut testcase)?;
|
.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
|
fuzzer
|
||||||
.scheduler_mut()
|
.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.
|
// 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 should be updated along with the base (and is no longer None)
|
||||||
base_post
|
base_post
|
||||||
.ok_or_else(|| Error::empty_optional("Failed to get the MutatedTransformPost"))?
|
.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);
|
state.set_max_size(orig_max_size);
|
||||||
|
@ -456,11 +456,11 @@ where
|
|||||||
|
|
||||||
// Time is measured directly the `evaluate_input` function
|
// Time is measured directly the `evaluate_input` function
|
||||||
let (untransformed, post) = input.try_transform_into(state)?;
|
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);
|
start_timer!(state);
|
||||||
self.mutator_mut().post_exec(state, corpus_idx)?;
|
self.mutator_mut().post_exec(state, corpus_id)?;
|
||||||
post.post_exec(state, corpus_idx)?;
|
post.post_exec(state, corpus_id)?;
|
||||||
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
mark_feature_time!(state, PerfFeature::MutatePostExec);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -260,7 +260,7 @@ pub struct StdState<I, C, R, SC> {
|
|||||||
/// This information is used by fuzzer `maybe_report_progress`.
|
/// This information is used by fuzzer `maybe_report_progress`.
|
||||||
last_report_time: Option<Duration>,
|
last_report_time: Option<Duration>,
|
||||||
/// The current index of the corpus; used to record for resumable fuzzing.
|
/// The current index of the corpus; used to record for resumable fuzzing.
|
||||||
corpus_idx: Option<CorpusId>,
|
corpus_id: Option<CorpusId>,
|
||||||
stage_stack: StageStack,
|
stage_stack: StageStack,
|
||||||
phantom: PhantomData<I>,
|
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> {
|
impl<I, C, R, SC> HasCurrentCorpusId for StdState<I, C, R, SC> {
|
||||||
fn set_corpus_idx(&mut self, idx: CorpusId) -> Result<(), Error> {
|
fn set_corpus_id(&mut self, id: CorpusId) -> Result<(), Error> {
|
||||||
self.corpus_idx = Some(idx);
|
self.corpus_id = Some(id);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_corpus_idx(&mut self) -> Result<(), Error> {
|
fn clear_corpus_id(&mut self) -> Result<(), Error> {
|
||||||
self.corpus_idx = None;
|
self.corpus_id = None;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_corpus_id(&self) -> Result<Option<CorpusId>, Error> {
|
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
|
/// 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<Ref<'_, Testcase<I>>, Error>;
|
||||||
//fn current_testcase(&self) -> Result<&Testcase<I>, Error>;
|
//fn current_testcase(&self) -> Result<&Testcase<I>, Error>;
|
||||||
|
|
||||||
/// Gets the current [`Testcase`] we are fuzzing (mut)
|
/// 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<RefMut<'_, Testcase<I>>, Error>;
|
||||||
//fn current_testcase_mut(&self) -> Result<&mut Testcase<I>, Error>;
|
//fn current_testcase_mut(&self) -> Result<&mut Testcase<I>, Error>;
|
||||||
|
|
||||||
/// Gets a cloned representation of the current [`Testcase`].
|
/// 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
|
/// # Note
|
||||||
/// This allocates memory and copies the contents!
|
/// This allocates memory and copies the contents!
|
||||||
@ -1096,7 +1096,7 @@ where
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
dont_reenter: None,
|
dont_reenter: None,
|
||||||
last_report_time: None,
|
last_report_time: None,
|
||||||
corpus_idx: None,
|
corpus_id: None,
|
||||||
stage_stack: StageStack::default(),
|
stage_stack: StageStack::default(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -1214,11 +1214,11 @@ impl<I> HasRand for NopState<I> {
|
|||||||
impl<I> State for NopState<I> where I: Input {}
|
impl<I> State for NopState<I> where I: Input {}
|
||||||
|
|
||||||
impl<I> HasCurrentCorpusId for NopState<I> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_corpus_idx(&mut self) -> Result<(), Error> {
|
fn clear_corpus_id(&mut self) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
// For `std::simd`
|
// For `std::simd`
|
||||||
#![cfg_attr(nightly, feature(portable_simd))]
|
#![cfg_attr(nightly, feature(portable_simd))]
|
||||||
// For `core::error`
|
// For `core::error`
|
||||||
|
#![cfg_attr(nightly, feature(error_in_core))]
|
||||||
#![warn(clippy::cargo)]
|
#![warn(clippy::cargo)]
|
||||||
#![allow(ambiguous_glob_reexports)]
|
#![allow(ambiguous_glob_reexports)]
|
||||||
#![deny(clippy::cargo_common_metadata)]
|
#![deny(clippy::cargo_common_metadata)]
|
||||||
|
@ -54,28 +54,28 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Touch this index and maybe evict an entry if we have touched an input which was unloaded.
|
/// 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_mapping = self.loaded_mapping.borrow_mut();
|
||||||
let mut loaded_entries = self.loaded_entries.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) => {
|
Entry::Occupied(mut e) => {
|
||||||
let &old = e.get();
|
let &old = e.get();
|
||||||
let new = self.next_recency.fetch_add(1, Ordering::Relaxed);
|
let new = self.next_recency.fetch_add(1, Ordering::Relaxed);
|
||||||
e.insert(new);
|
e.insert(new);
|
||||||
loaded_entries.remove(&old);
|
loaded_entries.remove(&old);
|
||||||
loaded_entries.insert(new, idx);
|
loaded_entries.insert(new, id);
|
||||||
}
|
}
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
// new entry! send it in
|
// new entry! send it in
|
||||||
let new = self.next_recency.fetch_add(1, Ordering::Relaxed);
|
let new = self.next_recency.fetch_add(1, Ordering::Relaxed);
|
||||||
e.insert(new);
|
e.insert(new);
|
||||||
loaded_entries.insert(new, idx);
|
loaded_entries.insert(new, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if loaded_entries.len() > self.max_len {
|
if loaded_entries.len() > self.max_len {
|
||||||
let idx = loaded_entries.pop_first().unwrap().1; // cannot panic
|
let id = loaded_entries.pop_first().unwrap().1; // cannot panic
|
||||||
let cell = corpus.get(idx).ok_or_else(|| {
|
let cell = corpus.get(id).ok_or_else(|| {
|
||||||
Error::key_not_found(format!("Tried to evict non-existent entry {idx}"))
|
Error::key_not_found(format!("Tried to evict non-existent entry {id}"))
|
||||||
})?;
|
})?;
|
||||||
let mut tc = cell.try_borrow_mut()?;
|
let mut tc = cell.try_borrow_mut()?;
|
||||||
let _ = tc.input_mut().take();
|
let _ = tc.input_mut().take();
|
||||||
@ -97,7 +97,7 @@ where
|
|||||||
testcase: RefCell<Testcase<I>>,
|
testcase: RefCell<Testcase<I>>,
|
||||||
is_disabled: bool,
|
is_disabled: bool,
|
||||||
) -> Result<CorpusId, Error> {
|
) -> Result<CorpusId, Error> {
|
||||||
let idx = if is_disabled {
|
let id = if is_disabled {
|
||||||
self.mapping.insert_disabled(testcase)
|
self.mapping.insert_disabled(testcase)
|
||||||
} else {
|
} else {
|
||||||
self.mapping.insert(testcase)
|
self.mapping.insert(testcase)
|
||||||
@ -107,7 +107,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
&self.mapping.enabled
|
&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() {
|
match testcase.file_path() {
|
||||||
Some(path) if path.canonicalize()?.starts_with(&self.corpus_dir) => {
|
Some(path) if path.canonicalize()?.starts_with(&self.corpus_dir) => {
|
||||||
// if it's already in the correct dir, we retain it
|
// 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!",
|
"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);
|
let path = self.corpus_dir.join(&name);
|
||||||
|
|
||||||
match input.to_file(&path) {
|
match input.to_file(&path) {
|
||||||
@ -134,8 +134,8 @@ where
|
|||||||
testcase.file_path_mut().replace(path);
|
testcase.file_path_mut().replace(path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.touch(idx, corpus)?;
|
self.touch(id, corpus)?;
|
||||||
Ok(idx)
|
Ok(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ where
|
|||||||
|
|
||||||
fn replace(
|
fn replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
_idx: CorpusId,
|
_id: CorpusId,
|
||||||
_testcase: Testcase<Self::Input>,
|
_testcase: Testcase<Self::Input>,
|
||||||
) -> Result<Testcase<Self::Input>, Error> {
|
) -> Result<Testcase<Self::Input>, Error> {
|
||||||
unimplemented!("It is unsafe to use this corpus variant with replace!");
|
unimplemented!("It is unsafe to use this corpus variant with replace!");
|
||||||
@ -335,7 +335,7 @@ where
|
|||||||
|
|
||||||
fn replace(
|
fn replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
_idx: CorpusId,
|
_id: CorpusId,
|
||||||
_testcase: Testcase<Self::Input>,
|
_testcase: Testcase<Self::Input>,
|
||||||
) -> Result<Testcase<Self::Input>, Error> {
|
) -> Result<Testcase<Self::Input>, Error> {
|
||||||
unimplemented!("Artifact prefix is thin and cannot get, replace, or remove.")
|
unimplemented!("Artifact prefix is thin and cannot get, replace, or remove.")
|
||||||
|
@ -108,7 +108,7 @@ impl LibfuzzerCrashCauseFeedback {
|
|||||||
let base = if let Some(filename) = testcase.filename() {
|
let base = if let Some(filename) = testcase.filename() {
|
||||||
filename.clone()
|
filename.clone()
|
||||||
} else {
|
} else {
|
||||||
let name = testcase.input().as_ref().unwrap().generate_name(0);
|
let name = testcase.input().as_ref().unwrap().generate_name(None);
|
||||||
name
|
name
|
||||||
};
|
};
|
||||||
let file_path = self.artifact_prefix.dir().join(format!(
|
let file_path = self.artifact_prefix.dir().join(format!(
|
||||||
|
@ -206,15 +206,15 @@ pub fn merge(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx in fuzzer.scheduler().removable() {
|
for id in fuzzer.scheduler().removable() {
|
||||||
let testcase = state.corpus_mut().remove(idx)?;
|
let testcase = state.corpus_mut().remove(id)?;
|
||||||
fuzzer
|
fuzzer
|
||||||
.scheduler_mut()
|
.scheduler_mut()
|
||||||
.on_remove(&mut state, idx, &Some(testcase))?;
|
.on_remove(&mut state, id, &Some(testcase))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx in fuzzer.scheduler().current().clone() {
|
for id in fuzzer.scheduler().current().clone() {
|
||||||
let mut testcase = state.corpus_mut().get(idx)?.borrow_mut();
|
let mut testcase = state.corpus_mut().get(id)?.borrow_mut();
|
||||||
let file_path = testcase
|
let file_path = testcase
|
||||||
.file_path_mut()
|
.file_path_mut()
|
||||||
.as_mut()
|
.as_mut()
|
||||||
@ -231,10 +231,10 @@ pub fn merge(
|
|||||||
new_file_path.push(base);
|
new_file_path.push(base);
|
||||||
if new_file_path.exists() {
|
if new_file_path.exists() {
|
||||||
drop(testcase);
|
drop(testcase);
|
||||||
let testcase = state.corpus_mut().remove(idx)?;
|
let testcase = state.corpus_mut().remove(id)?;
|
||||||
fuzzer
|
fuzzer
|
||||||
.scheduler_mut()
|
.scheduler_mut()
|
||||||
.on_remove(&mut state, idx, &Some(testcase))?;
|
.on_remove(&mut state, id, &Some(testcase))?;
|
||||||
} else {
|
} else {
|
||||||
// False-positive: file_path is used just below
|
// False-positive: file_path is used just below
|
||||||
#[allow(clippy::needless_borrows_for_generic_args)]
|
#[allow(clippy::needless_borrows_for_generic_args)]
|
||||||
|
@ -33,10 +33,10 @@ where
|
|||||||
fn on_remove(
|
fn on_remove(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut Self::State,
|
_state: &mut Self::State,
|
||||||
idx: CorpusId,
|
id: CorpusId,
|
||||||
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
_testcase: &Option<Testcase<<Self::State as UsesInput>::Input>>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.all.remove(&idx);
|
self.all.remove(&id);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,12 +45,12 @@ impl<S> Scheduler for MergeScheduler<S>
|
|||||||
where
|
where
|
||||||
S: State + HasCorpus,
|
S: State + HasCorpus,
|
||||||
{
|
{
|
||||||
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> {
|
||||||
self.all.insert(idx);
|
self.all.insert(id);
|
||||||
let testcase = state.corpus().get(idx)?.borrow();
|
let testcase = state.corpus().get(id)?.borrow();
|
||||||
let meta = testcase.metadata::<MapNoveltiesMetadata>()?;
|
let meta = testcase.metadata::<MapNoveltiesMetadata>()?;
|
||||||
for cov_idx in &meta.list {
|
for cov_ in &meta.list {
|
||||||
self.mapping.insert(*cov_idx, idx);
|
self.mapping.insert(*cov_, id);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -396,15 +396,15 @@ where
|
|||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &mut S::Input,
|
input: &mut S::Input,
|
||||||
) -> Result<MutationResult, Error> {
|
) -> 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
|
// 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 let Some(cur) = state.corpus().current() {
|
||||||
if idx == *cur {
|
if id == *cur {
|
||||||
return Ok(MutationResult::Skipped);
|
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 other = other_testcase.load_input(state.corpus())?;
|
||||||
let data2 = Vec::from(other.bytes());
|
let data2 = Vec::from(other.bytes());
|
||||||
drop(other_testcase);
|
drop(other_testcase);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Stub out syscalls. Linux only.
|
||||||
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use libc::{c_int, c_void, off_t, size_t};
|
use libc::{c_int, c_void, off_t, size_t};
|
||||||
@ -41,6 +43,7 @@ extern "C" {
|
|||||||
/// Call to functions using syscalls
|
/// Call to functions using syscalls
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
|
#[cfg(not(windows))]
|
||||||
pub unsafe extern "C" fn mmap(
|
pub unsafe extern "C" fn mmap(
|
||||||
addr: Pointer,
|
addr: Pointer,
|
||||||
length: size_t,
|
length: size_t,
|
||||||
@ -57,7 +60,10 @@ pub unsafe extern "C" fn mmap(
|
|||||||
|
|
||||||
// validity checks
|
// validity checks
|
||||||
if length == 0 || length % PAGE_SIZE != 0 || (addr as usize) % PAGE_SIZE != 0 {
|
if length == 0 || length % PAGE_SIZE != 0 || (addr as usize) % PAGE_SIZE != 0 {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
*libc::__errno_location() = libc::EINVAL;
|
*libc::__errno_location() = libc::EINVAL;
|
||||||
|
}
|
||||||
return libc::MAP_FAILED as Pointer;
|
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
|
// validity checks
|
||||||
if length == 0 || (addr as usize) % PAGE_SIZE != 0 {
|
if length == 0 || (addr as usize) % PAGE_SIZE != 0 {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
*libc::__errno_location() = libc::EINVAL;
|
*libc::__errno_location() = libc::EINVAL;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
let aligned_length = if length % PAGE_SIZE != 0 {
|
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
|
/// # Safety
|
||||||
/// Call to functions using syscalls
|
/// Call to functions using syscalls
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
#[cfg(not(windows))]
|
||||||
pub unsafe extern "C" fn madvise(addr: *mut c_void, length: size_t, advice: c_int) -> c_int {
|
pub unsafe extern "C" fn madvise(addr: *mut c_void, length: size_t, advice: c_int) -> c_int {
|
||||||
let ctx = Context::get();
|
let ctx = Context::get();
|
||||||
|
|
||||||
if ctx.enabled && advice == libc::MADV_DONTNEED {
|
if ctx.enabled && advice == libc::MADV_DONTNEED {
|
||||||
0
|
0
|
||||||
} else {
|
} 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 {
|
mod tests {
|
||||||
use rusty_fork::rusty_fork_test;
|
use rusty_fork::rusty_fork_test;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user