Add TypeRefCreator trait (#2065)

* poc

* ai suggestion

* rename this

* aaaa

* fmt

* simplify

* delete blob

* ignore

* fixup?

* some progress on cow-ification

* some more

* clippy fixes, finalise tests

* whoops, missed a spot

* no std compat

* api change: Named now requires alloc feature

* doc fix

* missed a spot

* additional fixes

* libfuzzer fixes

* fix tutorial

* fix

* add

* aa

* fix tutorial

* fix

* Rename

* fix

* aa

* fmt

* aa

---------

Co-authored-by: Addison Crump <addison.crump@cispa.de>
This commit is contained in:
Dongjia "toka" Zhang 2024-04-23 19:03:30 +02:00 committed by GitHub
parent 76a95bc5fd
commit 176659821a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
80 changed files with 810 additions and 648 deletions

7
.gitignore vendored
View File

@ -68,3 +68,10 @@ libafl_nyx/packer
*.ll
*.tar.gz
# common harness names
harness
program
fuzzer
fuzzer_libpng*
forkserver_simple

View File

@ -31,7 +31,7 @@ As you can see from the forkserver example,
let mut shmem = StdShMemProvider::new().unwrap().new_shmem(MAP_SIZE).unwrap();
//let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let mut shmem_buf = shmem.as_mut_slice();
let mut shmem_buf = shmem.as_slice_mut();
```
Here we make a shared memory region; `shmem`, and write this to environmental variable `__AFL_SHM_ID`. Then the instrumented binary, or the forkserver, finds this shared memory region (from the aforementioned env var) to record its coverage. On your fuzzer side, you can pass this shmem map to your `Observer` to obtain coverage feedbacks combined with any `Feedback`.
@ -59,7 +59,7 @@ let mut shmem;
unsafe{
shmem = StdShMemProvider::new().unwrap().new_shmem(MAX_EDGES_NUM).unwrap();
}
let shmem_buf = shmem.as_mut_slice();
let shmem_buf = shmem.as_slice_mut();
unsafe{
EDGES_PTR = shmem_buf.as_ptr();
}

View File

@ -22,7 +22,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{unix_shmem, ShMemProvider},
tuples::tuple_list,
AsMutSlice, AsSlice,
AsSlice, AsSliceMut,
};
#[allow(clippy::similar_names)]
@ -30,7 +30,7 @@ pub fn main() {
let mut shmem_provider = unix_shmem::UnixShMemProvider::new().unwrap();
let mut signals = shmem_provider.new_shmem(16).unwrap();
let signals_len = signals.as_slice().len();
let signals_ptr = signals.as_mut_slice().as_mut_ptr();
let signals_ptr = signals.as_slice_mut().as_mut_ptr();
let signals_set = |idx: usize| {
unsafe { write(signals_ptr.add(idx), 1) };

View File

@ -29,7 +29,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{unix_shmem, ShMem, ShMemId, ShMemProvider},
tuples::tuple_list,
AsMutSlice, AsSlice,
AsSlice, AsSliceMut,
};
#[allow(clippy::similar_names)]
@ -39,7 +39,7 @@ pub fn main() {
let shmem_id = signals.id();
// Create an observation channel using the signals map
let observer = unsafe { StdMapObserver::new("signals", signals.as_mut_slice()) };
let observer = unsafe { StdMapObserver::new("signals", signals.as_slice_mut()) };
// Create a stacktrace observer
let bt_observer = AsanBacktraceObserver::new("AsanBacktraceObserver");

View File

@ -25,7 +25,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{ShMem, ShMemProvider},
tuples::tuple_list,
AsMutSlice,
AsSliceMut,
};
#[allow(clippy::similar_names)]
@ -42,7 +42,7 @@ pub fn main() {
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
//let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let shmem_map = shmem.as_mut_slice();
let shmem_map = shmem.as_slice_mut();
// Create an observation channel using the signals map
let edges_observer = HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::new(

View File

@ -24,7 +24,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{unix_shmem, ShMem, ShMemProvider},
tuples::tuple_list,
AsMutSlice, AsSlice,
AsSlice, AsSliceMut,
};
#[allow(clippy::similar_names)]
@ -32,7 +32,7 @@ pub fn main() {
let mut shmem_provider = unix_shmem::UnixShMemProvider::new().unwrap();
let mut signals = shmem_provider.new_shmem(16).unwrap();
let signals_len = signals.len();
let signals_ptr = signals.as_mut_slice().as_mut_ptr();
let signals_ptr = signals.as_slice_mut().as_mut_ptr();
let mut bt = shmem_provider.new_on_shmem::<Option<u64>>(None).unwrap();
let signals_set = |idx: usize| {

View File

@ -1,7 +1,7 @@
use core::time::Duration;
use std::path::PathBuf;
use clap::{self, Parser};
use clap::Parser;
use libafl::{
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
@ -12,7 +12,7 @@ use libafl::{
inputs::BytesInput,
monitors::SimpleMonitor,
mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens},
observers::{CanTrack, ExplicitTracking, HitcountsMapObserver, StdMapObserver, TimeObserver},
observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::mutational::StdMutationalStage,
state::{HasCorpus, StdState},
@ -22,10 +22,10 @@ use libafl_bolts::{
current_nanos,
rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, MatchName, Merge},
AsMutSlice, Truncate,
tuples::{tuple_list, MatchNameRef, Merge, Referenceable},
AsSliceMut, Truncate,
};
use libafl_targets::{EDGES_MAP_PTR, EDGES_MAP_SIZE_IN_USE};
use libafl_targets::EDGES_MAP_SIZE_IN_USE;
use nix::sys::signal::Signal;
/// The commandline args this fuzzer accepts
@ -98,7 +98,7 @@ pub fn main() {
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let shmem_buf = shmem.as_mut_slice();
let shmem_buf = shmem.as_slice_mut();
// the next line is not needed
// unsafe { EDGES_MAP_PTR = shmem_buf.as_mut_ptr() };
@ -167,6 +167,8 @@ pub fn main() {
// Create the executor for the forkserver
let args = opt.arguments;
let observer_ref = edges_observer.type_ref();
let mut tokens = Tokens::new();
let mut executor = ForkserverExecutor::builder()
.program(opt.executable)
@ -183,7 +185,7 @@ pub fn main() {
if let Some(dynamic_map_size) = executor.coverage_map_size() {
executor
.observers_mut()
.match_name_mut::<ExplicitTracking<HitcountsMapObserver<StdMapObserver<'_, u8, false>>, true, false>>("shared_mem")
.match_by_ref_mut(observer_ref)
.unwrap()
.as_mut()
.truncate(dynamic_map_size);

View File

@ -23,7 +23,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, MatchName, Merge},
AsMutSlice, Truncate,
AsSliceMut, Truncate,
};
use nix::sys::signal::Signal;
@ -98,7 +98,7 @@ pub fn main() {
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let shmem_buf = shmem.as_mut_slice();
let shmem_buf = shmem.as_slice_mut();
// Create an observation channel using the signals map
let edges_observer = unsafe {

View File

@ -43,7 +43,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge},
AsMutSlice, AsSlice,
AsSlice, AsSliceMut,
};
use libafl_qemu::{
cmplog::{CmpLogMap, CmpLogObserver, QemuCmpLogChildHelper},
@ -209,11 +209,11 @@ fn fuzz(
let mut shmem_provider = StdShMemProvider::new()?;
let mut edges_shmem = shmem_provider.new_shmem(EDGES_MAP_SIZE_IN_USE).unwrap();
let edges = edges_shmem.as_mut_slice();
let edges = edges_shmem.as_slice_mut();
unsafe { EDGES_MAP_PTR = edges.as_mut_ptr() };
let mut cmp_shmem = shmem_provider.uninit_on_shmem::<CmpLogMap>().unwrap();
let cmplog = cmp_shmem.as_mut_slice();
let cmplog = cmp_shmem.as_slice_mut();
// Beginning of a page should be properly aligned.
#[allow(clippy::cast_ptr_alignment)]

View File

@ -40,7 +40,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, Merge},
AsMutSlice,
AsSliceMut,
};
use libafl_targets::cmps::AFLppCmpLogMap;
use nix::sys::signal::Signal;
@ -245,7 +245,7 @@ fn fuzz(
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let shmem_buf = shmem.as_mut_slice();
let shmem_buf = shmem.as_slice_mut();
// To let know the AFL++ binary that we have a big map
std::env::set_var("AFL_MAP_SIZE", format!("{}", MAP_SIZE));

View File

@ -38,7 +38,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, Merge},
AsMutSlice,
AsSliceMut,
};
use libafl_targets::{
cmps::{observers::AFLppCmpLogObserver, stages::AFLppCmplogTracingStage},
@ -246,7 +246,7 @@ fn fuzz(
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let shmem_buf = shmem.as_mut_slice();
let shmem_buf = shmem.as_slice_mut();
// To let know the AFL++ binary that we have a big map
std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}"));

View File

@ -28,7 +28,7 @@ use libafl::{
serialization_format::{DEFAULT_ENV_NAME, DEFAULT_SIZE},
ConcolicObserver,
},
TimeObserver, CanTrack,
CanTrack, TimeObserver,
},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::{
@ -43,7 +43,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{ShMem, ShMemProvider, StdShMemProvider},
tuples::tuple_list,
AsMutSlice, AsSlice, Named,
AsSliceMut, AsSlice, Named,
};
use libafl_targets::{
libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer, CmpLogObserver,
@ -206,8 +206,7 @@ fn fuzz(
concolic_shmem.write_to_env(DEFAULT_ENV_NAME).unwrap();
// The concolic observer observers the concolic shared memory map.
let concolic_observer =
ConcolicObserver::new("concolic".to_string(), concolic_shmem.as_mut_slice());
let concolic_observer = ConcolicObserver::new("concolic", concolic_shmem.as_slice_mut());
let concolic_observer_name = concolic_observer.name().to_string();

View File

@ -25,7 +25,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list,
AsMutSlice, AsSlice,
AsSlice, AsSliceMut,
};
use libafl_qemu::{
edges::{QemuEdgeCoverageChildHelper, EDGES_MAP_PTR, EDGES_MAP_SIZE_IN_USE},
@ -159,7 +159,7 @@ pub fn fuzz() -> Result<(), Error> {
};
let mut edges_shmem = shmem_provider.new_shmem(EDGES_MAP_SIZE_IN_USE).unwrap();
let edges = edges_shmem.as_mut_slice();
let edges = edges_shmem.as_slice_mut();
unsafe { EDGES_MAP_PTR = edges.as_mut_ptr() };
let edges_observer = unsafe {

View File

@ -1,3 +1,5 @@
use std::borrow::Cow;
use libafl::{
corpus::Testcase,
events::EventFirer,
@ -78,8 +80,9 @@ where
impl Named for PacketLenFeedback {
#[inline]
fn name(&self) -> &str {
"PacketLenFeedback"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("PacketLenFeedback");
&NAME
}
}

View File

@ -1,3 +1,5 @@
use std::borrow::Cow;
use lain::traits::Mutatable;
use libafl::{
mutators::{MutationResult, Mutator},
@ -28,8 +30,9 @@ where
}
impl Named for LainMutator {
fn name(&self) -> &str {
"LainMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("LainMutator");
&NAME
}
}

View File

@ -2,6 +2,7 @@
//! of your corpus.
use alloc::{
borrow::Cow,
string::{String, ToString},
vec::Vec,
};
@ -143,7 +144,7 @@ where
manager.fire(
state,
Event::UpdateUserStats {
name: "minimisation exec pass".to_string(),
name: Cow::from("minimisation exec pass"),
value: UserStats::new(UserStatsValue::Ratio(curr, total), AggregatorOps::None),
phantom: PhantomData,
},

View File

@ -19,9 +19,7 @@ pub use llmp::*;
#[cfg(feature = "tcp_manager")]
#[allow(clippy::ignored_unit_patterns)]
pub mod tcp;
#[cfg(feature = "scalability_introspection")]
use alloc::string::ToString;
use alloc::{boxed::Box, string::String, vec::Vec};
use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec};
use core::{
fmt,
hash::{BuildHasher, Hasher},
@ -315,7 +313,7 @@ where
/// New user stats event to monitor.
UpdateUserStats {
/// Custom user monitor name
name: String,
name: Cow<'static, str>,
/// Custom user monitor value
value: UserStats,
/// [`PhantomData`]
@ -534,7 +532,7 @@ where
self.fire(
state,
Event::UpdateUserStats {
name: "total imported".to_string(),
name: Cow::from("total imported"),
value: UserStats::new(
UserStatsValue::Number(
(imported_with_observer + imported_without_observer) as u64,

View File

@ -23,7 +23,7 @@ use libafl_bolts::{
os::{dup2, pipes::Pipe},
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::Prepend,
AsMutSlice, AsSlice, Truncate,
AsSlice, AsSliceMut, Truncate,
};
use nix::{
sys::{
@ -714,7 +714,7 @@ impl<'a, SP> ForkserverExecutorBuilder<'a, SP> {
shmem.write_to_env("__AFL_SHM_FUZZ_ID")?;
let size_in_bytes = (self.max_input_size + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes();
shmem.as_mut_slice()[..4].clone_from_slice(&size_in_bytes[..4]);
shmem.as_slice_mut()[..4].clone_from_slice(&size_in_bytes[..4]);
Some(shmem)
}
};
@ -1122,9 +1122,9 @@ where
}
let size_in_bytes = size.to_ne_bytes();
// The first four bytes tells the size of the shmem.
map.as_mut_slice()[..SHMEM_FUZZ_HDR_SIZE]
map.as_slice_mut()[..SHMEM_FUZZ_HDR_SIZE]
.copy_from_slice(&size_in_bytes[..SHMEM_FUZZ_HDR_SIZE]);
map.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)]
map.as_slice_mut()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)]
.copy_from_slice(&target_bytes.as_slice()[..size]);
} else {
self.input_file.write_buf(input.target_bytes().as_slice())?;
@ -1228,7 +1228,7 @@ mod tests {
use libafl_bolts::{
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::tuple_list,
AsMutSlice,
AsSliceMut,
};
use serial_test::serial;
@ -1250,7 +1250,7 @@ mod tests {
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let shmem_buf = shmem.as_mut_slice();
let shmem_buf = shmem.as_slice_mut();
let edges_observer = HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::new(
"shared_mem",

View File

@ -3,7 +3,7 @@
//! This feedback should be used in combination with another feedback as this feedback always considers testcases
//! to be not interesting.
//! Requires a [`ConcolicObserver`] to observe the concolic trace.
use alloc::{borrow::ToOwned, string::String};
use alloc::borrow::Cow;
use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::Named;
@ -25,7 +25,7 @@ use crate::{
/// Requires a [`ConcolicObserver`] to observe the concolic trace.
#[derive(Debug)]
pub struct ConcolicFeedback<S> {
name: String,
name: Cow<'static, str>,
phantom: PhantomData<S>,
}
@ -35,14 +35,14 @@ impl<S> ConcolicFeedback<S> {
#[must_use]
pub fn from_observer(observer: &ConcolicObserver) -> Self {
Self {
name: observer.name().to_owned(),
name: observer.name().clone(),
phantom: PhantomData,
}
}
}
impl<S> Named for ConcolicFeedback<S> {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -1,7 +1,7 @@
//! Diff Feedback, comparing the content of two observers of the same type.
//!
use alloc::string::{String, ToString};
use alloc::borrow::Cow;
use core::{
fmt::{self, Debug, Formatter},
marker::PhantomData,
@ -53,11 +53,11 @@ where
F: FnMut(&O1, &O2) -> DiffResult,
{
/// This feedback's name
name: String,
name: Cow<'static, str>,
/// The first observer to compare against
o1_name: String,
o1_name: Cow<'static, str>,
/// The second observer to compare against
o2_name: String,
o2_name: Cow<'static, str>,
/// The function used to compare the two observers
compare_fn: F,
phantomm: PhantomData<(O1, O2, I, S)>,
@ -70,9 +70,9 @@ where
O2: Named,
{
/// Create a new [`DiffFeedback`] using two observers and a test function.
pub fn new(name: &str, o1: &O1, o2: &O2, compare_fn: F) -> Result<Self, Error> {
let o1_name = o1.name().to_string();
let o2_name = o2.name().to_string();
pub fn new(name: &'static str, o1: &O1, o2: &O2, compare_fn: F) -> Result<Self, Error> {
let o1_name = o1.name().clone();
let o2_name = o2.name().clone();
if o1_name == o2_name {
Err(Error::illegal_argument(format!(
"DiffFeedback: observer names must be different (both were {o1_name})"
@ -81,7 +81,7 @@ where
Ok(Self {
o1_name,
o2_name,
name: name.to_string(),
name: Cow::from(name),
compare_fn,
phantomm: PhantomData,
})
@ -115,7 +115,7 @@ where
O1: Named,
O2: Named,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -172,7 +172,7 @@ where
#[cfg(test)]
mod tests {
use alloc::string::{String, ToString};
use alloc::borrow::Cow;
use core::marker::PhantomData;
use libafl_bolts::{tuples::tuple_list, Named};
@ -188,13 +188,13 @@ mod tests {
#[derive(Debug)]
struct NopObserver {
name: String,
name: Cow<'static, str>,
value: bool,
}
impl NopObserver {
fn new(name: &str, value: bool) -> Self {
fn new(name: &'static str, value: bool) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
value,
}
}
@ -206,7 +206,7 @@ mod tests {
}
}
impl Named for NopObserver {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -1,4 +1,4 @@
use alloc::string::{String, ToString};
use alloc::borrow::Cow;
use core::{fmt::Debug, hash::Hash, marker::PhantomData};
use hashbrown::HashSet;
@ -70,8 +70,8 @@ pub struct ListFeedback<T>
where
T: Hash + Eq,
{
name: String,
observer_name: String,
name: Cow<'static, str>,
observer_name: Cow<'static, str>,
novelty: HashSet<T>,
phantom: PhantomData<T>,
}
@ -151,8 +151,8 @@ where
T: Debug + Serialize + Hash + Eq + DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -164,8 +164,8 @@ where
#[must_use]
pub fn new(observer: &ListObserver<T>) -> Self {
Self {
name: observer.name().to_string(),
observer_name: observer.name().to_string(),
name: observer.name().clone(),
observer_name: observer.name().clone(),
novelty: HashSet::<T>::new(),
phantom: PhantomData,
}

View File

@ -1,9 +1,6 @@
//! Map feedback, maximizing or minimizing maps, for example the afl-style map observer.
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, vec::Vec};
#[rustversion::nightly]
use core::simd::prelude::SimdOrd;
use core::{
@ -12,7 +9,7 @@ use core::{
ops::{BitAnd, BitOr},
};
use libafl_bolts::{AsIter, AsMutSlice, AsSlice, HasRefCnt, Named};
use libafl_bolts::{AsIter, AsSlice, AsSliceMut, HasRefCnt, Named};
use num_traits::PrimInt;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
@ -244,11 +241,11 @@ impl AsSlice for MapIndexesMetadata {
}
}
impl AsMutSlice for MapIndexesMetadata {
impl AsSliceMut for MapIndexesMetadata {
type Entry = usize;
/// Convert to a slice
fn as_mut_slice(&mut self) -> &mut [usize] {
self.list.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [usize] {
self.list.as_slice_mut()
}
}
@ -292,12 +289,12 @@ impl AsSlice for MapNoveltiesMetadata {
}
}
impl AsMutSlice for MapNoveltiesMetadata {
impl AsSliceMut for MapNoveltiesMetadata {
type Entry = usize;
/// Convert to a slice
#[must_use]
fn as_mut_slice(&mut self) -> &mut [usize] {
self.list.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [usize] {
self.list.as_slice_mut()
}
}
@ -387,11 +384,11 @@ pub struct MapFeedback<C, N, O, R, S, T> {
/// New indexes observed in the last observation
novelties: Option<Vec<usize>>,
/// Name identifier of this instance
name: String,
name: Cow<'static, str>,
/// Name identifier of the observer
observer_name: String,
observer_name: Cow<'static, str>,
/// Name of the feedback as shown in the `UserStats`
stats_name: String,
stats_name: Cow<'static, str>,
/// Phantom Data of Reducer
phantom: PhantomData<(C, N, O, R, S, T)>,
}
@ -481,7 +478,7 @@ where
map_state.history_map.resize(len, observer.initial());
}
let history_map = map_state.history_map.as_mut_slice();
let history_map = map_state.history_map.as_slice_mut();
if C::INDICES {
let mut indices = Vec::new();
@ -534,7 +531,7 @@ where
manager.fire(
state,
Event::UpdateUserStats {
name: self.stats_name.to_string(),
name: self.stats_name.clone(),
value: UserStats::new(
UserStatsValue::Ratio(covered as u64, len as u64),
AggregatorOps::Avg,
@ -671,8 +668,8 @@ where
impl<C, N, O, R, S, T> Named for MapFeedback<C, N, O, R, S, T> {
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -682,13 +679,18 @@ where
C: AsRef<O>,
{
#[inline]
fn observer_name(&self) -> &str {
self.observer_name.as_str()
fn observer_name(&self) -> &Cow<'static, str> {
&self.observer_name
}
}
fn create_stats_name(name: &str) -> String {
name.to_lowercase()
#[allow(clippy::ptr_arg)]
fn create_stats_name(name: &Cow<'static, str>) -> Cow<'static, str> {
if name.chars().all(char::is_lowercase) {
name.clone()
} else {
name.to_lowercase().into()
}
}
impl<C, N, O, R, S, T> MapFeedback<C, N, O, R, S, T>
@ -707,8 +709,8 @@ where
let map_observer = map_observer.as_ref();
Self {
novelties: if C::NOVELTIES { Some(vec![]) } else { None },
name: map_observer.name().to_string(),
observer_name: map_observer.name().to_string(),
name: map_observer.name().clone(),
observer_name: map_observer.name().clone(),
stats_name: create_stats_name(map_observer.name()),
phantom: PhantomData,
}
@ -719,12 +721,13 @@ where
/// same name and therefore also the same history.
#[must_use]
pub fn with_name(name: &'static str, map_observer: &C) -> Self {
let name = Cow::from(name);
let map_observer = map_observer.as_ref();
Self {
novelties: if C::NOVELTIES { Some(vec![]) } else { None },
name: name.to_string(),
observer_name: map_observer.name().to_string(),
stats_name: create_stats_name(name),
observer_name: map_observer.name().clone(),
stats_name: create_stats_name(&name),
name,
phantom: PhantomData,
}
}

View File

@ -5,6 +5,9 @@
// TODO: make S of Feedback<S> an associated type when specialisation + AT is stable
pub mod map;
use alloc::borrow::Cow;
pub use map::*;
pub mod differential;
@ -29,7 +32,6 @@ pub mod transferred;
/// The module for list feedback
pub mod list;
use alloc::string::{String, ToString};
use core::{
fmt::{self, Debug, Formatter},
marker::PhantomData,
@ -138,7 +140,7 @@ where
/// Has an associated observer name (mostly used to retrieve the observer with `MatchName` from an `ObserverTuple`)
pub trait HasObserverName {
/// The name associated with the observer
fn observer_name(&self) -> &str;
fn observer_name(&self) -> &Cow<'static, str>;
}
/// A combined feedback consisting of multiple [`Feedback`]s
@ -154,7 +156,7 @@ where
pub first: A,
/// Second [`Feedback`]
pub second: B,
name: String,
name: Cow<'static, str>,
phantom: PhantomData<(S, FL)>,
}
@ -165,8 +167,8 @@ where
FL: FeedbackLogic<A, B, S>,
S: State,
{
fn name(&self) -> &str {
self.name.as_ref()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -179,7 +181,12 @@ where
{
/// Create a new combined feedback
pub fn new(first: A, second: B) -> Self {
let name = format!("{} ({},{})", FL::name(), first.name(), second.name());
let name = Cow::from(format!(
"{} ({},{})",
FL::name(),
first.name(),
second.name()
));
Self {
first,
second,
@ -641,7 +648,7 @@ where
/// The feedback to invert
pub first: A,
/// The name
name: String,
name: Cow<'static, str>,
phantom: PhantomData<S>,
}
@ -713,7 +720,7 @@ where
S: State,
{
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -725,7 +732,7 @@ where
{
/// Creates a new [`NotFeedback`].
pub fn new(first: A) -> Self {
let name = format!("Not({})", first.name());
let name = Cow::from(format!("Not({})", first.name()));
Self {
first,
name,
@ -839,8 +846,9 @@ where
impl Named for CrashFeedback {
#[inline]
fn name(&self) -> &str {
"CrashFeedback"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("CrashFeedback");
&NAME
}
}
@ -895,8 +903,9 @@ where
impl Named for TimeoutFeedback {
#[inline]
fn name(&self) -> &str {
"TimeoutFeedback"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("TimeoutFeedback");
&NAME
}
}
@ -922,7 +931,7 @@ pub type TimeoutFeedbackFactory = DefaultFeedbackFactory<TimeoutFeedback>;
/// It decides, if the given [`TimeObserver`] value of a run is interesting.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct TimeFeedback {
name: String,
name: Cow<'static, str>,
}
impl<S> Feedback<S> for TimeFeedback
@ -973,8 +982,8 @@ where
impl Named for TimeFeedback {
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -983,7 +992,7 @@ impl TimeFeedback {
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
}
}
@ -991,7 +1000,7 @@ impl TimeFeedback {
#[must_use]
pub fn with_observer(observer: &TimeObserver) -> Self {
Self {
name: observer.name().to_string(),
name: observer.name().clone(),
}
}
}
@ -1033,8 +1042,9 @@ where
impl Named for ConstFeedback {
#[inline]
fn name(&self) -> &str {
"ConstFeedback"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("ConstFeedback");
&NAME
}
}

View File

@ -1,5 +1,5 @@
//! Nautilus grammar mutator, see <https://github.com/nautilus-fuzz/nautilus>
use alloc::string::String;
use alloc::{borrow::Cow, string::String};
use core::{fmt::Debug, marker::PhantomData};
use std::fs::create_dir_all;
@ -74,8 +74,9 @@ impl<'a, S> NautilusFeedback<'a, S> {
}
impl<'a, S> Named for NautilusFeedback<'a, S> {
fn name(&self) -> &str {
"NautilusFeedback"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("NautilusFeedback");
&NAME
}
}

View File

@ -1,6 +1,6 @@
//! The ``NewHashFeedback`` uses the backtrace hash and a hashset to only keep novel cases
use alloc::string::{String, ToString};
use alloc::{borrow::Cow, string::ToString};
use std::{fmt::Debug, marker::PhantomData};
use hashbrown::HashSet;
@ -78,8 +78,8 @@ impl HashSetState<u64> for NewHashFeedbackMetadata {
/// A [`NewHashFeedback`] maintains a hashset of already seen stacktraces and considers interesting unseen ones
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NewHashFeedback<O, S> {
name: String,
observer_name: String,
name: Cow<'static, str>,
observer_name: Cow<'static, str>,
/// Initial capacity of hash set
capacity: usize,
o_type: PhantomData<(O, S)>,
@ -137,14 +137,14 @@ where
impl<O, S> Named for NewHashFeedback<O, S> {
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl<O, S> HasObserverName for NewHashFeedback<O, S> {
#[inline]
fn observer_name(&self) -> &str {
fn observer_name(&self) -> &Cow<'static, str> {
&self.observer_name
}
}
@ -159,18 +159,6 @@ impl<O, S> NewHashFeedback<O, S>
where
O: ObserverWithHashField + Named,
{
/// Returns a new [`NewHashFeedback`].
/// Setting an observer name that doesn't exist would eventually trigger a panic.
#[must_use]
pub fn with_names(name: &str, observer_name: &str) -> Self {
Self {
name: name.to_string(),
observer_name: observer_name.to_string(),
capacity: DEFAULT_CAPACITY,
o_type: PhantomData,
}
}
/// Returns a new [`NewHashFeedback`].
#[must_use]
pub fn new(observer: &O) -> Self {
@ -182,8 +170,8 @@ where
#[must_use]
pub fn with_capacity(observer: &O, capacity: usize) -> Self {
Self {
name: NEWHASHFEEDBACK_PREFIX.to_string() + observer.name(),
observer_name: observer.name().to_string(),
name: Cow::from(NEWHASHFEEDBACK_PREFIX.to_string() + observer.name()),
observer_name: observer.name().clone(),
capacity,
o_type: PhantomData,
}

View File

@ -1,6 +1,6 @@
//! Feedback and metatadata for stderr and stdout.
use alloc::string::{String, ToString};
use alloc::{borrow::Cow, string::String};
use libafl_bolts::{impl_serdeany, Named};
use serde::{Deserialize, Serialize};
@ -28,7 +28,7 @@ impl_serdeany!(StdOutMetadata);
/// is never interesting (use with an OR).
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct StdOutToMetadataFeedback {
name: String,
name: Cow<'static, str>,
}
impl<S> Feedback<S> for StdOutToMetadataFeedback
@ -90,8 +90,8 @@ where
impl Named for StdOutToMetadataFeedback {
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -99,9 +99,9 @@ impl StdOutToMetadataFeedback {
/// Creates a new [`StdOutToMetadataFeedback`]. The provided `name` is
/// used to look up the observer.
#[must_use]
pub fn new(name: &str) -> Self {
pub fn new(name: &'static str) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
}
}
@ -109,7 +109,7 @@ impl StdOutToMetadataFeedback {
#[must_use]
pub fn with_observer(observer: &StdOutObserver) -> Self {
Self {
name: observer.name().to_string(),
name: observer.name().clone(),
}
}
}
@ -127,7 +127,7 @@ impl_serdeany!(StdErrMetadata);
/// is never interesting (use with an OR).
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct StdErrToMetadataFeedback {
name: String,
name: Cow<'static, str>,
}
impl<S> Feedback<S> for StdErrToMetadataFeedback
@ -189,8 +189,8 @@ where
impl Named for StdErrToMetadataFeedback {
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -198,9 +198,9 @@ impl StdErrToMetadataFeedback {
/// Creates a new [`StdErrToMetadataFeedback`]. The provided `name` is
/// used to look up the observer.
#[must_use]
pub fn new(name: &str) -> Self {
pub fn new(name: &'static str) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
}
}
@ -208,7 +208,7 @@ impl StdErrToMetadataFeedback {
#[must_use]
pub fn with_observer(observer: &StdErrObserver) -> Self {
Self {
name: observer.name().to_string(),
name: observer.name().clone(),
}
}
}

View File

@ -1,6 +1,8 @@
//! Feedbacks and associated metadata for detecting whether a given testcase was transferred from
//! another node.
use alloc::borrow::Cow;
use libafl_bolts::{impl_serdeany, Error, Named};
use serde::{Deserialize, Serialize};
@ -10,7 +12,8 @@ use crate::{
};
/// Constant name of the [`TransferringMetadata`].
pub const TRANSFERRED_FEEDBACK_NAME: &str = "transferred_feedback_internal";
pub const TRANSFERRED_FEEDBACK_NAME: Cow<'static, str> =
Cow::Borrowed("transferred_feedback_internal");
/// Metadata which denotes whether we are currently transferring an input. Implementors of
/// multi-node communication systems (like [`crate::events::LlmpEventManager`]) should wrap any
@ -37,8 +40,8 @@ impl TransferringMetadata {
pub struct TransferredFeedback;
impl Named for TransferredFeedback {
fn name(&self) -> &str {
TRANSFERRED_FEEDBACK_NAME
fn name(&self) -> &Cow<'static, str> {
&TRANSFERRED_FEEDBACK_NAME
}
}

View File

@ -16,7 +16,7 @@ use alloc::string::ToString;
pub use prometheus::PrometheusMonitor;
#[cfg(feature = "std")]
pub mod disk;
use alloc::{fmt::Debug, string::String, vec::Vec};
use alloc::{borrow::Cow, fmt::Debug, string::String, vec::Vec};
use core::{fmt, fmt::Write, time::Duration};
#[cfg(feature = "std")]
@ -158,7 +158,7 @@ pub enum UserStatsValue {
/// A Float value
Float(f64),
/// A `String`
String(String),
String(Cow<'static, str>),
/// A ratio of two values
Ratio(u64, u64),
/// Percent
@ -364,7 +364,7 @@ pub struct ClientStats {
/// the start time of the client
pub start_time: Duration,
/// User-defined monitor
pub user_monitor: HashMap<String, UserStats>,
pub user_monitor: HashMap<Cow<'static, str>, UserStats>,
/// Client performance statistics
#[cfg(feature = "introspection")]
pub introspection_monitor: ClientPerfMonitor,
@ -465,7 +465,11 @@ impl ClientStats {
}
/// Update the user-defined stat with name and value
pub fn update_user_stats(&mut self, name: String, value: UserStats) -> Option<UserStats> {
pub fn update_user_stats(
&mut self,
name: Cow<'static, str>,
value: UserStats,
) -> Option<UserStats> {
self.user_monitor.insert(name, value)
}

View File

@ -22,7 +22,7 @@
// When using docker, you may need to point prometheus.yml to the docker0 interface or host.docker.internal
// ====================
use alloc::{fmt::Debug, string::String, vec::Vec};
use alloc::{borrow::Cow, fmt::Debug, string::String, vec::Vec};
use core::{fmt, time::Duration};
use std::{
sync::{atomic::AtomicU64, Arc},
@ -111,42 +111,42 @@ where
self.corpus_count
.get_or_create(&Labels {
client: sender_id.0,
stat: String::new(),
stat: Cow::from(""),
})
.set(corpus_size.try_into().unwrap());
let objective_size = self.objective_size();
self.objective_count
.get_or_create(&Labels {
client: sender_id.0,
stat: String::new(),
stat: Cow::from(""),
})
.set(objective_size.try_into().unwrap());
let total_execs = self.total_execs();
self.executions
.get_or_create(&Labels {
client: sender_id.0,
stat: String::new(),
stat: Cow::from(""),
})
.set(total_execs.try_into().unwrap());
let execs_per_sec = self.execs_per_sec();
self.exec_rate
.get_or_create(&Labels {
client: sender_id.0,
stat: String::new(),
stat: Cow::from(""),
})
.set(execs_per_sec);
let run_time = (current_time() - self.start_time).as_secs();
self.runtime
.get_or_create(&Labels {
client: sender_id.0,
stat: String::new(),
stat: Cow::from(""),
})
.set(run_time.try_into().unwrap()); // run time in seconds, which can be converted to a time format by Grafana or similar
let total_clients = self.client_stats_count().try_into().unwrap(); // convert usize to u64 (unlikely that # of clients will be > 2^64 -1...)
self.clients_count
.get_or_create(&Labels {
client: sender_id.0,
stat: String::new(),
stat: Cow::from(""),
})
.set(total_clients);
@ -352,7 +352,7 @@ pub async fn serve_metrics(
#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)]
pub struct Labels {
client: u32, // sender_id: u32, to differentiate between clients when multiple are spawned.
stat: String, // for custom_stat filtering.
stat: Cow<'static, str>, // for custom_stat filtering.
}
#[derive(Clone)]

View File

@ -1,6 +1,6 @@
//! Monitor based on ratatui
use alloc::{boxed::Box, string::ToString};
use alloc::{borrow::Cow, boxed::Box, string::ToString};
use core::cmp;
use std::{
collections::VecDeque,
@ -211,7 +211,7 @@ pub struct ClientTuiContext {
pub process_timing: ProcessTiming,
pub item_geometry: ItemGeometry,
pub user_stats: HashMap<String, UserStats>,
pub user_stats: HashMap<Cow<'static, str>, UserStats>,
}
impl ClientTuiContext {

View File

@ -1,6 +1,6 @@
//! Mutations for [`EncodedInput`]s
//!
use alloc::vec::Vec;
use alloc::{borrow::Cow, vec::Vec};
use core::cmp::{max, min};
use libafl_bolts::{
@ -37,8 +37,9 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedRandMutator {
}
impl Named for EncodedRandMutator {
fn name(&self) -> &str {
"EncodedRandMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedRandMutator");
&NAME
}
}
@ -67,8 +68,9 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedIncMutator {
}
impl Named for EncodedIncMutator {
fn name(&self) -> &str {
"EncodedIncMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedIncMutator");
&NAME
}
}
@ -97,8 +99,9 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedDecMutator {
}
impl Named for EncodedDecMutator {
fn name(&self) -> &str {
"EncodedDecMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedDecMutator");
&NAME
}
}
@ -131,8 +134,9 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedAddMutator {
}
impl Named for EncodedAddMutator {
fn name(&self) -> &str {
"EncodedAddMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedAddMutator");
&NAME
}
}
@ -164,8 +168,9 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedDeleteMutator {
}
impl Named for EncodedDeleteMutator {
fn name(&self) -> &str {
"EncodedDeleteMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedDeleteMutator");
&NAME
}
}
@ -224,8 +229,9 @@ where
}
impl Named for EncodedInsertCopyMutator {
fn name(&self) -> &str {
"EncodedInsertCopyMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedInsertCopyMutator");
&NAME
}
}
@ -261,8 +267,9 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedCopyMutator {
}
impl Named for EncodedCopyMutator {
fn name(&self) -> &str {
"EncodedCopyMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedCopyMutator");
&NAME
}
}
@ -330,8 +337,9 @@ where
}
impl Named for EncodedCrossoverInsertMutator {
fn name(&self) -> &str {
"EncodedCrossoverInsertMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedCrossoverInsertMutator");
&NAME
}
}
@ -392,8 +400,9 @@ where
}
impl Named for EncodedCrossoverReplaceMutator {
fn name(&self) -> &str {
"EncodedCrossoverReplaceMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("EncodedCrossoverReplaceMutator");
&NAME
}
}

View File

@ -1,6 +1,6 @@
//! Gramatron is the rewritten gramatron fuzzer in rust.
//! See the original gramatron repo [`Gramatron`](https://github.com/HexHive/Gramatron) for more details.
use alloc::vec::Vec;
use alloc::{borrow::Cow, vec::Vec};
use core::cmp::max;
use hashbrown::HashMap;
@ -56,8 +56,9 @@ impl<'a, S> Named for GramatronRandomMutator<'a, S>
where
S: HasRand + HasMetadata,
{
fn name(&self) -> &str {
"GramatronRandomMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("GramatronRandomMutator");
&NAME
}
}
@ -151,8 +152,9 @@ where
}
impl Named for GramatronSpliceMutator {
fn name(&self) -> &str {
"GramatronSpliceMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("GramatronSpliceMutator");
&NAME
}
}
@ -253,8 +255,9 @@ where
}
impl Named for GramatronRecursionMutator {
fn name(&self) -> &str {
"GramatronRecursionMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("GramatronRecursionMutator");
&NAME
}
}

View File

@ -1,7 +1,7 @@
//! Grimoire is the rewritten grimoire mutator in rust.
//! See the original repo [`Grimoire`](https://github.com/RUB-SysSec/grimoire) for more details.
use alloc::vec::Vec;
use alloc::{borrow::Cow, vec::Vec};
use core::cmp::{max, min};
use libafl_bolts::{
@ -135,8 +135,9 @@ where
}
impl Named for GrimoireExtensionMutator {
fn name(&self) -> &str {
"GrimoireExtensionMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("GrimoireExtensionMutator");
&NAME
}
}
@ -209,8 +210,9 @@ where
}
impl Named for GrimoireRecursiveReplacementMutator {
fn name(&self) -> &str {
"GrimoireRecursiveReplacementMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("GrimoireRecursiveReplacementMutator");
&NAME
}
}
@ -320,8 +322,9 @@ where
}
impl Named for GrimoireStringReplacementMutator {
fn name(&self) -> &str {
"GrimoireStringReplacementMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("GrimoireStringReplacementMutator");
&NAME
}
}
@ -378,8 +381,9 @@ where
}
impl Named for GrimoireRandomDeleteMutator {
fn name(&self) -> &str {
"GrimoireRandomDeleteMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("GrimoireRandomDeleteMutator");
&NAME
}
}

View File

@ -394,11 +394,11 @@ impl<I, S> MutatorsTuple<I, S> for Vec<Box<dyn Mutator<I, S>>> {
}
fn names_reversed(&self) -> Vec<&str> {
self.iter().rev().map(|x| x.name()).collect()
self.iter().rev().map(|x| x.name().as_ref()).collect()
}
fn names(&self) -> Vec<&str> {
self.iter().map(|x| x.name()).collect()
self.iter().map(|x| x.name().as_ref()).collect()
}
}

View File

@ -1,8 +1,5 @@
//! The `MOpt` mutator scheduler, see <https://github.com/puppet-meteor/MOpt-AFL> and <https://www.usenix.org/conference/usenixsecurity19/presentation/lyu>
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, string::ToString, vec::Vec};
use core::{
fmt::{self, Debug},
marker::PhantomData,
@ -367,7 +364,7 @@ where
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
name: String,
name: Cow<'static, str>,
mode: MOptMode,
finds_before: usize,
mutations: MT,
@ -532,7 +529,7 @@ where
state.add_metadata::<MOpt>(MOpt::new(mutations.len(), swarm_num, rand_seed)?);
}
Ok(Self {
name: format!("StdMOptMutator[{}]", mutations.names().join(",")),
name: Cow::from(format!("StdMOptMutator[{}]", mutations.names().join(","))),
mode: MOptMode::Pilotfuzzing,
finds_before: 0,
mutations,
@ -617,7 +614,7 @@ where
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -1,6 +1,9 @@
//! A wide variety of mutations used during fuzzing.
use alloc::{borrow::ToOwned, vec::Vec};
use alloc::{
borrow::{Cow, ToOwned},
vec::Vec,
};
use core::{cmp::min, marker::PhantomData, mem::size_of, ops::Range};
use libafl_bolts::{rands::Rand, Named};
@ -135,8 +138,9 @@ where
}
impl Named for BitFlipMutator {
fn name(&self) -> &str {
"BitFlipMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BitFlipMutator");
&NAME
}
}
@ -168,8 +172,9 @@ where
}
impl Named for ByteFlipMutator {
fn name(&self) -> &str {
"ByteFlipMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("ByteFlipMutator");
&NAME
}
}
@ -202,8 +207,9 @@ where
}
impl Named for ByteIncMutator {
fn name(&self) -> &str {
"ByteIncMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("ByteIncMutator");
&NAME
}
}
@ -236,8 +242,9 @@ where
}
impl Named for ByteDecMutator {
fn name(&self) -> &str {
"ByteDecMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("ByteDecMutator");
&NAME
}
}
@ -270,8 +277,9 @@ where
}
impl Named for ByteNegMutator {
fn name(&self) -> &str {
"ByteNegMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("ByteNegMutator");
&NAME
}
}
@ -304,8 +312,9 @@ where
}
impl Named for ByteRandMutator {
fn name(&self) -> &str {
"ByteRandMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("ByteRandMutator");
&NAME
}
}
@ -364,8 +373,9 @@ macro_rules! add_mutator_impl {
}
impl Named for $name {
fn name(&self) -> &str {
stringify!($name)
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed(stringify!($name));
&NAME
}
}
@ -417,8 +427,9 @@ macro_rules! interesting_mutator_impl {
}
impl Named for $name {
fn name(&self) -> &str {
stringify!($name)
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed(stringify!($name));
&NAME
}
}
@ -460,8 +471,9 @@ where
}
impl Named for BytesDeleteMutator {
fn name(&self) -> &str {
"BytesDeleteMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesDeleteMutator");
&NAME
}
}
@ -506,8 +518,9 @@ where
}
impl Named for BytesExpandMutator {
fn name(&self) -> &str {
"BytesExpandMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesExpandMutator");
&NAME
}
}
@ -559,8 +572,9 @@ where
}
impl Named for BytesInsertMutator {
fn name(&self) -> &str {
"BytesInsertMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesInsertMutator");
&NAME
}
}
@ -612,8 +626,9 @@ where
}
impl Named for BytesRandInsertMutator {
fn name(&self) -> &str {
"BytesRandInsertMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesRandInsertMutator");
&NAME
}
}
@ -650,8 +665,9 @@ where
}
impl Named for BytesSetMutator {
fn name(&self) -> &str {
"BytesSetMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesSetMutator");
&NAME
}
}
@ -688,8 +704,9 @@ where
}
impl Named for BytesRandSetMutator {
fn name(&self) -> &str {
"BytesRandSetMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesRandSetMutator");
&NAME
}
}
@ -728,8 +745,9 @@ where
}
impl Named for BytesCopyMutator {
fn name(&self) -> &str {
"BytesCopyMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesCopyMutator");
&NAME
}
}
@ -787,8 +805,9 @@ where
}
impl Named for BytesInsertCopyMutator {
fn name(&self) -> &str {
"BytesInsertCopyMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesInsertCopyMutator");
&NAME
}
}
@ -990,8 +1009,9 @@ where
}
impl Named for BytesSwapMutator {
fn name(&self) -> &str {
"BytesSwapMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("BytesSwapMutator");
&NAME
}
}
@ -1082,8 +1102,9 @@ where
}
impl<I> Named for CrossoverInsertMutator<I> {
fn name(&self) -> &str {
"CrossoverInsertMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("CrossoverInsertMutator");
&NAME
}
}
@ -1163,8 +1184,9 @@ where
}
impl<I> Named for CrossoverReplaceMutator<I> {
fn name(&self) -> &str {
"CrossoverReplaceMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("CrossoverReplaceMutator");
&NAME
}
}
@ -1242,8 +1264,9 @@ where
}
impl Named for SpliceMutator {
fn name(&self) -> &str {
"SpliceMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("SpliceMutator");
&NAME
}
}

View File

@ -1,5 +1,6 @@
//! Mutators for the `Nautilus` grammmar fuzzer
use alloc::borrow::Cow;
use core::fmt::Debug;
use grammartec::{
@ -60,8 +61,9 @@ impl<S> Mutator<NautilusInput, S> for NautilusRandomMutator<'_> {
}
impl Named for NautilusRandomMutator<'_> {
fn name(&self) -> &str {
"NautilusRandomMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("NautilusRandomMutator");
&NAME
}
}
@ -123,8 +125,9 @@ impl<S> Mutator<NautilusInput, S> for NautilusRecursionMutator<'_> {
}
impl Named for NautilusRecursionMutator<'_> {
fn name(&self) -> &str {
"NautilusRecursionMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("NautilusRecursionMutator");
&NAME
}
}
@ -190,8 +193,9 @@ where
}
impl Named for NautilusSpliceMutator<'_> {
fn name(&self) -> &str {
"NautilusSpliceMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("NautilusSpliceMutator");
&NAME
}
}

View File

@ -1,6 +1,6 @@
//! The `ScheduledMutator` schedules multiple mutations internally.
use alloc::{string::String, vec::Vec};
use alloc::{borrow::Cow, vec::Vec};
use core::{
fmt::{self, Debug},
marker::PhantomData,
@ -9,7 +9,7 @@ use core::{
use libafl_bolts::{
rands::Rand,
tuples::{tuple_list, tuple_list_type, Merge, NamedTuple},
AsMutSlice, AsSlice, Named,
AsSlice, AsSliceMut, Named,
};
use serde::{Deserialize, Serialize};
@ -40,30 +40,30 @@ use crate::{
)] // for SerdeAny
pub struct LogMutationMetadata {
/// A list of logs
pub list: Vec<String>,
pub list: Vec<Cow<'static, str>>,
}
libafl_bolts::impl_serdeany!(LogMutationMetadata);
impl AsSlice for LogMutationMetadata {
type Entry = String;
type Entry = Cow<'static, str>;
#[must_use]
fn as_slice(&self) -> &[String] {
fn as_slice(&self) -> &[Cow<'static, str>] {
self.list.as_slice()
}
}
impl AsMutSlice for LogMutationMetadata {
type Entry = String;
impl AsSliceMut for LogMutationMetadata {
type Entry = Cow<'static, str>;
#[must_use]
fn as_mut_slice(&mut self) -> &mut [String] {
self.list.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [Cow<'static, str>] {
self.list.as_slice_mut()
}
}
impl LogMutationMetadata {
/// Creates new [`struct@LogMutationMetadata`].
#[must_use]
pub fn new(list: Vec<String>) -> Self {
pub fn new(list: Vec<Cow<'static, str>>) -> Self {
Self { list }
}
}
@ -113,7 +113,7 @@ where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
name: String,
name: Cow<'static, str>,
mutations: MT,
max_stack_pow: u64,
phantom: PhantomData<(I, S)>,
@ -139,7 +139,7 @@ where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -198,7 +198,10 @@ where
/// Create a new [`StdScheduledMutator`] instance specifying mutations
pub fn new(mutations: MT) -> Self {
StdScheduledMutator {
name: format!("StdScheduledMutator[{}]", mutations.names().join(", ")),
name: Cow::from(format!(
"StdScheduledMutator[{}]",
mutations.names().join(", ")
)),
mutations,
max_stack_pow: 7,
phantom: PhantomData,
@ -208,7 +211,10 @@ where
/// Create a new [`StdScheduledMutator`] instance specifying mutations and the maximun number of iterations
pub fn with_max_stack_pow(mutations: MT, max_stack_pow: u64) -> Self {
StdScheduledMutator {
name: format!("StdScheduledMutator[{}]", mutations.names().join(", ")),
name: Cow::from(format!(
"StdScheduledMutator[{}]",
mutations.names().join(", ")
)),
mutations,
max_stack_pow,
phantom: PhantomData,
@ -340,7 +346,7 @@ where
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{
name: String,
name: Cow<'static, str>,
scheduled: SM,
mutation_log: Vec<MutationId>,
phantom: PhantomData<(I, MT, S)>,
@ -368,7 +374,7 @@ where
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -386,9 +392,9 @@ where
fn post_exec(&mut self, state: &mut S, corpus_idx: Option<CorpusId>) -> Result<(), Error> {
if let Some(idx) = corpus_idx {
let mut testcase = (*state.corpus_mut().get(idx)?).borrow_mut();
let mut log = Vec::<String>::new();
let mut log = Vec::<Cow<'static, str>>::new();
while let Some(idx) = self.mutation_log.pop() {
let name = String::from(self.scheduled.mutations().name(idx.0).unwrap()); // TODO maybe return an Error on None
let name = self.scheduled.mutations().name(idx.0).unwrap().clone(); // TODO maybe return an Error on None
log.push(name);
}
let meta = LogMutationMetadata::new(log);
@ -460,7 +466,7 @@ where
/// This mutator logs all mutators.
pub fn new(scheduled: SM) -> Self {
Self {
name: format!("LoggerScheduledMutator[{}]", scheduled.name()),
name: Cow::from(format!("LoggerScheduledMutator[{}]", scheduled.name())),
scheduled,
mutation_log: vec![],
phantom: PhantomData,

View File

@ -1,5 +1,5 @@
//! Mutators for preserving string categories, which may be useful for certain targets which are primarily string-oriented.
use alloc::vec::Vec;
use alloc::{borrow::Cow, vec::Vec};
use core::{
cmp::{Ordering, Reverse},
ops::Range,
@ -271,8 +271,9 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
pub struct StringCategoryRandMutator;
impl Named for StringCategoryRandMutator {
fn name(&self) -> &str {
"string-category-rand"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("string-category-rand");
&NAME
}
}
@ -329,8 +330,9 @@ where
pub struct StringSubcategoryRandMutator;
impl Named for StringSubcategoryRandMutator {
fn name(&self) -> &str {
"string-subcategory-rand"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("string-subcategory-rand");
&NAME
}
}
@ -375,8 +377,9 @@ where
pub struct StringCategoryTokenReplaceMutator;
impl Named for StringCategoryTokenReplaceMutator {
fn name(&self) -> &str {
"string-category-token-replace"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("string-category-token-replace");
&NAME
}
}
@ -434,8 +437,9 @@ where
pub struct StringSubcategoryTokenReplaceMutator;
impl Named for StringSubcategoryTokenReplaceMutator {
fn name(&self) -> &str {
"string-subcategory-replace"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("string-subcategory-replace");
&NAME
}
}

View File

@ -1,6 +1,6 @@
//! Tokens are what AFL calls extras or dictionaries.
//! They may be inserted as part of mutations during fuzzing.
use alloc::vec::Vec;
use alloc::{borrow::Cow, vec::Vec};
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
use core::slice::from_raw_parts;
use core::{
@ -346,8 +346,9 @@ where
}
impl Named for TokenInsert {
fn name(&self) -> &str {
"TokenInsert"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("TokenInsert");
&NAME
}
}
@ -404,8 +405,9 @@ where
}
impl Named for TokenReplace {
fn name(&self) -> &str {
"TokenReplace"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("TokenReplace");
&NAME
}
}
@ -588,8 +590,9 @@ where
}
impl Named for I2SRandReplace {
fn name(&self) -> &str {
"I2SRandReplace"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("I2SRandReplace");
&NAME
}
}
@ -1673,8 +1676,9 @@ where
}
impl Named for AFLppRedQueen {
fn name(&self) -> &str {
"AFLppRedQueen"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("AFLppRedQueen");
&NAME
}
}

View File

@ -2,7 +2,7 @@
//! Instead of a random mutator for a random amount of iterations, we can run
//! a specific mutator for a specified amount of iterations
use alloc::{string::String, vec::Vec};
use alloc::{borrow::Cow, vec::Vec};
use core::{
fmt::{self, Debug},
marker::PhantomData,
@ -85,7 +85,7 @@ where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
name: String,
name: Cow<'static, str>,
mutations: MT,
max_stack_pow: u64,
phantom: PhantomData<(I, S)>,
@ -140,7 +140,7 @@ where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -238,7 +238,7 @@ where
state.add_metadata(TuneableScheduledMutatorMetadata::default());
}
TuneableScheduledMutator {
name: format!("TuneableMutator[{}]", mutations.names().join(", ")),
name: Cow::from(format!("TuneableMutator[{}]", mutations.names().join(", "))),
mutations,
max_stack_pow: 7,
phantom: PhantomData,

View File

@ -1,14 +1,11 @@
//! The `CmpObserver` provides access to the logged values of CMP instructions
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, vec::Vec};
use core::{fmt::Debug, marker::PhantomData};
use c2rust_bitfields::BitfieldStruct;
use hashbrown::HashMap;
use libafl_bolts::{ownedref::OwnedRefMut, serdeany::SerdeAny, AsMutSlice, AsSlice, Named};
use libafl_bolts::{ownedref::OwnedRefMut, serdeany::SerdeAny, AsSlice, AsSliceMut, Named};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{executors::ExitKind, inputs::UsesInput, observers::Observer, Error, HasMetadata};
@ -95,12 +92,12 @@ impl AsSlice for CmpValuesMetadata {
}
}
impl AsMutSlice for CmpValuesMetadata {
impl AsSliceMut for CmpValuesMetadata {
type Entry = CmpValues;
/// Convert to a slice
#[must_use]
fn as_mut_slice(&mut self) -> &mut [CmpValues] {
self.list.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [CmpValues] {
self.list.as_slice_mut()
}
}
@ -250,7 +247,7 @@ where
{
cmp_map: OwnedRefMut<'a, CM>,
size: Option<OwnedRefMut<'a, usize>>,
name: String,
name: Cow<'static, str>,
add_meta: bool,
data: M::Data,
phantom: PhantomData<S>,
@ -313,7 +310,7 @@ where
S: UsesInput + HasMetadata,
M: CmpObserverMetadata<'a, CM>,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -328,7 +325,7 @@ where
#[must_use]
pub fn new(name: &'static str, map: OwnedRefMut<'a, CM>, add_meta: bool) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
size: None,
cmp_map: map,
add_meta,
@ -347,7 +344,7 @@ where
data: M::Data,
) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
size: None,
cmp_map,
add_meta,
@ -365,7 +362,7 @@ where
size: OwnedRefMut<'a, usize>,
) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
size: Some(size),
cmp_map,
add_meta,
@ -385,7 +382,7 @@ where
size: OwnedRefMut<'a, usize>,
) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
size: Some(size),
cmp_map,
add_meta,

View File

@ -1,4 +1,4 @@
use alloc::string::String;
use alloc::borrow::Cow;
use libafl_bolts::Named;
use serde::{Deserialize, Serialize};
@ -16,7 +16,7 @@ use crate::{
pub struct ConcolicObserver<'map> {
#[serde(skip)]
map: &'map [u8],
name: String,
name: Cow<'static, str>,
}
impl<'map, S> Observer<S> for ConcolicObserver<'map> where S: UsesInput {}
@ -32,7 +32,7 @@ impl<'map> ConcolicObserver<'map> {
}
impl<'map> Named for ConcolicObserver<'map> {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -40,7 +40,10 @@ impl<'map> Named for ConcolicObserver<'map> {
impl<'map> ConcolicObserver<'map> {
/// Creates a new [`ConcolicObserver`] with the given name and memory buffer.
#[must_use]
pub fn new(name: String, map: &'map [u8]) -> Self {
Self { map, name }
pub fn new(name: &'static str, map: &'map [u8]) -> Self {
Self {
map,
name: Cow::from(name),
}
}
}

View File

@ -1,7 +1,4 @@
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, vec::Vec};
use core::fmt::Debug;
use libafl_bolts::{ownedref::OwnedMutPtr, Error, Named};
@ -17,7 +14,7 @@ pub struct ListObserver<T>
where
T: Debug + Serialize,
{
name: String,
name: Cow<'static, str>,
/// The list
list: OwnedMutPtr<Vec<T>>,
}
@ -34,7 +31,7 @@ where
#[must_use]
pub fn new(name: &'static str, list: OwnedMutPtr<Vec<T>>) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
list,
}
}
@ -67,7 +64,7 @@ impl<T> Named for ListObserver<T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -1,9 +1,6 @@
//! The `MapObserver` provides access a map, usually injected into the target
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, vec::Vec};
use core::{
fmt::Debug,
hash::{Hash, Hasher},
@ -16,7 +13,7 @@ use core::{
use ahash::RandomState;
use libafl_bolts::{
ownedref::{OwnedMutPtr, OwnedMutSlice},
AsIter, AsIterMut, AsMutSlice, AsSlice, HasLen, Named, Truncate,
AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, Truncate,
};
use meminterval::IntervalTree;
use num_traits::Bounded;
@ -181,7 +178,7 @@ impl<T, const ITH: bool, const NTH: bool> Named for ExplicitTracking<T, ITH, NTH
where
T: Named,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
self.0.name()
}
}
@ -532,7 +529,7 @@ where
{
map: OwnedMutSlice<'a, T>,
initial: T,
name: String,
name: Cow<'static, str>,
}
impl<'a, S, T> Observer<S> for StdMapObserver<'a, T, false>
@ -573,8 +570,8 @@ where
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -626,7 +623,7 @@ where
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
let cnt = self.usable_count();
self.as_mut_slice()[..cnt].iter_mut()
self.as_slice_mut()[..cnt].iter_mut()
}
}
@ -669,7 +666,7 @@ where
fn into_iter(self) -> Self::IntoIter {
let cnt = self.usable_count();
self.as_mut_slice()[..cnt].iter_mut()
self.as_slice_mut()[..cnt].iter_mut()
}
}
@ -753,7 +750,7 @@ where
#[inline]
fn get_mut(&mut self, idx: usize) -> &mut T {
&mut self.as_mut_slice()[idx]
&mut self.as_slice_mut()[idx]
}
/// Count the set bytes in the map
@ -795,7 +792,7 @@ where
// Normal memset, see https://rust.godbolt.org/z/Trs5hv
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_mut_slice();
let map = self.as_slice_mut();
for x in &mut map[0..cnt] {
*x = initial;
}
@ -844,15 +841,15 @@ where
}
}
impl<'a, T, const DIFFERENTIAL: bool> AsMutSlice for StdMapObserver<'a, T, DIFFERENTIAL>
impl<'a, T, const DIFFERENTIAL: bool> AsSliceMut for StdMapObserver<'a, T, DIFFERENTIAL>
where
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
{
type Entry = T;
#[must_use]
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] {
self.map.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [T] {
self.map.as_slice_mut()
}
}
@ -868,7 +865,7 @@ where
#[must_use]
unsafe fn maybe_differential<S>(name: S, map: &'a mut [T]) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
let len = map.len();
let ptr = map.as_mut_ptr();
@ -879,7 +876,7 @@ where
#[must_use]
fn maybe_differential_from_mut_slice<S>(name: S, map: OwnedMutSlice<'a, T>) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
StdMapObserver {
name: name.into(),
@ -892,7 +889,7 @@ where
#[must_use]
fn maybe_differential_owned<S>(name: S, map: Vec<T>) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self {
map: OwnedMutSlice::from(map),
@ -908,7 +905,7 @@ where
#[must_use]
fn maybe_differential_from_ownedref<S>(name: S, map: OwnedMutSlice<'a, T>) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self {
map,
@ -923,7 +920,7 @@ where
/// Will dereference the `map_ptr` with up to len elements.
unsafe fn maybe_differential_from_mut_ptr<S>(name: S, map_ptr: *mut T, len: usize) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential_from_mut_slice(
name,
@ -959,7 +956,7 @@ where
#[must_use]
pub unsafe fn new<S>(name: S, map: &'a mut [T]) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential(name, map)
}
@ -967,7 +964,7 @@ where
/// Creates a new [`MapObserver`] from an [`OwnedMutSlice`]
pub fn from_mut_slice<S>(name: S, map: OwnedMutSlice<'a, T>) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential_from_mut_slice(name, map)
}
@ -976,7 +973,7 @@ where
#[must_use]
pub fn owned<S>(name: S, map: Vec<T>) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential_owned(name, map)
}
@ -988,7 +985,7 @@ where
#[must_use]
pub fn from_ownedref<S>(name: S, map: OwnedMutSlice<'a, T>) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential_from_ownedref(name, map)
}
@ -999,7 +996,7 @@ where
/// Will dereference the `map_ptr` with up to len elements.
pub unsafe fn from_mut_ptr<S>(name: S, map_ptr: *mut T, len: usize) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential_from_mut_ptr(name, map_ptr, len)
}
@ -1017,7 +1014,7 @@ where
#[must_use]
pub unsafe fn differential<S>(name: S, map: &'a mut [T]) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential(name, map)
}
@ -1026,7 +1023,7 @@ where
#[must_use]
pub fn differential_owned<S>(name: S, map: Vec<T>) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential_owned(name, map)
}
@ -1038,7 +1035,7 @@ where
#[must_use]
pub fn differential_from_ownedref<S>(name: S, map: OwnedMutSlice<'a, T>) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential_from_ownedref(name, map)
}
@ -1049,7 +1046,7 @@ where
/// Will dereference the `map_ptr` with up to len elements.
pub unsafe fn differential_from_mut_ptr<S>(name: S, map_ptr: *mut T, len: usize) -> Self
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
Self::maybe_differential_from_mut_ptr(name, map_ptr, len)
}
@ -1082,7 +1079,7 @@ where
{
map: OwnedMutSlice<'a, T>,
initial: T,
name: String,
name: Cow<'static, str>,
}
impl<'a, S, T, const N: usize> Observer<S> for ConstMapObserver<'a, T, N>
@ -1102,8 +1099,8 @@ where
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -1155,7 +1152,7 @@ where
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
let cnt = self.usable_count();
self.as_mut_slice()[..cnt].iter_mut()
self.as_slice_mut()[..cnt].iter_mut()
}
}
@ -1197,7 +1194,7 @@ where
fn into_iter(self) -> Self::IntoIter {
let cnt = self.usable_count();
self.as_mut_slice()[..cnt].iter_mut()
self.as_slice_mut()[..cnt].iter_mut()
}
}
@ -1285,7 +1282,7 @@ where
#[inline]
fn get_mut(&mut self, idx: usize) -> &mut T {
&mut self.as_mut_slice()[idx]
&mut self.as_slice_mut()[idx]
}
/// Count the set bytes in the map
@ -1317,7 +1314,7 @@ where
// Normal memset, see https://rust.godbolt.org/z/Trs5hv
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_mut_slice();
let map = self.as_slice_mut();
for x in &mut map[0..cnt] {
*x = initial;
}
@ -1354,14 +1351,14 @@ where
}
}
impl<'a, T, const N: usize> AsMutSlice for ConstMapObserver<'a, T, N>
impl<'a, T, const N: usize> AsSliceMut for ConstMapObserver<'a, T, N>
where
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
{
type Entry = T;
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] {
self.map.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [T] {
self.map.as_slice_mut()
}
}
@ -1379,7 +1376,7 @@ where
assert!(map.len() >= N);
Self {
map: OwnedMutSlice::from(map),
name: name.to_string(),
name: Cow::from(name),
initial: T::default(),
}
}
@ -1391,7 +1388,7 @@ where
let initial = if map.is_empty() { T::default() } else { map[0] };
Self {
map: OwnedMutSlice::from(map),
name: name.to_string(),
name: Cow::from(name),
initial,
}
}
@ -1403,7 +1400,7 @@ where
pub unsafe fn from_mut_ptr(name: &'static str, map_ptr: *mut T) -> Self {
ConstMapObserver {
map: OwnedMutSlice::from_raw_parts_mut(map_ptr, N),
name: name.to_string(),
name: Cow::from(name),
initial: T::default(),
}
}
@ -1420,7 +1417,7 @@ where
map: OwnedMutSlice<'a, T>,
size: OwnedMutPtr<usize>,
initial: T,
name: String,
name: Cow<'static, str>,
}
impl<'a, S, T> Observer<S> for VariableMapObserver<'a, T>
@ -1447,8 +1444,8 @@ where
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Bounded + PartialEq,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -1504,7 +1501,7 @@ where
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
let cnt = self.usable_count();
self.as_mut_slice()[..cnt].iter_mut()
self.as_slice_mut()[..cnt].iter_mut()
}
}
@ -1550,7 +1547,7 @@ where
fn into_iter(self) -> Self::IntoIter {
let cnt = self.usable_count();
self.as_mut_slice()[..cnt].iter_mut()
self.as_slice_mut()[..cnt].iter_mut()
}
}
@ -1647,7 +1644,7 @@ where
}
fn get_mut(&mut self, idx: usize) -> &mut T {
&mut self.map.as_mut_slice()[idx]
&mut self.map.as_slice_mut()[idx]
}
/// Count the set bytes in the map
@ -1675,7 +1672,7 @@ where
// Normal memset, see https://rust.godbolt.org/z/Trs5hv
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_mut_slice();
let map = self.as_slice_mut();
for x in &mut map[0..cnt] {
*x = initial;
}
@ -1722,7 +1719,7 @@ where
}
}
impl<'a, T> AsMutSlice for VariableMapObserver<'a, T>
impl<'a, T> AsSliceMut for VariableMapObserver<'a, T>
where
T: 'static
+ Default
@ -1736,9 +1733,9 @@ where
{
type Entry = T;
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] {
fn as_slice_mut(&mut self) -> &mut [T] {
let cnt = self.usable_count();
&mut self.map.as_mut_slice()[..cnt]
&mut self.map.as_slice_mut()[..cnt]
}
}
@ -1798,7 +1795,7 @@ where
impl<S, M> Observer<S> for HitcountsMapObserver<M>
where
M: MapObserver<Entry = u8> + Observer<S> + AsMutSlice<Entry = u8>,
M: MapObserver<Entry = u8> + Observer<S> + AsSliceMut<Entry = u8>,
S: UsesInput,
{
#[inline]
@ -1814,7 +1811,7 @@ where
input: &S::Input,
exit_kind: &ExitKind,
) -> Result<(), Error> {
let map = self.as_mut_slice();
let map = self.as_slice_mut();
let mut len = map.len();
let align_offset = map.as_ptr().align_offset(size_of::<u16>());
@ -1861,7 +1858,7 @@ where
M: Named + Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
self.base.name()
}
}
@ -1964,14 +1961,14 @@ where
}
}
impl<M> AsMutSlice for HitcountsMapObserver<M>
impl<M> AsSliceMut for HitcountsMapObserver<M>
where
M: MapObserver + AsMutSlice,
M: MapObserver + AsSliceMut,
{
type Entry = <M as AsMutSlice>::Entry;
type Entry = <M as AsSliceMut>::Entry;
#[inline]
fn as_mut_slice(&mut self) -> &mut [Self::Entry] {
self.base.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
self.base.as_slice_mut()
}
}
@ -2063,7 +2060,7 @@ where
M: DifferentialObserver<OTA, OTB, S>
+ MapObserver<Entry = u8>
+ Serialize
+ AsMutSlice<Entry = u8>,
+ AsSliceMut<Entry = u8>,
OTA: ObserversTuple<S>,
OTB: ObserversTuple<S>,
S: UsesInput,
@ -2129,7 +2126,7 @@ where
M: Named + Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
self.base.name()
}
}
@ -2235,14 +2232,14 @@ where
}
}
impl<M> AsMutSlice for HitcountsIterableMapObserver<M>
impl<M> AsSliceMut for HitcountsIterableMapObserver<M>
where
M: MapObserver + AsMutSlice,
M: MapObserver + AsSliceMut,
{
type Entry = <M as AsMutSlice>::Entry;
type Entry = <M as AsSliceMut>::Entry;
#[inline]
fn as_mut_slice(&mut self) -> &mut [Self::Entry] {
self.base.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
self.base.as_slice_mut()
}
}
@ -2366,7 +2363,7 @@ where
intervals: IntervalTree<usize, usize>,
len: usize,
initial: T,
name: String,
name: Cow<'static, str>,
iter_idx: usize,
}
@ -2396,8 +2393,8 @@ where
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned + Debug,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -2472,7 +2469,7 @@ where
let elem = self.intervals.query(idx..=idx).next().unwrap();
let i = *elem.value;
let j = idx - elem.interval.start;
&mut self.maps[i].as_mut_slice()[j]
&mut self.maps[i].as_slice_mut()[j]
}
#[inline]
@ -2501,7 +2498,7 @@ where
fn reset_map(&mut self) -> Result<(), Error> {
let initial = self.initial();
for map in &mut self.maps {
for x in map.as_mut_slice() {
for x in map.as_slice_mut() {
*x = initial;
}
}
@ -2553,7 +2550,7 @@ where
maps,
intervals,
len: idx,
name: name.to_string(),
name: Cow::from(name),
initial: T::default(),
iter_idx: 0,
}
@ -2601,7 +2598,7 @@ where
maps,
intervals,
len: idx,
name: name.to_string(),
name: Cow::from(name),
initial: T::default(),
iter_idx: 0,
}
@ -2695,7 +2692,7 @@ where
{
map: Vec<T>,
initial: T,
name: String,
name: Cow<'static, str>,
}
impl<S, T> Observer<S> for OwnedMapObserver<T>
@ -2715,8 +2712,8 @@ where
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -2750,7 +2747,7 @@ where
type IntoIter = IterMut<'it, T>;
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
self.as_mut_slice().iter_mut()
self.as_slice_mut().iter_mut()
}
}
@ -2774,7 +2771,7 @@ where
type IntoIter = IterMut<'it, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_mut_slice().iter_mut()
self.as_slice_mut().iter_mut()
}
}
@ -2842,7 +2839,7 @@ where
#[inline]
fn get_mut(&mut self, idx: usize) -> &mut T {
&mut self.as_mut_slice()[idx]
&mut self.as_slice_mut()[idx]
}
/// Count the set bytes in the map
@ -2880,7 +2877,7 @@ where
// Normal memset, see https://rust.godbolt.org/z/Trs5hv
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_mut_slice();
let map = self.as_slice_mut();
for x in &mut map[0..cnt] {
*x = initial;
}
@ -2916,15 +2913,15 @@ where
}
}
impl<T> AsMutSlice for OwnedMapObserver<T>
impl<T> AsSliceMut for OwnedMapObserver<T>
where
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned + Debug,
{
type Entry = T;
#[must_use]
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] {
self.map.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [T] {
self.map.as_slice_mut()
}
}
@ -2938,7 +2935,7 @@ where
let initial = if map.is_empty() { T::default() } else { map[0] };
Self {
map,
name: name.to_string(),
name: Cow::from(name),
initial,
}
}

View File

@ -1,6 +1,9 @@
//! Observers give insights about runs of a target, such as coverage, timing, stack depth, and more.
pub mod map;
use alloc::borrow::Cow;
pub use map::*;
pub mod cmp;
@ -22,7 +25,6 @@ pub mod value;
/// List observer
pub mod list;
use alloc::string::{String, ToString};
use core::{fmt::Debug, time::Duration};
#[cfg(feature = "std")]
use std::time::Instant;
@ -410,7 +412,7 @@ where
/// A simple observer, just overlooking the runtime of the target.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TimeObserver {
name: String,
name: Cow<'static, str>,
#[cfg(feature = "std")]
#[serde(with = "instant_serializer")]
@ -453,7 +455,7 @@ impl TimeObserver {
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
#[cfg(feature = "std")]
start_time: Instant::now(),
@ -513,7 +515,7 @@ where
}
impl Named for TimeObserver {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -1,13 +1,11 @@
//! the ``StacktraceObserver`` looks up the stacktrace on the execution thread and computes a hash for it for dedupe
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, string::String, vec::Vec};
#[cfg(feature = "casr")]
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
string::ToString,
};
use std::{
fmt::Debug,
@ -83,10 +81,10 @@ pub fn collect_backtrace() -> u64 {
if symbols.len() > 1 {
let symbol = &symbols[0];
if let Some(name) = symbol.name() {
strace_entry.function = name.as_str().unwrap_or("").to_string();
strace_entry.function = name.as_str().map_or_else(String::new, str::to_string);
}
if let Some(file) = symbol.filename() {
strace_entry.debug.file = file.to_str().unwrap_or("").to_string();
strace_entry.debug.file = file.to_string_lossy().to_string();
}
strace_entry.debug.line = u64::from(symbol.lineno().unwrap_or(0));
strace_entry.debug.column = u64::from(symbol.colno().unwrap_or(0));
@ -116,7 +114,7 @@ pub enum HarnessType {
#[allow(clippy::unsafe_derive_deserialize)]
#[derive(Serialize, Deserialize, Debug)]
pub struct BacktraceObserver<'a> {
observer_name: String,
observer_name: Cow<'static, str>,
hash: OwnedRefMut<'a, Option<u64>>,
harness_type: HarnessType,
}
@ -125,13 +123,16 @@ impl<'a> BacktraceObserver<'a> {
#[cfg(not(feature = "casr"))]
/// Creates a new [`BacktraceObserver`] with the given name.
#[must_use]
pub fn new(
observer_name: &str,
pub fn new<S>(
observer_name: S,
backtrace_hash: OwnedRefMut<'a, Option<u64>>,
harness_type: HarnessType,
) -> Self {
) -> Self
where
S: Into<Cow<'static, str>>,
{
Self {
observer_name: observer_name.to_string(),
observer_name: observer_name.into(),
hash: backtrace_hash,
harness_type,
}
@ -140,14 +141,17 @@ impl<'a> BacktraceObserver<'a> {
#[cfg(feature = "casr")]
/// Creates a new [`BacktraceObserver`] with the given name.
#[must_use]
pub fn new(
observer_name: &str,
pub fn new<S>(
observer_name: S,
backtrace_hash: OwnedRefMut<'a, Option<u64>>,
harness_type: HarnessType,
) -> Self {
) -> Self
where
S: Into<Cow<'static, str>>,
{
init_ignored_frames!("rust", "cpp", "go");
Self {
observer_name: observer_name.to_string(),
observer_name: observer_name.into(),
hash: backtrace_hash,
harness_type,
}
@ -155,7 +159,10 @@ impl<'a> BacktraceObserver<'a> {
/// Creates a new [`BacktraceObserver`] with the given name, owning a new `backtrace_hash` variable.
#[must_use]
pub fn owned(observer_name: &str, harness_type: HarnessType) -> Self {
pub fn owned<S>(observer_name: S, harness_type: HarnessType) -> Self
where
S: Into<Cow<'static, str>>,
{
Self::new(observer_name, OwnedRefMut::owned(None), harness_type)
}
@ -227,7 +234,7 @@ where
}
impl<'a> Named for BacktraceObserver<'a> {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.observer_name
}
}
@ -263,7 +270,7 @@ pub fn get_asan_runtime_flags() -> String {
/// An observer looking at the backtrace of target command using ASAN output
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AsanBacktraceObserver {
observer_name: String,
observer_name: Cow<'static, str>,
hash: Option<u64>,
}
@ -271,9 +278,12 @@ impl AsanBacktraceObserver {
#[cfg(not(feature = "casr"))]
/// Creates a new [`BacktraceObserver`] with the given name.
#[must_use]
pub fn new(observer_name: &str) -> Self {
pub fn new<S>(observer_name: S) -> Self
where
S: Into<Cow<'static, str>>,
{
Self {
observer_name: observer_name.to_string(),
observer_name: observer_name.into(),
hash: None,
}
}
@ -281,10 +291,13 @@ impl AsanBacktraceObserver {
#[cfg(feature = "casr")]
/// Creates a new [`BacktraceObserver`] with the given name.
#[must_use]
pub fn new(observer_name: &str) -> Self {
pub fn new<S>(observer_name: S) -> Self
where
S: Into<Cow<'static, str>>,
{
init_ignored_frames!("rust", "cpp", "go");
Self {
observer_name: observer_name.to_string(),
observer_name: observer_name.into(),
hash: None,
}
}
@ -390,7 +403,7 @@ where
}
impl Named for AsanBacktraceObserver {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.observer_name
}
}

View File

@ -2,7 +2,7 @@
//! The executor must explicitly support these observers.
//! For example, they are supported on the [`crate::executors::CommandExecutor`].
use alloc::string::String;
use alloc::borrow::Cow;
use std::vec::Vec;
use libafl_bolts::Named;
@ -15,7 +15,7 @@ use crate::{inputs::UsesInput, observers::Observer};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct StdOutObserver {
/// The name of the observer.
pub name: String,
pub name: Cow<'static, str>,
/// The stdout of the target during its last execution.
pub stdout: Option<Vec<u8>>,
}
@ -24,8 +24,11 @@ pub struct StdOutObserver {
impl StdOutObserver {
/// Create a new [`StdOutObserver`] with the given name.
#[must_use]
pub fn new(name: String) -> Self {
Self { name, stdout: None }
pub fn new(name: &'static str) -> Self {
Self {
name: Cow::from(name),
stdout: None,
}
}
}
@ -45,7 +48,7 @@ where
}
impl Named for StdOutObserver {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -55,7 +58,7 @@ impl Named for StdOutObserver {
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct StdErrObserver {
/// The name of the observer.
pub name: String,
pub name: Cow<'static, str>,
/// The stderr of the target during its last execution.
pub stderr: Option<Vec<u8>>,
}
@ -64,8 +67,11 @@ pub struct StdErrObserver {
impl StdErrObserver {
/// Create a new [`StdErrObserver`] with the given name.
#[must_use]
pub fn new(name: String) -> Self {
Self { name, stderr: None }
pub fn new(name: &'static str) -> Self {
Self {
name: Cow::from(name),
stderr: None,
}
}
}
@ -85,7 +91,7 @@ where
}
impl Named for StdErrObserver {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -1,9 +1,6 @@
//! A simple observer with a single value.
use alloc::{
boxed::Box,
string::{String, ToString},
};
use alloc::{borrow::Cow, boxed::Box};
use core::{
cell::{Ref, RefCell},
fmt::Debug,
@ -29,7 +26,7 @@ where
T: Debug + Serialize,
{
/// The name of this observer.
name: String,
name: Cow<'static, str>,
/// The value.
pub value: OwnedRef<'a, T>,
}
@ -42,7 +39,7 @@ where
#[must_use]
pub fn new(name: &'static str, value: OwnedRef<'a, T>) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
value,
}
}
@ -87,7 +84,7 @@ impl<'a, T> Named for ValueObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -109,7 +106,7 @@ where
T: Debug + Serialize,
{
/// The name of this observer.
name: String,
name: Cow<'static, str>,
/// The value.
pub value: OwnedRef<'a, RefCell<T>>,
}
@ -122,7 +119,7 @@ where
#[must_use]
pub fn new(name: &'static str, value: OwnedRef<'a, RefCell<T>>) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
value,
}
}
@ -170,7 +167,7 @@ impl<'a, T> Named for RefCellValueObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -4,7 +4,7 @@ use alloc::vec::Vec;
use core::fmt::Debug;
use hashbrown::HashMap;
use libafl_bolts::{rands::Rand, AsMutSlice, AsSlice, HasLen, HasRefCnt};
use libafl_bolts::{rands::Rand, AsSlice, AsSliceMut, HasLen, HasRefCnt};
use serde::{Deserialize, Serialize};
use crate::{
@ -42,12 +42,12 @@ impl AsSlice for AccountingIndexesMetadata {
self.list.as_slice()
}
}
impl AsMutSlice for AccountingIndexesMetadata {
impl AsSliceMut for AccountingIndexesMetadata {
type Entry = usize;
/// Convert to a slice
fn as_mut_slice(&mut self) -> &mut [usize] {
self.list.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [usize] {
self.list.as_slice_mut()
}
}

View File

@ -1,6 +1,7 @@
//! The calibration stage. The fuzzer measures the average exec time and the bitmap size.
use alloc::{
borrow::Cow,
string::{String, ToString},
vec::Vec,
};
@ -311,7 +312,7 @@ where
mgr.fire(
state,
Event::UpdateUserStats {
name: "stability".to_string(),
name: Cow::from("stability"),
value: UserStats::new(
UserStatsValue::Ratio(
(map_len - unstable_entries) as u64,

View File

@ -1,9 +1,5 @@
//! The colorization stage from `colorization()` in afl++
use alloc::{
collections::binary_heap::BinaryHeap,
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, collections::binary_heap::BinaryHeap, string::ToString, vec::Vec};
use core::{cmp::Ordering, fmt::Debug, marker::PhantomData, ops::Range};
use libafl_bolts::{rands::Rand, tuples::MatchName, Named};
@ -55,7 +51,7 @@ impl Ord for Earlier {
/// The mutational stage using power schedules
#[derive(Clone, Debug)]
pub struct ColorizationStage<C, E, EM, O, Z> {
map_observer_name: String,
map_observer_name: Cow<'static, str>,
#[allow(clippy::type_complexity)]
phantom: PhantomData<(C, E, EM, O, E, Z)>,
}
@ -71,7 +67,7 @@ impl<C, E, EM, O, Z> Named for ColorizationStage<C, E, EM, O, Z>
where
E: UsesState,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.map_observer_name
}
}
@ -301,7 +297,7 @@ where
/// Creates a new [`ColorizationStage`]
pub fn new(map_observer: &C) -> Self {
Self {
map_observer_name: map_observer.name().to_string(),
map_observer_name: map_observer.name().clone(),
phantom: PhantomData,
}
}

View File

@ -2,7 +2,7 @@
//! and use the results for fuzzer input and mutations.
//!
use alloc::string::String;
use alloc::{borrow::Cow, string::String};
#[cfg(feature = "concolic_mutation")]
use alloc::{string::ToString, vec::Vec};
#[cfg(feature = "concolic_mutation")]
@ -47,8 +47,9 @@ where
}
impl<EM, TE, Z> Named for ConcolicTracingStage<EM, TE, Z> {
fn name(&self) -> &str {
"ConcolicTracingStage"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("ConcolicTracingStage");
&NAME
}
}

View File

@ -1,6 +1,7 @@
//! The tracing stage can trace the target and enrich a [`crate::corpus::Testcase`] with metadata, for example for `CmpLog`.
use alloc::{
borrow::Cow,
string::{String, ToString},
vec::Vec,
};
@ -49,8 +50,9 @@ pub struct GeneralizationStage<C, EM, O, OT, Z> {
}
impl<C, EM, O, OT, Z> Named for GeneralizationStage<C, EM, O, OT, Z> {
fn name(&self) -> &str {
"GeneralizationStage"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("GeneralizationStage");
&NAME
}
}

View File

@ -4,8 +4,8 @@ A well-known [`Stage`], for example, is the mutational stage, running multiple [
Other stages may enrich [`crate::corpus::Testcase`]s with metadata.
*/
use alloc::{boxed::Box, vec::Vec};
use core::{any, marker::PhantomData};
use alloc::{borrow::Cow, boxed::Box, vec::Vec};
use core::marker::PhantomData;
pub use calibrate::CalibrationStage;
pub use colorization::*;
@ -305,8 +305,9 @@ where
CB: FnMut(&mut Z, &mut E, &mut E::State, &mut EM) -> Result<(), Error>,
E: UsesState,
{
fn name(&self) -> &str {
any::type_name::<Self>()
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("<unnamed fn>");
&NAME
}
}
@ -644,6 +645,7 @@ impl ExecutionCountRestartHelper {
#[cfg(test)]
pub mod test {
use alloc::borrow::Cow;
use core::marker::PhantomData;
use libafl_bolts::{impl_serdeany, Error, Named};
@ -745,8 +747,9 @@ pub mod test {
struct StageWithOneTry;
impl Named for StageWithOneTry {
fn name(&self) -> &str {
"TestStage"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("TestStage");
&NAME
}
}

View File

@ -1,7 +1,8 @@
//| The [`MutationalStage`] is the default stage used during fuzzing.
//! For the current input, it will perform a range of random mutations, and then run them in the executor.
use core::{any::type_name, marker::PhantomData};
use alloc::borrow::Cow;
use core::marker::PhantomData;
use libafl_bolts::{rands::Rand, Named};
@ -313,8 +314,9 @@ where
Z: Evaluator<E, EM>,
Z::State: HasCorpus + HasRand,
{
fn name(&self) -> &str {
type_name::<Self>()
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("MultiMutational");
&NAME
}
}

View File

@ -1,7 +1,7 @@
//! Stage to compute/report AFL stats
#[cfg(feature = "std")]
use alloc::string::ToString;
use alloc::{borrow::Cow, string::ToString};
use core::{marker::PhantomData, time::Duration};
use libafl_bolts::current_time;
@ -109,9 +109,9 @@ where
_manager.fire(
state,
Event::UpdateUserStats {
name: "AflStats".to_string(),
name: Cow::from("AflStats"),
value: UserStats::new(
UserStatsValue::String(json.to_string()),
UserStatsValue::String(Cow::from(json.to_string())),
AggregatorOps::None,
),
phantom: PhantomData,

View File

@ -1,5 +1,6 @@
//! The [`SyncFromDiskStage`] is a stage that imports inputs from disk for e.g. sync with AFL
use alloc::borrow::Cow;
use core::marker::PhantomData;
use std::{
fs,
@ -63,8 +64,9 @@ impl<CB, E, EM, Z> Named for SyncFromDiskStage<CB, E, EM, Z>
where
E: UsesState,
{
fn name(&self) -> &str {
self.sync_dir.to_str().unwrap()
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("SyncFromDiskStage");
&NAME
}
}

View File

@ -1,6 +1,6 @@
//! The [`TMinMutationalStage`] is a stage which will attempt to minimize corpus entries.
use alloc::string::{String, ToString};
use alloc::borrow::Cow;
use core::{borrow::BorrowMut, fmt::Debug, hash::Hash, marker::PhantomData};
use ahash::RandomState;
@ -349,33 +349,20 @@ where
/// provided
#[derive(Clone, Debug)]
pub struct MapEqualityFeedback<M, S> {
name: String,
obs_name: String,
name: Cow<'static, str>,
obs_name: Cow<'static, str>,
orig_hash: u64,
phantom: PhantomData<(M, S)>,
}
impl<M, S> MapEqualityFeedback<M, S> {
/// Create a new map equality feedback -- can be used with feedback logic
#[must_use]
pub fn new(name: &str, obs_name: &str, orig_hash: u64) -> Self {
MapEqualityFeedback {
name: name.to_string(),
obs_name: obs_name.to_string(),
orig_hash,
phantom: PhantomData,
}
}
}
impl<M, S> Named for MapEqualityFeedback<M, S> {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl<M, S> HasObserverName for MapEqualityFeedback<M, S> {
fn observer_name(&self) -> &str {
fn observer_name(&self) -> &Cow<'static, str> {
&self.obs_name
}
}
@ -407,7 +394,7 @@ where
/// A feedback factory for ensuring that the maps for minimized inputs are the same
#[derive(Debug, Clone)]
pub struct MapEqualityFactory<M, S> {
obs_name: String,
obs_name: Cow<'static, str>,
phantom: PhantomData<(M, S)>,
}
@ -418,14 +405,14 @@ where
/// Creates a new map equality feedback for the given observer
pub fn with_observer(obs: &M) -> Self {
Self {
obs_name: obs.name().to_string(),
obs_name: obs.name().clone(),
phantom: PhantomData,
}
}
}
impl<M, S> HasObserverName for MapEqualityFactory<M, S> {
fn observer_name(&self) -> &str {
fn observer_name(&self) -> &Cow<'static, str> {
&self.obs_name
}
}
@ -441,7 +428,7 @@ where
.match_name::<M>(self.observer_name())
.expect("Should have been provided valid observer name.");
MapEqualityFeedback {
name: "MapEq".to_string(),
name: Cow::from("MapEq"),
obs_name: self.obs_name.clone(),
orig_hash: obs.hash_simple(),
phantom: PhantomData,

View File

@ -1,5 +1,6 @@
//! The tracing stage can trace the target and enrich a testcase with metadata, for example for `CmpLog`.
use alloc::borrow::Cow;
use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::Named;
@ -106,8 +107,9 @@ where
}
impl<EM, TE, Z> Named for TracingStage<EM, TE, Z> {
fn name(&self) -> &str {
"TracingStage"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("TracingStage");
&NAME
}
}
@ -159,8 +161,9 @@ impl<E, EM, SOT, Z> Named for ShadowTracingStage<E, EM, SOT, Z>
where
E: UsesState,
{
fn name(&self) -> &str {
"ShadowTracingStage"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("ShadowTracingStage");
&NAME
}
}

View File

@ -164,7 +164,7 @@ pub mod bolts_prelude {
#[cfg(all(unix, feature = "std"))]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use alloc::{borrow::Cow, vec::Vec};
#[cfg(all(not(feature = "xxh3"), feature = "alloc"))]
use core::hash::BuildHasher;
#[cfg(any(feature = "xxh3", feature = "alloc"))]
@ -231,9 +231,10 @@ use {
pub const IP_LOCALHOST: &str = "127.0.0.1";
/// We need fixed names for many parts of this lib.
#[cfg(feature = "alloc")]
pub trait Named {
/// Provide the name of this element.
fn name(&self) -> &str;
fn name(&self) -> &Cow<'static, str>;
}
#[cfg(feature = "errors_backtrace")]
@ -681,11 +682,11 @@ pub trait AsSlice {
}
/// Can be converted to a mutable slice
pub trait AsMutSlice {
pub trait AsSliceMut {
/// Type of the entries in this mut slice
type Entry;
/// Convert to a slice
fn as_mut_slice(&mut self) -> &mut [Self::Entry];
fn as_slice_mut(&mut self) -> &mut [Self::Entry];
}
#[cfg(feature = "alloc")]
@ -698,10 +699,10 @@ impl<T> AsSlice for Vec<T> {
}
#[cfg(feature = "alloc")]
impl<T> AsMutSlice for Vec<T> {
impl<T> AsSliceMut for Vec<T> {
type Entry = T;
fn as_mut_slice(&mut self) -> &mut [Self::Entry] {
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
self
}
}
@ -722,18 +723,18 @@ impl<T> AsSlice for [T] {
}
}
impl<T> AsMutSlice for &mut [T] {
impl<T> AsSliceMut for &mut [T] {
type Entry = T;
fn as_mut_slice(&mut self) -> &mut [Self::Entry] {
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
self
}
}
impl<T> AsMutSlice for [T] {
impl<T> AsSliceMut for [T] {
type Entry = T;
fn as_mut_slice(&mut self) -> &mut [Self::Entry] {
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
self
}
}

View File

@ -394,7 +394,7 @@ impl Listener {
#[inline]
#[allow(clippy::cast_ptr_alignment)]
unsafe fn shmem2page_mut<SHM: ShMem>(afl_shmem: &mut SHM) -> *mut LlmpPage {
afl_shmem.as_mut_slice().as_mut_ptr() as *mut LlmpPage
afl_shmem.as_slice_mut().as_mut_ptr() as *mut LlmpPage
}
/// Get sharedmem from a page

View File

@ -40,7 +40,7 @@ use uds::{UnixListenerExt, UnixSocketAddr, UnixStreamExt};
use crate::{
shmem::{ShMem, ShMemDescription, ShMemId, ShMemProvider},
AsMutSlice, AsSlice, Error,
AsSlice, AsSliceMut, Error,
};
/// The default server name for our abstract shmem server
@ -102,13 +102,13 @@ where
self.inner.as_slice()
}
}
impl<SH> AsMutSlice for ServedShMem<SH>
impl<SH> AsSliceMut for ServedShMem<SH>
where
SH: ShMem,
{
type Entry = u8;
fn as_mut_slice(&mut self) -> &mut [u8] {
self.inner.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [u8] {
self.inner.as_slice_mut()
}
}

View File

@ -10,7 +10,7 @@ use core::{clone::Clone, fmt::Debug, slice};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{shmem::ShMem, AsMutSlice, AsSlice, IntoOwned, Truncate};
use crate::{shmem::ShMem, AsSlice, AsSliceMut, IntoOwned, Truncate};
/// Private part of the unsafe marker, making sure this cannot be initialized directly.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
@ -562,7 +562,7 @@ impl<'a, 'it, T> IntoIterator for &'it mut OwnedMutSlice<'a, T> {
type IntoIter = IterMut<'it, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_mut_slice().iter_mut()
self.as_slice_mut().iter_mut()
}
}
@ -651,17 +651,17 @@ impl<'a, T: Sized> AsSlice for OwnedMutSlice<'a, T> {
}
}
}
impl<'a, T: Sized> AsMutSlice for OwnedMutSlice<'a, T> {
impl<'a, T: Sized> AsSliceMut for OwnedMutSlice<'a, T> {
type Entry = T;
/// Get the value as mut slice
#[must_use]
fn as_mut_slice(&mut self) -> &mut [T] {
fn as_slice_mut(&mut self) -> &mut [T] {
match &mut self.inner {
OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe {
slice::from_raw_parts_mut(*rr, *len)
},
OwnedMutSliceInner::Ref(r) => r,
OwnedMutSliceInner::Owned(v) => v.as_mut_slice(),
OwnedMutSliceInner::Owned(v) => v.as_slice_mut(),
}
}
}

View File

@ -31,7 +31,7 @@ pub use win32_shmem::{Win32ShMem, Win32ShMemProvider};
use crate::os::pipes::Pipe;
#[cfg(all(feature = "std", unix, not(target_os = "haiku")))]
pub use crate::os::unix_shmem_server::{ServedShMemProvider, ShMemService};
use crate::{AsMutSlice, AsSlice, Error};
use crate::{AsSlice, AsSliceMut, Error};
/// The standard sharedmem provider
#[cfg(all(windows, feature = "std"))]
@ -192,7 +192,7 @@ impl Display for ShMemId {
/// A [`ShMem`] is an interface to shared maps.
/// They are the backbone of [`crate::llmp`] for inter-process communication.
/// All you need for scaling on a new target is to implement this interface, as well as the respective [`ShMemProvider`].
pub trait ShMem: Sized + Debug + Clone + AsSlice<Entry = u8> + AsMutSlice<Entry = u8> {
pub trait ShMem: Sized + Debug + Clone + AsSlice<Entry = u8> + AsSliceMut<Entry = u8> {
/// Get the id of this shared memory mapping
fn id(&self) -> ShMemId;
@ -218,7 +218,7 @@ pub trait ShMem: Sized + Debug + Clone + AsSlice<Entry = u8> + AsMutSlice<Entry
/// If the map is too small, returns `None`
fn as_mut_ptr_of<T: Sized>(&mut self) -> Option<*mut T> {
if self.len() >= mem::size_of::<T>() {
Some(self.as_mut_slice().as_mut_ptr() as *mut T)
Some(self.as_slice_mut().as_mut_ptr() as *mut T)
} else {
None
}
@ -357,13 +357,13 @@ where
}
#[cfg(feature = "alloc")]
impl<T> AsMutSlice for RcShMem<T>
impl<T> AsSliceMut for RcShMem<T>
where
T: ShMemProvider + Debug,
{
type Entry = u8;
fn as_mut_slice(&mut self) -> &mut [u8] {
self.internal.as_mut_slice()
fn as_slice_mut(&mut self) -> &mut [u8] {
self.internal.as_slice_mut()
}
}
@ -600,7 +600,7 @@ pub mod unix_shmem {
use crate::{
rands::{Rand, RandomSeed, StdRand},
shmem::{ShMem, ShMemId, ShMemProvider},
AsMutSlice, AsSlice, Error,
AsSlice, AsSliceMut, Error,
};
// This is macOS's limit
@ -782,9 +782,9 @@ pub mod unix_shmem {
}
}
impl AsMutSlice for MmapShMem {
impl AsSliceMut for MmapShMem {
type Entry = u8;
fn as_mut_slice(&mut self) -> &mut [u8] {
fn as_slice_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.map, self.map_size) }
}
}
@ -894,9 +894,9 @@ pub mod unix_shmem {
}
}
impl AsMutSlice for CommonUnixShMem {
impl AsSliceMut for CommonUnixShMem {
type Entry = u8;
fn as_mut_slice(&mut self) -> &mut [u8] {
fn as_slice_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.map, self.map_size) }
}
}
@ -964,7 +964,7 @@ pub mod unix_shmem {
use crate::{
shmem::{ShMem, ShMemId, ShMemProvider},
AsMutSlice, AsSlice, Error,
AsSlice, AsSliceMut, Error,
};
/// An ashmem based impl for linux/android
@ -1104,10 +1104,10 @@ pub mod unix_shmem {
}
}
impl AsMutSlice for AshmemShMem {
impl AsSliceMut for AshmemShMem {
type Entry = u8;
fn as_mut_slice(&mut self) -> &mut [u8] {
fn as_slice_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.map, self.map_size) }
}
}
@ -1189,7 +1189,7 @@ pub mod win32_shmem {
use crate::{
shmem::{ShMem, ShMemId, ShMemProvider},
AsMutSlice, AsSlice, Error,
AsSlice, AsSliceMut, Error,
};
const INVALID_HANDLE_VALUE: isize = -1;
@ -1303,9 +1303,9 @@ pub mod win32_shmem {
unsafe { slice::from_raw_parts(self.map, self.map_size) }
}
}
impl AsMutSlice for Win32ShMem {
impl AsSliceMut for Win32ShMem {
type Entry = u8;
fn as_mut_slice(&mut self) -> &mut [u8] {
fn as_slice_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.map, self.map_size) }
}
}
@ -1395,7 +1395,7 @@ impl<T: ShMem> ShMemCursor<T> {
/// Slice from the current location on this map to the end, mutable
fn empty_slice_mut(&mut self) -> &mut [u8] {
&mut (self.inner.as_mut_slice()[self.pos..])
&mut (self.inner.as_slice_mut()[self.pos..])
}
}
@ -1470,7 +1470,7 @@ mod tests {
use crate::{
shmem::{ShMemProvider, StdShMemProvider},
AsMutSlice, AsSlice,
AsSlice, AsSliceMut,
};
#[test]
@ -1479,7 +1479,7 @@ mod tests {
fn test_shmem_service() {
let mut provider = StdShMemProvider::new().unwrap();
let mut map = provider.new_shmem(1024).unwrap();
map.as_mut_slice()[0] = 1;
map.as_slice_mut()[0] = 1;
assert!(map.as_slice()[0] == 1);
}
}

View File

@ -1,11 +1,12 @@
//! Compiletime lists/tuples used throughout the `LibAFL` universe
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use alloc::{borrow::Cow, vec::Vec};
#[rustversion::not(nightly)]
use core::any::type_name;
use core::{
any::TypeId,
marker::PhantomData,
mem::transmute,
ptr::{addr_of, addr_of_mut},
};
@ -14,7 +15,9 @@ pub use tuple_list::{tuple_list, tuple_list_type, TupleList};
#[cfg(any(feature = "xxh3", feature = "alloc"))]
use crate::hash_std;
use crate::{HasLen, Named};
use crate::HasLen;
#[cfg(feature = "alloc")]
use crate::Named;
/// Returns if the type `T` is equal to `U`
/// From <https://stackoverflow.com/a/60138532/7658998>
@ -407,31 +410,36 @@ where
}
}
#[cfg(feature = "alloc")]
/// A named tuple
pub trait NamedTuple: HasConstLen {
/// Gets the name of this tuple
fn name(&self, index: usize) -> Option<&str>;
fn name(&self, index: usize) -> Option<&Cow<'static, str>>;
}
#[cfg(feature = "alloc")]
impl NamedTuple for () {
fn name(&self, _index: usize) -> Option<&str> {
fn name(&self, _index: usize) -> Option<&Cow<'static, str>> {
None
}
}
#[cfg(feature = "alloc")]
impl Named for () {
#[inline]
fn name(&self) -> &str {
"Empty"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("Empty");
&NAME
}
}
#[cfg(feature = "alloc")]
impl<Head, Tail> NamedTuple for (Head, Tail)
where
Head: Named,
Tail: NamedTuple,
{
fn name(&self, index: usize) -> Option<&str> {
fn name(&self, index: usize) -> Option<&Cow<'static, str>> {
if index == 0 {
Some(self.0.name())
} else {
@ -445,6 +453,7 @@ where
/// # Note
/// This operation may not be 100% accurate with Rust stable, see the notes for [`type_eq`]
/// (in `nightly`, it uses [specialization](https://stackoverflow.com/a/60138532/7658998)).
#[cfg(feature = "alloc")]
pub trait MatchName {
/// Match for a name and return the borrowed value
fn match_name<T>(&self, name: &str) -> Option<&T>;
@ -452,6 +461,7 @@ pub trait MatchName {
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T>;
}
#[cfg(feature = "alloc")]
impl MatchName for () {
fn match_name<T>(&self, _name: &str) -> Option<&T> {
None
@ -461,6 +471,7 @@ impl MatchName for () {
}
}
#[cfg(feature = "alloc")]
impl<Head, Tail> MatchName for (Head, Tail)
where
Head: Named,
@ -484,6 +495,7 @@ where
}
/// Finds an element of a `type` by the given `name`.
#[cfg(feature = "alloc")]
pub trait MatchNameAndType {
/// Finds an element of a `type` by the given `name`, and returns a borrow, or [`Option::None`].
fn match_name_type<T: 'static>(&self, name: &str) -> Option<&T>;
@ -491,6 +503,7 @@ pub trait MatchNameAndType {
fn match_name_type_mut<T: 'static>(&mut self, name: &str) -> Option<&mut T>;
}
#[cfg(feature = "alloc")]
impl MatchNameAndType for () {
fn match_name_type<T: 'static>(&self, _name: &str) -> Option<&T> {
None
@ -500,6 +513,7 @@ impl MatchNameAndType for () {
}
}
#[cfg(feature = "alloc")]
impl<Head, Tail> MatchNameAndType for (Head, Tail)
where
Head: 'static + Named,
@ -524,6 +538,54 @@ where
}
}
/// Structs that has `ReReference `
/// You should use this when you want to avoid specifying types using `match_name_type_mut`
#[cfg(feature = "alloc")]
pub trait Referenceable: Named {
/// Return the `ReReference `
fn type_ref(&self) -> ReReference<Self> {
ReReference {
name: Named::name(self).clone(),
phantom: PhantomData,
}
}
}
#[cfg(feature = "alloc")]
impl<N> Referenceable for N where N: Named {}
/// Empty object with the type T
#[derive(Debug)]
#[cfg(feature = "alloc")]
pub struct ReReference<T: ?Sized> {
name: Cow<'static, str>,
phantom: PhantomData<T>,
}
/// Search using `ReReference `
#[cfg(feature = "alloc")]
pub trait MatchNameRef {
/// Search using name and `ReReference `
fn match_by_ref<T>(&self, rf: ReReference<T>) -> Option<&T>;
/// Search using name and `ReReference `
fn match_by_ref_mut<T>(&mut self, rf: ReReference<T>) -> Option<&mut T>;
}
#[cfg(feature = "alloc")]
impl<M> MatchNameRef for M
where
M: MatchName,
{
fn match_by_ref<T>(&self, rf: ReReference<T>) -> Option<&T> {
self.match_name::<T>(&rf.name)
}
fn match_by_ref_mut<T>(&mut self, rf: ReReference<T>) -> Option<&mut T> {
self.match_name_mut::<T>(&rf.name)
}
}
/// Allows prepending of values to a tuple
pub trait Prepend<T> {
/// The Resulting [`TupleList`], of an [`Prepend::prepend()`] call,

View File

@ -196,7 +196,7 @@ where
// The index is modulo by the length, therefore it is always in bounds
let len = self.hitcounts_map.len();
self.hitcounts_map
.as_mut_slice()
.as_slice_mut()
.get_unchecked_mut(hash % len)
};
*val = val.saturating_add(1);

View File

@ -1,5 +1,6 @@
//! Errors that can be caught by the `libafl_frida` address sanitizer.
use std::{
borrow::Cow,
fmt::Debug,
io::Write,
marker::PhantomData,
@ -38,6 +39,8 @@ use crate::{
alloc::AllocationMetadata, asan::asan_rt::ASAN_SAVE_REGISTER_COUNT, utils::disas_count,
};
static ASAN_ERRORS_NAME: Cow<'static, str> = Cow::Borrowed("AsanErrors");
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct AsanReadWriteError {
pub registers: [usize; ASAN_SAVE_REGISTER_COUNT],
@ -587,8 +590,8 @@ where
impl Named for AsanErrorsObserver {
#[inline]
fn name(&self) -> &str {
"AsanErrors"
fn name(&self) -> &Cow<'static, str> {
&ASAN_ERRORS_NAME
}
}
@ -662,7 +665,7 @@ where
OT: ObserversTuple<S>,
{
let observer = observers
.match_name::<AsanErrorsObserver>("AsanErrors")
.match_name::<AsanErrorsObserver>(&ASAN_ERRORS_NAME)
.expect("An AsanErrorsFeedback needs an AsanErrorsObserver");
let errors = observer.errors();
if errors.is_empty() {
@ -698,8 +701,8 @@ where
impl<S> Named for AsanErrorsFeedback<S> {
#[inline]
fn name(&self) -> &str {
"AsanErrors"
fn name(&self) -> &Cow<'static, str> {
&ASAN_ERRORS_NAME
}
}

View File

@ -1,5 +1,6 @@
use alloc::rc::Rc;
use core::{cell::RefCell, fmt::Debug};
use std::borrow::Cow;
use libafl::{
alloc,
@ -36,8 +37,9 @@ impl LibfuzzerKeepFeedback {
}
impl Named for LibfuzzerKeepFeedback {
fn name(&self) -> &str {
"libfuzzer-keep"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("libfuzzer-keep");
&NAME
}
}
@ -90,8 +92,9 @@ impl LibfuzzerCrashCauseFeedback {
}
impl Named for LibfuzzerCrashCauseFeedback {
fn name(&self) -> &str {
"crash-cause"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("crash-cause");
&NAME
}
}

View File

@ -1,4 +1,5 @@
use std::{
borrow::Cow,
fmt::Debug,
hash::{Hash, Hasher},
};
@ -37,7 +38,7 @@ pub trait ValueObserver: for<'de> Deserialize<'de> + Serialize + Debug + Named {
#[derive(Deserialize, Serialize, Debug)]
pub struct MappedEdgeMapObserver<M, O> {
inner: M,
name: String,
name: Cow<'static, str>,
value_observer: O,
}
@ -48,7 +49,7 @@ where
{
pub fn new(obs: M, value_obs: O) -> Self {
Self {
name: format!("{}_{}", value_obs.name(), obs.name()),
name: Cow::from(format!("{}_{}", value_obs.name(), obs.name())),
inner: obs,
value_observer: value_obs,
}
@ -77,7 +78,7 @@ where
}
impl<M, O> Named for MappedEdgeMapObserver<M, O> {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -251,8 +252,9 @@ impl ValueObserver for SizeValueObserver {
}
impl Named for SizeValueObserver {
fn name(&self) -> &str {
"size"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("size");
&NAME
}
}
@ -295,7 +297,7 @@ impl ValueObserver for TimeValueObserver {
}
impl Named for TimeValueObserver {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
self.time_obs.name()
}
}
@ -356,8 +358,9 @@ impl ValueObserver for SizeTimeValueObserver {
}
impl Named for SizeTimeValueObserver {
fn name(&self) -> &str {
"size_time"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("size_time");
&NAME
}
}

View File

@ -101,7 +101,7 @@ impl<T> __IncompleteArrayField<T> {
::std::slice::from_raw_parts(self.as_ptr(), len)
}
#[inline]
pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
pub unsafe fn as_slice_mut(&mut self, len: usize) -> &mut [T] {
::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
}
}

View File

@ -27,7 +27,7 @@ use libafl_bolts::{
rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, Merge},
AsMutSlice,
AsSliceMut,
};
use typed_builder::TypedBuilder;
@ -120,7 +120,7 @@ impl<'a> ForkserverBytesCoverageSugar<'a> {
// Coverage map shared between target and fuzzer
let mut shmem = shmem_provider_client.new_shmem(MAP_SIZE).unwrap();
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let shmem_map = shmem.as_mut_slice();
let shmem_map = shmem.as_slice_mut();
// To let know the AFL++ binary that we have a big map
std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}"));

View File

@ -1,7 +1,4 @@
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, vec::Vec};
use core::{fmt::Debug, marker::PhantomData};
use libafl::{
@ -74,7 +71,7 @@ where
{
cmp_map: OwnedRefMut<'a, AFLppCmpLogMap>,
size: Option<OwnedRefMut<'a, usize>>,
name: String,
name: Cow<'static, str>,
add_meta: bool,
original: <AFLppCmpValuesMetadata as CmpObserverMetadata<'a, AFLppCmpLogMap>>::Data,
phantom: PhantomData<S>,
@ -183,7 +180,7 @@ impl<'a, S> Named for AFLppCmpLogObserver<'a, S>
where
S: UsesInput + HasMetadata,
{
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -200,7 +197,7 @@ where
add_meta: bool,
) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
size: None,
cmp_map,
add_meta,
@ -223,7 +220,7 @@ where
size: OwnedRefMut<'a, usize>,
) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
size: Some(size),
cmp_map,
add_meta,

View File

@ -2,7 +2,7 @@
//! The values will then be used in subsequent mutations.
//!
use alloc::string::{String, ToString};
use alloc::borrow::Cow;
use core::fmt::Debug;
use libafl::{
@ -22,7 +22,7 @@ pub struct CmpLogObserver {
map: OwnedMutPtr<CmpLogMap>,
size: Option<OwnedMutPtr<usize>>,
add_meta: bool,
name: String,
name: Cow<'static, str>,
}
impl<'a, S> CmpObserver<'a, CmpLogMap, S, CmpValuesMetadata> for CmpLogObserver
@ -78,7 +78,7 @@ where
}
impl Named for CmpLogObserver {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -91,7 +91,7 @@ impl CmpLogObserver {
#[must_use]
pub unsafe fn with_map_ptr(name: &'static str, map: *mut CmpLogMap, add_meta: bool) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
size: None,
add_meta,
map: OwnedMutPtr::Ptr(map),

View File

@ -1,4 +1,7 @@
use alloc::string::{String, ToString};
use alloc::{
borrow::Cow,
string::{String, ToString},
};
use core::marker::PhantomData;
#[cfg(feature = "introspection")]
@ -32,8 +35,9 @@ where
}
impl<EM, TE, Z> Named for AFLppCmplogTracingStage<EM, TE, Z> {
fn name(&self) -> &str {
"AFLppCmplogTracingStage"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("AFLppCmplogTracingStage");
&NAME
}
}

View File

@ -1,6 +1,6 @@
//! Coverage maps as static mut array
use alloc::string::String;
use alloc::borrow::Cow;
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
use libafl::{mutators::Tokens, Error};
@ -108,7 +108,7 @@ pub unsafe fn edges_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> {
/// This will dereference [`edges_map_mut_ptr`] and crash if it is not a valid address.
pub unsafe fn std_edges_map_observer<'a, S>(name: S) -> StdMapObserver<'a, u8, false>
where
S: Into<String>,
S: Into<Cow<'static, str>>,
{
StdMapObserver::from_mut_slice(name, edges_map_mut_slice())
}
@ -152,7 +152,7 @@ pub use swap::*;
#[cfg(feature = "pointer_maps")]
mod swap {
use alloc::string::{String, ToString};
use alloc::borrow::Cow;
use core::fmt::Debug;
use libafl::{
@ -160,7 +160,7 @@ mod swap {
observers::{DifferentialObserver, Observer, ObserversTuple, StdMapObserver},
Error,
};
use libafl_bolts::{ownedref::OwnedMutSlice, AsMutSlice, Named};
use libafl_bolts::{ownedref::OwnedMutSlice, AsSliceMut, Named};
use serde::{Deserialize, Serialize};
use super::{EDGES_MAP_PTR, EDGES_MAP_PTR_NUM};
@ -173,9 +173,9 @@ mod swap {
pub struct DifferentialAFLMapSwapObserver<'a, 'b> {
first_map: OwnedMutSlice<'a, u8>,
second_map: OwnedMutSlice<'b, u8>,
first_name: String,
second_name: String,
name: String,
first_name: Cow<'static, str>,
second_name: Cow<'static, str>,
name: Cow<'static, str>,
}
impl<'a, 'b> DifferentialAFLMapSwapObserver<'a, 'b> {
@ -185,15 +185,15 @@ mod swap {
second: &mut StdMapObserver<'b, u8, D2>,
) -> Self {
Self {
first_name: first.name().to_string(),
second_name: second.name().to_string(),
name: format!("differential_{}_{}", first.name(), second.name()),
first_name: first.name().clone(),
second_name: second.name().clone(),
name: Cow::from(format!("differential_{}_{}", first.name(), second.name())),
first_map: unsafe {
let slice = first.map_mut().as_mut_slice();
let slice = first.map_mut().as_slice_mut();
OwnedMutSlice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len())
},
second_map: unsafe {
let slice = second.map_mut().as_mut_slice();
let slice = second.map_mut().as_slice_mut();
OwnedMutSlice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len())
},
}
@ -225,7 +225,7 @@ mod swap {
}
impl<'a, 'b> Named for DifferentialAFLMapSwapObserver<'a, 'b> {
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -240,7 +240,7 @@ mod swap {
S: UsesInput,
{
fn pre_observe_first(&mut self, _: &mut OTA) -> Result<(), Error> {
let slice = self.first_map.as_mut_slice();
let slice = self.first_map.as_slice_mut();
unsafe {
EDGES_MAP_PTR = slice.as_mut_ptr();
EDGES_MAP_PTR_NUM = slice.len();
@ -249,7 +249,7 @@ mod swap {
}
fn pre_observe_second(&mut self, _: &mut OTB) -> Result<(), Error> {
let slice = self.second_map.as_mut_slice();
let slice = self.second_map.as_slice_mut();
unsafe {
EDGES_MAP_PTR = slice.as_mut_ptr();
EDGES_MAP_PTR_NUM = slice.len();

View File

@ -1,4 +1,7 @@
use alloc::rc::{Rc, Weak};
use alloc::{
borrow::Cow,
rc::{Rc, Weak},
};
use std::{
cell::RefCell,
marker::PhantomData,
@ -279,8 +282,9 @@ where
}
impl<MT, SM> Named for LLVMCustomMutator<MT, SM, false> {
fn name(&self) -> &str {
"LLVMCustomMutator"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("LLVMCustomMutator");
&NAME
}
}
@ -353,8 +357,9 @@ where
}
impl<MT, SM> Named for LLVMCustomMutator<MT, SM, true> {
fn name(&self) -> &str {
"LLVMCustomCrossover"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("LLVMCustomCrossover");
&NAME
}
}

View File

@ -1,3 +1,4 @@
use alloc::borrow::Cow;
use core::{ffi::c_void, fmt::Debug};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
@ -68,7 +69,7 @@ pub unsafe extern "C" fn __sanitizer_free_hook(ptr: *const c_void) {
}
}
const OOM_OBS_NAME: &str = "libfuzzer-like-oom";
static OOM_OBS_NAME: Cow<'static, str> = Cow::Borrowed("libfuzzer-like-oom");
/// Observer which detects if the target would run out of memory or otherwise violate the permissible usage of malloc
#[derive(Debug, Serialize, Deserialize)]
@ -88,8 +89,8 @@ impl OomObserver {
impl Named for OomObserver {
// strictly one name to prevent two from being registered
fn name(&self) -> &str {
OOM_OBS_NAME
fn name(&self) -> &Cow<'static, str> {
&OOM_OBS_NAME
}
}
@ -142,8 +143,9 @@ impl OomFeedback {
}
impl Named for OomFeedback {
fn name(&self) -> &str {
"oom"
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("oom");
&NAME
}
}

View File

@ -2,7 +2,7 @@
use alloc::vec::Vec;
use core::ptr::addr_of_mut;
use libafl_bolts::{ownedref::OwnedMutSlice, AsMutSlice, AsSlice};
use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut};
/// A [`Vec`] of `8-bit-counters` maps for multiple modules.
/// They are initialized by calling [`__sanitizer_cov_8bit_counters_init`](
@ -32,9 +32,9 @@ pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> {
pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) {
unsafe {
for existing in &mut *addr_of_mut!(COUNTERS_MAPS) {
let range = existing.as_mut_slice().as_mut_ptr()
let range = existing.as_slice_mut().as_mut_ptr()
..=existing
.as_mut_slice()
.as_slice_mut()
.as_mut_ptr()
.add(existing.as_slice().len());
if range.contains(&start) || range.contains(&stop) {
@ -59,10 +59,7 @@ pub use self::observers::{counters_maps_observer, CountersMultiMapObserver};
#[cfg(feature = "observers")]
mod observers {
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloc::{borrow::Cow, vec::Vec};
use core::{
fmt::Debug,
hash::{Hash, Hasher},
@ -78,7 +75,7 @@ mod observers {
Error,
};
use libafl_bolts::{
ownedref::OwnedMutSlice, AsIter, AsIterMut, AsMutSlice, AsSlice, HasLen, Named,
ownedref::OwnedMutSlice, AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named,
};
use meminterval::IntervalTree;
use serde::{Deserialize, Serialize};
@ -122,7 +119,7 @@ mod observers {
intervals: IntervalTree<usize, usize>,
len: usize,
initial: u8,
name: String,
name: Cow<'static, str>,
iter_idx: usize,
}
@ -147,8 +144,8 @@ mod observers {
impl<const DIFFERENTIAL: bool> Named for CountersMultiMapObserver<DIFFERENTIAL> {
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -200,7 +197,7 @@ mod observers {
let elem = self.intervals.query_mut(idx..=idx).next().unwrap();
let i = elem.value;
let j = idx - elem.interval.start;
unsafe { &mut (*addr_of_mut!(COUNTERS_MAPS[*i])).as_mut_slice()[j] }
unsafe { &mut (*addr_of_mut!(COUNTERS_MAPS[*i])).as_slice_mut()[j] }
}
#[inline]
@ -229,7 +226,7 @@ mod observers {
fn reset_map(&mut self) -> Result<(), Error> {
let initial = self.initial();
for map in unsafe { &mut *addr_of_mut!(COUNTERS_MAPS) } {
for x in map.as_mut_slice() {
for x in map.as_slice_mut() {
*x = initial;
}
}
@ -277,7 +274,7 @@ mod observers {
Self {
intervals,
len: idx,
name: name.to_string(),
name: Cow::from(name),
initial: u8::default(),
iter_idx: 0,
}
@ -308,7 +305,7 @@ mod observers {
unsafe { &mut *addr_of_mut!(COUNTERS_MAPS) }
.iter_mut()
.for_each(|m| {
let l = m.as_mut_slice().len();
let l = m.as_slice_mut().len();
intervals.insert(idx..(idx + l), v);
idx += l;
v += 1;
@ -316,7 +313,7 @@ mod observers {
Self {
intervals,
len: idx,
name: name.to_string(),
name: Cow::from(name),
initial: u8::default(),
iter_idx: 0,
}

View File

@ -11,7 +11,7 @@ use libafl::{
use libafl_bolts::{
fs::{InputFile, INPUTFILE_STD},
shmem::{ShMem, ShMemProvider, StdShMemProvider},
AsMutSlice, AsSlice,
AsSlice, AsSliceMut,
};
use tinyinst::tinyinst::{litecov::RunResult, TinyInst};
@ -65,9 +65,9 @@ where
let size = target_bytes.as_slice().len();
let size_in_bytes = size.to_ne_bytes();
// The first four bytes tells the size of the shmem.
shmem.as_mut_slice()[..SHMEM_FUZZ_HDR_SIZE]
shmem.as_slice_mut()[..SHMEM_FUZZ_HDR_SIZE]
.copy_from_slice(&size_in_bytes[..SHMEM_FUZZ_HDR_SIZE]);
shmem.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)]
shmem.as_slice_mut()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)]
.copy_from_slice(target_bytes.as_slice());
}
None => {
@ -240,7 +240,7 @@ where
// shmem.write_to_env("__TINY_SHM_FUZZ_ID")?;
let size_in_bytes = (MAX_FILE + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes();
shmem.as_mut_slice()[..4].clone_from_slice(&size_in_bytes[..4]);
shmem.as_slice_mut()[..4].clone_from_slice(&size_in_bytes[..4]);
(Some(shmem), Some(shmem_id))
}