Allow for AsIter(Mut)/AsSlice(Mut) to be implemented in safe Rust (#2120)
* Generalize `AsIter` to allow iterating over contents of a `RefCell` Towards `MapObserver`s in safe Rust. * Helpers for `RefCellValueObserver` * MapObserver: Return owned Self::Entry from .get() `Self::Entry` is `Copy`, so there's not much value in returning a reference from `get()`. Futhermore, returning a reference limits the possible implementations of `MapObserver`, because it forces the borrow/reset to outlive the body of the method. * MapObserver: Replace `.get_mut()` with `.set(idx, val)` Like the previous commit, this is intended to expand the possible implementations of `MapObserver` to types with interior mutability, which can't necessarily loan out their content. * Make `RefCellValueObserver` into a safe `MapObserver` * as iter mut * as slice (mut): allow for non-& refs * nostd * CI round 1 * cleanup + AsSlice defs for RefCellValueObserver * clippy fixes * avoid unnecessary imports * whoops, too aggressive * use deref instead of as slice * whoops * fix as slice conditional importing in stable --------- Co-authored-by: Addison Crump <addison.crump@cispa.de>
This commit is contained in:
parent
28c43b332f
commit
b0248461e2
@ -165,7 +165,7 @@ where
|
||||
|
||||
// Store coverage, mapping coverage map indices to hit counts (if present) and the
|
||||
// associated seeds for the map indices with those hit counts.
|
||||
for (i, e) in obs.as_iter().copied().enumerate() {
|
||||
for (i, e) in obs.as_iter().map(|x| *x).enumerate() {
|
||||
if e != obs.initial() {
|
||||
cov_map
|
||||
.entry(i)
|
||||
|
@ -6,12 +6,14 @@ use core::simd::prelude::SimdOrd;
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
marker::PhantomData,
|
||||
ops::{BitAnd, BitOr},
|
||||
ops::{BitAnd, BitOr, Deref, DerefMut},
|
||||
};
|
||||
|
||||
#[rustversion::nightly]
|
||||
use libafl_bolts::AsSlice;
|
||||
use libafl_bolts::{
|
||||
tuples::{MatchNameRef, Reference, Referenceable},
|
||||
AsIter, AsSlice, AsSliceMut, HasRefCnt, Named,
|
||||
AsIter, HasRefCnt, Named,
|
||||
};
|
||||
use num_traits::PrimInt;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
@ -235,19 +237,18 @@ pub struct MapIndexesMetadata {
|
||||
|
||||
libafl_bolts::impl_serdeany!(MapIndexesMetadata);
|
||||
|
||||
impl AsSlice for MapIndexesMetadata {
|
||||
type Entry = usize;
|
||||
impl Deref for MapIndexesMetadata {
|
||||
type Target = [usize];
|
||||
/// Convert to a slice
|
||||
fn as_slice(&self) -> &[usize] {
|
||||
self.list.as_slice()
|
||||
fn deref(&self) -> &[usize] {
|
||||
&self.list
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSliceMut for MapIndexesMetadata {
|
||||
type Entry = usize;
|
||||
impl DerefMut for MapIndexesMetadata {
|
||||
/// Convert to a slice
|
||||
fn as_slice_mut(&mut self) -> &mut [usize] {
|
||||
self.list.as_slice_mut()
|
||||
fn deref_mut(&mut self) -> &mut [usize] {
|
||||
&mut self.list
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,21 +283,20 @@ pub struct MapNoveltiesMetadata {
|
||||
|
||||
libafl_bolts::impl_serdeany!(MapNoveltiesMetadata);
|
||||
|
||||
impl AsSlice for MapNoveltiesMetadata {
|
||||
type Entry = usize;
|
||||
impl Deref for MapNoveltiesMetadata {
|
||||
type Target = [usize];
|
||||
/// Convert to a slice
|
||||
#[must_use]
|
||||
fn as_slice(&self) -> &[usize] {
|
||||
self.list.as_slice()
|
||||
fn deref(&self) -> &[usize] {
|
||||
&self.list
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSliceMut for MapNoveltiesMetadata {
|
||||
type Entry = usize;
|
||||
impl DerefMut for MapNoveltiesMetadata {
|
||||
/// Convert to a slice
|
||||
#[must_use]
|
||||
fn as_slice_mut(&mut self) -> &mut [usize] {
|
||||
self.list.as_slice_mut()
|
||||
fn deref_mut(&mut self) -> &mut [usize] {
|
||||
&mut self.list
|
||||
}
|
||||
}
|
||||
|
||||
@ -469,13 +469,13 @@ where
|
||||
map_state.history_map.resize(len, observer.initial());
|
||||
}
|
||||
|
||||
let history_map = map_state.history_map.as_slice_mut();
|
||||
let history_map = &mut map_state.history_map;
|
||||
if C::INDICES {
|
||||
let mut indices = Vec::new();
|
||||
|
||||
for (i, value) in observer
|
||||
.as_iter()
|
||||
.copied()
|
||||
.map(|x| *x)
|
||||
.enumerate()
|
||||
.filter(|(_, value)| *value != initial)
|
||||
{
|
||||
@ -490,7 +490,7 @@ where
|
||||
} else {
|
||||
for (i, value) in observer
|
||||
.as_iter()
|
||||
.copied()
|
||||
.map(|x| *x)
|
||||
.enumerate()
|
||||
.filter(|(_, value)| *value != initial)
|
||||
{
|
||||
@ -539,8 +539,7 @@ where
|
||||
#[rustversion::nightly]
|
||||
impl<C, O, S> Feedback<S> for MapFeedback<C, DifferentIsNovel, O, MaxReducer, u8>
|
||||
where
|
||||
O: MapObserver<Entry = u8> + AsSlice<Entry = u8>,
|
||||
for<'it> O: AsIter<'it, Item = u8>,
|
||||
O: MapObserver<Entry = u8> + for<'a> AsSlice<'a, Entry = u8> + for<'a> AsIter<'a, Item = u8>,
|
||||
S: State + HasNamedMetadata,
|
||||
C: CanTrack + AsRef<O> + Observer<S>,
|
||||
{
|
||||
@ -756,7 +755,7 @@ where
|
||||
novelties.clear();
|
||||
for (i, item) in observer
|
||||
.as_iter()
|
||||
.copied()
|
||||
.map(|x| *x)
|
||||
.enumerate()
|
||||
.filter(|(_, item)| *item != initial)
|
||||
{
|
||||
@ -770,7 +769,7 @@ where
|
||||
} else {
|
||||
for (i, item) in observer
|
||||
.as_iter()
|
||||
.copied()
|
||||
.map(|x| *x)
|
||||
.enumerate()
|
||||
.filter(|(_, item)| *item != initial)
|
||||
{
|
||||
|
@ -4,12 +4,13 @@ use alloc::{borrow::Cow, vec::Vec};
|
||||
use core::{
|
||||
fmt::{self, Debug},
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use libafl_bolts::{
|
||||
rands::Rand,
|
||||
tuples::{tuple_list, tuple_list_type, Merge, NamedTuple},
|
||||
AsSlice, AsSliceMut, Named,
|
||||
Named,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -45,18 +46,16 @@ pub struct LogMutationMetadata {
|
||||
|
||||
libafl_bolts::impl_serdeany!(LogMutationMetadata);
|
||||
|
||||
impl AsSlice for LogMutationMetadata {
|
||||
type Entry = Cow<'static, str>;
|
||||
#[must_use]
|
||||
fn as_slice(&self) -> &[Cow<'static, str>] {
|
||||
self.list.as_slice()
|
||||
impl Deref for LogMutationMetadata {
|
||||
type Target = [Cow<'static, str>];
|
||||
fn deref(&self) -> &[Cow<'static, str>] {
|
||||
&self.list
|
||||
}
|
||||
}
|
||||
impl AsSliceMut for LogMutationMetadata {
|
||||
type Entry = Cow<'static, str>;
|
||||
impl DerefMut for LogMutationMetadata {
|
||||
#[must_use]
|
||||
fn as_slice_mut(&mut self) -> &mut [Cow<'static, str>] {
|
||||
self.list.as_slice_mut()
|
||||
fn deref_mut(&mut self) -> &mut [Cow<'static, str>] {
|
||||
&mut self.list
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use core::slice::from_raw_parts;
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
mem::size_of,
|
||||
ops::{Add, AddAssign},
|
||||
ops::{Add, AddAssign, Deref},
|
||||
slice::Iter,
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
@ -272,9 +272,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSlice for Tokens {
|
||||
type Entry = Vec<u8>;
|
||||
fn as_slice(&self) -> &[Vec<u8>] {
|
||||
impl Deref for Tokens {
|
||||
type Target = [Vec<u8>];
|
||||
fn deref(&self) -> &[Vec<u8>] {
|
||||
self.tokens()
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,15 @@
|
||||
//! The `CmpObserver` provides access to the logged values of CMP instructions
|
||||
|
||||
use alloc::{borrow::Cow, vec::Vec};
|
||||
use core::{fmt::Debug, marker::PhantomData};
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use c2rust_bitfields::BitfieldStruct;
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::{ownedref::OwnedRefMut, serdeany::SerdeAny, AsSlice, AsSliceMut, Named};
|
||||
use libafl_bolts::{ownedref::OwnedRefMut, serdeany::SerdeAny, Named};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
use crate::{executors::ExitKind, inputs::UsesInput, observers::Observer, Error, HasMetadata};
|
||||
@ -83,21 +87,16 @@ pub struct CmpValuesMetadata {
|
||||
|
||||
libafl_bolts::impl_serdeany!(CmpValuesMetadata);
|
||||
|
||||
impl AsSlice for CmpValuesMetadata {
|
||||
type Entry = CmpValues;
|
||||
/// Convert to a slice
|
||||
#[must_use]
|
||||
fn as_slice(&self) -> &[CmpValues] {
|
||||
self.list.as_slice()
|
||||
impl Deref for CmpValuesMetadata {
|
||||
type Target = [CmpValues];
|
||||
fn deref(&self) -> &[CmpValues] {
|
||||
&self.list
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSliceMut for CmpValuesMetadata {
|
||||
type Entry = CmpValues;
|
||||
/// Convert to a slice
|
||||
#[must_use]
|
||||
fn as_slice_mut(&mut self) -> &mut [CmpValues] {
|
||||
self.list.as_slice_mut()
|
||||
impl DerefMut for CmpValuesMetadata {
|
||||
fn deref_mut(&mut self) -> &mut [CmpValues] {
|
||||
&mut self.list
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ use core::{
|
||||
fmt::Debug,
|
||||
hash::{Hash, Hasher},
|
||||
iter::Flatten,
|
||||
marker::PhantomData,
|
||||
mem::size_of,
|
||||
ops::{Deref, DerefMut},
|
||||
slice::{self, Iter, IterMut},
|
||||
};
|
||||
|
||||
@ -414,10 +414,10 @@ pub trait MapObserver:
|
||||
type Entry: Bounded + PartialEq + Default + Copy + Debug + Hash + 'static;
|
||||
|
||||
/// Get the value at `idx`
|
||||
fn get(&self, idx: usize) -> &Self::Entry;
|
||||
fn get(&self, idx: usize) -> Self::Entry;
|
||||
|
||||
/// Get the value at `idx` (mutable)
|
||||
fn get_mut(&mut self, idx: usize) -> &mut Self::Entry;
|
||||
/// Set the value at `idx`
|
||||
fn set(&mut self, idx: usize, val: Self::Entry);
|
||||
|
||||
/// Get the number of usable entries in the map (all by default)
|
||||
fn usable_count(&self) -> usize;
|
||||
@ -459,64 +459,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A Simple iterator calling `MapObserver::get`
|
||||
#[derive(Debug)]
|
||||
pub struct MapObserverSimpleIterator<'a, O>
|
||||
where
|
||||
O: 'a + MapObserver,
|
||||
{
|
||||
index: usize,
|
||||
observer: *const O,
|
||||
phantom: PhantomData<&'a u8>,
|
||||
}
|
||||
|
||||
impl<'a, O> Iterator for MapObserverSimpleIterator<'a, O>
|
||||
where
|
||||
O: 'a + MapObserver,
|
||||
{
|
||||
type Item = &'a O::Entry;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
unsafe {
|
||||
if self.index >= self.observer.as_ref().unwrap().usable_count() {
|
||||
None
|
||||
} else {
|
||||
let i = self.index;
|
||||
self.index += 1;
|
||||
Some(self.observer.as_ref().unwrap().get(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Simple iterator calling `MapObserver::get_mut`
|
||||
#[derive(Debug)]
|
||||
pub struct MapObserverSimpleIteratorMut<'a, O>
|
||||
where
|
||||
O: 'a + MapObserver,
|
||||
{
|
||||
index: usize,
|
||||
observer: *mut O,
|
||||
phantom: PhantomData<&'a u8>,
|
||||
}
|
||||
|
||||
impl<'a, O> Iterator for MapObserverSimpleIteratorMut<'a, O>
|
||||
where
|
||||
O: 'a + MapObserver,
|
||||
{
|
||||
type Item = &'a O::Entry;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
unsafe {
|
||||
if self.index >= self.observer.as_ref().unwrap().usable_count() {
|
||||
None
|
||||
} else {
|
||||
let i = self.index;
|
||||
self.index += 1;
|
||||
Some(self.observer.as_mut().unwrap().get_mut(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The Map Observer retrieves the state of a map,
|
||||
/// that will get updated by the target.
|
||||
/// A well-known example is the AFL-Style coverage map.
|
||||
@ -585,48 +527,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T, const DIFFERENTIAL: bool> AsIter<'it> for StdMapObserver<'a, T, DIFFERENTIAL>
|
||||
where
|
||||
T: Bounded
|
||||
+ PartialEq
|
||||
+ Default
|
||||
+ Copy
|
||||
+ Hash
|
||||
+ 'static
|
||||
+ Serialize
|
||||
+ serde::de::DeserializeOwned
|
||||
+ Debug,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = Iter<'it, T>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
let cnt = self.usable_count();
|
||||
self.as_slice()[..cnt].iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T, const DIFFERENTIAL: bool> AsIterMut<'it> for StdMapObserver<'a, T, DIFFERENTIAL>
|
||||
where
|
||||
T: Bounded
|
||||
+ PartialEq
|
||||
+ Default
|
||||
+ Copy
|
||||
+ Hash
|
||||
+ 'static
|
||||
+ Serialize
|
||||
+ serde::de::DeserializeOwned
|
||||
+ Debug,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = IterMut<'it, T>;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
|
||||
let cnt = self.usable_count();
|
||||
self.as_slice_mut()[..cnt].iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T, const DIFFERENTIAL: bool> IntoIterator for &'it StdMapObserver<'a, T, DIFFERENTIAL>
|
||||
where
|
||||
T: Bounded
|
||||
@ -744,13 +644,12 @@ where
|
||||
type Entry = T;
|
||||
|
||||
#[inline]
|
||||
fn get(&self, pos: usize) -> &T {
|
||||
&self.as_slice()[pos]
|
||||
fn get(&self, pos: usize) -> T {
|
||||
self.as_slice()[pos]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut T {
|
||||
&mut self.as_slice_mut()[idx]
|
||||
fn set(&mut self, pos: usize, val: T) {
|
||||
self.map.as_slice_mut()[pos] = val;
|
||||
}
|
||||
|
||||
/// Count the set bytes in the map
|
||||
@ -829,27 +728,22 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const DIFFERENTIAL: bool> AsSlice for StdMapObserver<'a, T, DIFFERENTIAL>
|
||||
impl<'a, T, const DIFFERENTIAL: bool> Deref for StdMapObserver<'a, T, DIFFERENTIAL>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
type Entry = T;
|
||||
#[must_use]
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[T] {
|
||||
self.map.as_slice()
|
||||
type Target = [T];
|
||||
fn deref(&self) -> &[T] {
|
||||
&self.map
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const DIFFERENTIAL: bool> AsSliceMut for StdMapObserver<'a, T, DIFFERENTIAL>
|
||||
impl<'a, T, const DIFFERENTIAL: bool> DerefMut for StdMapObserver<'a, T, DIFFERENTIAL>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
type Entry = T;
|
||||
#[must_use]
|
||||
#[inline]
|
||||
fn as_slice_mut(&mut self) -> &mut [T] {
|
||||
self.map.as_slice_mut()
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
&mut self.map
|
||||
}
|
||||
}
|
||||
|
||||
@ -1114,48 +1008,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T, const N: usize> AsIter<'it> for ConstMapObserver<'a, T, N>
|
||||
where
|
||||
T: Bounded
|
||||
+ PartialEq
|
||||
+ Default
|
||||
+ Copy
|
||||
+ Hash
|
||||
+ 'static
|
||||
+ Serialize
|
||||
+ serde::de::DeserializeOwned
|
||||
+ Debug,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = Iter<'it, T>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
let cnt = self.usable_count();
|
||||
self.as_slice()[..cnt].iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T, const N: usize> AsIterMut<'it> for ConstMapObserver<'a, T, N>
|
||||
where
|
||||
T: Bounded
|
||||
+ PartialEq
|
||||
+ Default
|
||||
+ Copy
|
||||
+ Hash
|
||||
+ 'static
|
||||
+ Serialize
|
||||
+ serde::de::DeserializeOwned
|
||||
+ Debug,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = IterMut<'it, T>;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
|
||||
let cnt = self.usable_count();
|
||||
self.as_slice_mut()[..cnt].iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T, const N: usize> IntoIterator for &'it ConstMapObserver<'a, T, N>
|
||||
where
|
||||
T: Bounded
|
||||
@ -1276,13 +1128,13 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get(&self, idx: usize) -> &T {
|
||||
&self.as_slice()[idx]
|
||||
fn get(&self, idx: usize) -> T {
|
||||
self.as_slice()[idx]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut T {
|
||||
&mut self.as_slice_mut()[idx]
|
||||
fn set(&mut self, idx: usize, val: T) {
|
||||
self.map.as_slice_mut()[idx] = val;
|
||||
}
|
||||
|
||||
/// Count the set bytes in the map
|
||||
@ -1340,25 +1192,22 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> AsSlice for ConstMapObserver<'a, T, N>
|
||||
impl<'a, T, const N: usize> Deref for ConstMapObserver<'a, T, N>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
type Entry = T;
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[T] {
|
||||
self.map.as_slice()
|
||||
type Target = [T];
|
||||
fn deref(&self) -> &[T] {
|
||||
&self.map
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> AsSliceMut for ConstMapObserver<'a, T, N>
|
||||
impl<'a, T, const N: usize> DerefMut for ConstMapObserver<'a, T, N>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
type Entry = T;
|
||||
#[inline]
|
||||
fn as_slice_mut(&mut self) -> &mut [T] {
|
||||
self.map.as_slice_mut()
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
&mut self.map
|
||||
}
|
||||
}
|
||||
|
||||
@ -1459,52 +1308,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T> AsIter<'it> for VariableMapObserver<'a, T>
|
||||
where
|
||||
T: Bounded
|
||||
+ PartialEq
|
||||
+ Default
|
||||
+ Copy
|
||||
+ Hash
|
||||
+ 'static
|
||||
+ Serialize
|
||||
+ serde::de::DeserializeOwned
|
||||
+ Debug
|
||||
+ PartialEq
|
||||
+ Bounded,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = Iter<'it, T>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
let cnt = self.usable_count();
|
||||
self.as_slice()[..cnt].iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T> AsIterMut<'it> for VariableMapObserver<'a, T>
|
||||
where
|
||||
T: Bounded
|
||||
+ PartialEq
|
||||
+ Default
|
||||
+ Copy
|
||||
+ Hash
|
||||
+ 'static
|
||||
+ Serialize
|
||||
+ serde::de::DeserializeOwned
|
||||
+ Debug
|
||||
+ PartialEq
|
||||
+ Bounded,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = IterMut<'it, T>;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
|
||||
let cnt = self.usable_count();
|
||||
self.as_slice_mut()[..cnt].iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'it, T> IntoIterator for &'it VariableMapObserver<'a, T>
|
||||
where
|
||||
T: Bounded
|
||||
@ -1595,6 +1398,7 @@ where
|
||||
self.as_slice().hash(hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> AsRef<Self> for VariableMapObserver<'a, T>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + PartialEq + Bounded,
|
||||
@ -1639,12 +1443,12 @@ where
|
||||
*self.size.as_ref()
|
||||
}
|
||||
|
||||
fn get(&self, idx: usize) -> &T {
|
||||
&self.map.as_slice()[idx]
|
||||
fn get(&self, idx: usize) -> T {
|
||||
self.map.as_slice()[idx]
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, idx: usize) -> &mut T {
|
||||
&mut self.map.as_slice_mut()[idx]
|
||||
fn set(&mut self, idx: usize, val: T) {
|
||||
self.map.as_slice_mut()[idx] = val;
|
||||
}
|
||||
|
||||
/// Count the set bytes in the map
|
||||
@ -1697,7 +1501,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> AsSlice for VariableMapObserver<'a, T>
|
||||
impl<'a, T> Deref for VariableMapObserver<'a, T>
|
||||
where
|
||||
T: Bounded
|
||||
+ PartialEq
|
||||
@ -1711,15 +1515,14 @@ where
|
||||
+ PartialEq
|
||||
+ Bounded,
|
||||
{
|
||||
type Entry = T;
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[T] {
|
||||
type Target = [T];
|
||||
fn deref(&self) -> &[T] {
|
||||
let cnt = self.usable_count();
|
||||
&self.map.as_slice()[..cnt]
|
||||
&self.map[..cnt]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> AsSliceMut for VariableMapObserver<'a, T>
|
||||
impl<'a, T> DerefMut for VariableMapObserver<'a, T>
|
||||
where
|
||||
T: 'static
|
||||
+ Default
|
||||
@ -1731,11 +1534,9 @@ where
|
||||
+ PartialEq
|
||||
+ Bounded,
|
||||
{
|
||||
type Entry = T;
|
||||
#[inline]
|
||||
fn as_slice_mut(&mut self) -> &mut [T] {
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
let cnt = self.usable_count();
|
||||
&mut self.map.as_slice_mut()[..cnt]
|
||||
&mut self.map[..cnt]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1795,7 +1596,7 @@ where
|
||||
|
||||
impl<S, M> Observer<S> for HitcountsMapObserver<M>
|
||||
where
|
||||
M: MapObserver<Entry = u8> + Observer<S> + AsSliceMut<Entry = u8>,
|
||||
M: MapObserver<Entry = u8> + Observer<S> + for<'a> AsSliceMut<'a, Entry = u8>,
|
||||
S: UsesInput,
|
||||
{
|
||||
#[inline]
|
||||
@ -1811,7 +1612,7 @@ where
|
||||
input: &S::Input,
|
||||
exit_kind: &ExitKind,
|
||||
) -> Result<(), Error> {
|
||||
let map = self.as_slice_mut();
|
||||
let mut map = self.as_slice_mut();
|
||||
let mut len = map.len();
|
||||
let align_offset = map.as_ptr().align_offset(size_of::<u16>());
|
||||
|
||||
@ -1849,6 +1650,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
drop(map);
|
||||
|
||||
self.base.post_exec(state, input, exit_kind)
|
||||
}
|
||||
}
|
||||
@ -1908,13 +1711,13 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get(&self, idx: usize) -> &u8 {
|
||||
fn get(&self, idx: usize) -> u8 {
|
||||
self.base.get(idx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut u8 {
|
||||
self.base.get_mut(idx)
|
||||
fn set(&mut self, idx: usize, val: u8) {
|
||||
self.base.set(idx, val);
|
||||
}
|
||||
|
||||
/// Count the set bytes in the map
|
||||
@ -1950,24 +1753,26 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> AsSlice for HitcountsMapObserver<M>
|
||||
impl<'a, M> AsSlice<'a> for HitcountsMapObserver<M>
|
||||
where
|
||||
M: MapObserver + AsSlice,
|
||||
M: MapObserver + AsSlice<'a>,
|
||||
{
|
||||
type Entry = <M as AsSlice>::Entry;
|
||||
type Entry = <M as AsSlice<'a>>::Entry;
|
||||
type SliceRef = <M as AsSlice<'a>>::SliceRef;
|
||||
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[Self::Entry] {
|
||||
fn as_slice(&'a self) -> Self::SliceRef {
|
||||
self.base.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> AsSliceMut for HitcountsMapObserver<M>
|
||||
impl<'a, M> AsSliceMut<'a> for HitcountsMapObserver<M>
|
||||
where
|
||||
M: MapObserver + AsSliceMut,
|
||||
M: MapObserver + AsSliceMut<'a>,
|
||||
{
|
||||
type Entry = <M as AsSliceMut>::Entry;
|
||||
type SliceRefMut = <M as AsSliceMut<'a>>::SliceRefMut;
|
||||
#[inline]
|
||||
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
|
||||
fn as_slice_mut(&'a mut self) -> Self::SliceRefMut {
|
||||
self.base.as_slice_mut()
|
||||
}
|
||||
}
|
||||
@ -1983,30 +1788,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, M> AsIter<'it> for HitcountsMapObserver<M>
|
||||
where
|
||||
M: Named + Serialize + serde::de::DeserializeOwned + AsIter<'it, Item = u8>,
|
||||
{
|
||||
type Item = u8;
|
||||
type IntoIter = <M as AsIter<'it>>::IntoIter;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
self.base.as_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, M> AsIterMut<'it> for HitcountsMapObserver<M>
|
||||
where
|
||||
M: Named + Serialize + serde::de::DeserializeOwned + AsIterMut<'it, Item = u8>,
|
||||
{
|
||||
type Item = u8;
|
||||
type IntoIter = <M as AsIterMut<'it>>::IntoIter;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
|
||||
self.base.as_iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, M> IntoIterator for &'it HitcountsMapObserver<M>
|
||||
where
|
||||
M: Serialize + serde::de::DeserializeOwned,
|
||||
@ -2060,7 +1841,7 @@ where
|
||||
M: DifferentialObserver<OTA, OTB, S>
|
||||
+ MapObserver<Entry = u8>
|
||||
+ Serialize
|
||||
+ AsSliceMut<Entry = u8>,
|
||||
+ for<'a> AsSliceMut<'a, Entry = u8>,
|
||||
OTA: ObserversTuple<S>,
|
||||
OTB: ObserversTuple<S>,
|
||||
S: UsesInput,
|
||||
@ -2113,7 +1894,7 @@ where
|
||||
input: &S::Input,
|
||||
exit_kind: &ExitKind,
|
||||
) -> Result<(), Error> {
|
||||
for item in self.as_iter_mut() {
|
||||
for mut item in self.as_iter_mut() {
|
||||
*item = unsafe { *COUNT_CLASS_LOOKUP.get_unchecked((*item) as usize) };
|
||||
}
|
||||
|
||||
@ -2179,13 +1960,13 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get(&self, idx: usize) -> &u8 {
|
||||
fn get(&self, idx: usize) -> u8 {
|
||||
self.base.get(idx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut u8 {
|
||||
self.base.get_mut(idx)
|
||||
fn set(&mut self, idx: usize, val: u8) {
|
||||
self.base.set(idx, val);
|
||||
}
|
||||
|
||||
/// Count the set bytes in the map
|
||||
@ -2221,28 +2002,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> AsSlice for HitcountsIterableMapObserver<M>
|
||||
where
|
||||
M: MapObserver + AsSlice,
|
||||
{
|
||||
type Entry = <M as AsSlice>::Entry;
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[Self::Entry] {
|
||||
self.base.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> AsSliceMut for HitcountsIterableMapObserver<M>
|
||||
where
|
||||
M: MapObserver + AsSliceMut,
|
||||
{
|
||||
type Entry = <M as AsSliceMut>::Entry;
|
||||
#[inline]
|
||||
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
|
||||
self.base.as_slice_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> HitcountsIterableMapObserver<M>
|
||||
where
|
||||
M: Serialize + serde::de::DeserializeOwned,
|
||||
@ -2259,6 +2018,7 @@ where
|
||||
M: Named + Serialize + serde::de::DeserializeOwned + AsIter<'it, Item = u8>,
|
||||
{
|
||||
type Item = u8;
|
||||
type Ref = <M as AsIter<'it>>::Ref;
|
||||
type IntoIter = <M as AsIter<'it>>::IntoIter;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
@ -2270,10 +2030,10 @@ impl<'it, M> AsIterMut<'it> for HitcountsIterableMapObserver<M>
|
||||
where
|
||||
M: Named + Serialize + serde::de::DeserializeOwned + AsIterMut<'it, Item = u8>,
|
||||
{
|
||||
type Item = u8;
|
||||
type IntoIter = <M as AsIterMut<'it>>::IntoIter;
|
||||
type RefMut = <M as AsIterMut<'it>>::RefMut;
|
||||
type IntoIterMut = <M as AsIterMut<'it>>::IntoIterMut;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut {
|
||||
self.base.as_iter_mut()
|
||||
}
|
||||
}
|
||||
@ -2457,19 +2217,19 @@ where
|
||||
type Entry = T;
|
||||
|
||||
#[inline]
|
||||
fn get(&self, idx: usize) -> &T {
|
||||
fn get(&self, idx: usize) -> T {
|
||||
let elem = self.intervals.query(idx..=idx).next().unwrap();
|
||||
let i = *elem.value;
|
||||
let j = idx - elem.interval.start;
|
||||
&self.maps[i].as_slice()[j]
|
||||
self.maps[i].as_slice()[j]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut T {
|
||||
fn set(&mut self, idx: usize, val: Self::Entry) {
|
||||
let elem = self.intervals.query(idx..=idx).next().unwrap();
|
||||
let i = *elem.value;
|
||||
let j = idx - elem.interval.start;
|
||||
&mut self.maps[i].as_slice_mut()[j]
|
||||
self.maps[i].as_slice_mut()[j] = val;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -2513,7 +2273,7 @@ where
|
||||
let cnt = self.usable_count();
|
||||
let mut res = Vec::with_capacity(cnt);
|
||||
for i in 0..cnt {
|
||||
res.push(*self.get(i));
|
||||
res.push(self.get(i));
|
||||
}
|
||||
res
|
||||
}
|
||||
@ -2524,7 +2284,7 @@ where
|
||||
let cnt = self.usable_count();
|
||||
let mut res = 0;
|
||||
for i in indexes {
|
||||
if *i < cnt && *self.get(*i) != initial {
|
||||
if *i < cnt && self.get(*i) != initial {
|
||||
res += 1;
|
||||
}
|
||||
}
|
||||
@ -2611,6 +2371,7 @@ where
|
||||
'a: 'it,
|
||||
{
|
||||
type Item = T;
|
||||
type Ref = &'it T;
|
||||
type IntoIter = Flatten<Iter<'it, OwnedMutSlice<'a, T>>>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
@ -2623,10 +2384,10 @@ where
|
||||
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
'a: 'it,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = Flatten<IterMut<'it, OwnedMutSlice<'a, T>>>;
|
||||
type RefMut = &'it mut T;
|
||||
type IntoIterMut = Flatten<IterMut<'it, OwnedMutSlice<'a, T>>>;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut {
|
||||
self.maps.iter_mut().flatten()
|
||||
}
|
||||
}
|
||||
@ -2727,30 +2488,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, T> AsIter<'it> for OwnedMapObserver<T>
|
||||
where
|
||||
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = Iter<'it, T>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, T> AsIterMut<'it> for OwnedMapObserver<T>
|
||||
where
|
||||
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = IterMut<'it, T>;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
|
||||
self.as_slice_mut().iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, T> IntoIterator for &'it OwnedMapObserver<T>
|
||||
where
|
||||
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
@ -2833,13 +2570,13 @@ where
|
||||
type Entry = T;
|
||||
|
||||
#[inline]
|
||||
fn get(&self, pos: usize) -> &T {
|
||||
&self.as_slice()[pos]
|
||||
fn get(&self, pos: usize) -> T {
|
||||
self.as_slice()[pos]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut T {
|
||||
&mut self.as_slice_mut()[idx]
|
||||
fn set(&mut self, pos: usize, val: Self::Entry) {
|
||||
self.as_slice_mut()[pos] = val;
|
||||
}
|
||||
|
||||
/// Count the set bytes in the map
|
||||
@ -2901,27 +2638,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsSlice for OwnedMapObserver<T>
|
||||
impl<T> Deref for OwnedMapObserver<T>
|
||||
where
|
||||
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
type Entry = T;
|
||||
#[must_use]
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[T] {
|
||||
self.map.as_slice()
|
||||
type Target = [T];
|
||||
|
||||
fn deref(&self) -> &[T] {
|
||||
&self.map
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsSliceMut for OwnedMapObserver<T>
|
||||
impl<T> DerefMut for OwnedMapObserver<T>
|
||||
where
|
||||
T: 'static + Default + Copy + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
type Entry = T;
|
||||
#[must_use]
|
||||
#[inline]
|
||||
fn as_slice_mut(&mut self) -> &mut [T] {
|
||||
self.map.as_slice_mut()
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
&mut self.map
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
//! A simple observer with a single value.
|
||||
|
||||
use alloc::{borrow::Cow, boxed::Box};
|
||||
use alloc::{borrow::Cow, boxed::Box, vec::Vec};
|
||||
use core::{
|
||||
cell::{Ref, RefCell},
|
||||
cell::{Ref, RefCell, RefMut},
|
||||
fmt::Debug,
|
||||
hash::Hash,
|
||||
ops::Deref,
|
||||
hash::{Hash, Hasher},
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use ahash::RandomState;
|
||||
use libafl_bolts::{ownedref::OwnedRef, Named};
|
||||
use libafl_bolts::{ownedref::OwnedRef, AsIter, AsIterMut, AsSlice, AsSliceMut, Named};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::Observer;
|
||||
@ -100,21 +100,15 @@ where
|
||||
|
||||
/// A simple observer with a single [`RefCell`]'d value.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||
pub struct RefCellValueObserver<'a, T>
|
||||
where
|
||||
T: Debug + Serialize,
|
||||
{
|
||||
#[serde(bound = "T: serde::de::DeserializeOwned + serde::Serialize")]
|
||||
pub struct RefCellValueObserver<'a, T> {
|
||||
/// The name of this observer.
|
||||
name: Cow<'static, str>,
|
||||
/// The value.
|
||||
pub value: OwnedRef<'a, RefCell<T>>,
|
||||
}
|
||||
|
||||
impl<'a, T> RefCellValueObserver<'a, T>
|
||||
where
|
||||
T: Debug + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
impl<'a, T> RefCellValueObserver<'a, T> {
|
||||
/// Creates a new [`RefCellValueObserver`] with the given name.
|
||||
#[must_use]
|
||||
pub fn new(name: &'static str, value: OwnedRef<'a, RefCell<T>>) -> Self {
|
||||
@ -125,6 +119,8 @@ where
|
||||
}
|
||||
|
||||
/// Get a reference to the underlying value.
|
||||
///
|
||||
/// Panics if it can't borrow.
|
||||
#[must_use]
|
||||
pub fn get_ref<'b>(&'b self) -> Ref<'a, T>
|
||||
where
|
||||
@ -133,6 +129,17 @@ where
|
||||
self.value.as_ref().borrow()
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the underlying value.
|
||||
///
|
||||
/// Panics if it can't borrow.
|
||||
#[must_use]
|
||||
pub fn get_ref_mut<'b>(&'b self) -> RefMut<'a, T>
|
||||
where
|
||||
'b: 'a,
|
||||
{
|
||||
self.value.as_ref().borrow_mut()
|
||||
}
|
||||
|
||||
/// Set the value.
|
||||
pub fn set(&mut self, new_value: T) {
|
||||
self.value.as_ref().replace(new_value);
|
||||
@ -156,27 +163,246 @@ where
|
||||
impl<'a, S, T> Observer<S> for RefCellValueObserver<'a, T>
|
||||
where
|
||||
S: UsesInput,
|
||||
T: Debug + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Named for RefCellValueObserver<'a, T>
|
||||
where
|
||||
T: Debug + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
impl<'a, T> Named for RefCellValueObserver<'a, T> {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Hash> ObserverWithHashField for RefCellValueObserver<'a, T>
|
||||
impl<'a, T> ObserverWithHashField for RefCellValueObserver<'a, T>
|
||||
where
|
||||
T: Debug + Serialize + serde::de::DeserializeOwned,
|
||||
T: Hash,
|
||||
{
|
||||
fn hash(&self) -> Option<u64> {
|
||||
Some(RandomState::with_seeds(1, 2, 3, 4).hash_one(&*self.value.as_ref().borrow()))
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Iterator`] over [`RefCellValueObserver`] of a [`Deref`] to `[T]`.
|
||||
#[derive(Debug)]
|
||||
pub struct RefCellValueObserverIter<'it, T> {
|
||||
v: Ref<'it, [T]>,
|
||||
}
|
||||
|
||||
impl<'it, T: 'it, A: Deref<Target = [T]>> AsSlice<'it> for RefCellValueObserver<'_, A> {
|
||||
type Entry = T;
|
||||
type SliceRef = Ref<'it, [T]>;
|
||||
|
||||
fn as_slice(&'it self) -> Self::SliceRef {
|
||||
Ref::map(self.value.as_ref().borrow(), |s| &**s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, T: 'it, A: DerefMut<Target = [T]>> AsSliceMut<'it> for RefCellValueObserver<'_, A> {
|
||||
type SliceRefMut = RefMut<'it, [T]>;
|
||||
|
||||
fn as_slice_mut(&'it mut self) -> Self::SliceRefMut {
|
||||
RefMut::map(self.value.as_ref().borrow_mut(), |s| &mut **s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, T: 'it, A: Deref<Target = [T]>> AsIter<'it> for RefCellValueObserver<'_, A> {
|
||||
type Item = T;
|
||||
type Ref = Ref<'it, Self::Item>;
|
||||
type IntoIter = RefCellValueObserverIter<'it, T>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
Self::IntoIter {
|
||||
v: Ref::map(self.value.as_ref().borrow(), Deref::deref),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, T: 'it> Iterator for RefCellValueObserverIter<'it, T> {
|
||||
type Item = Ref<'it, T>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.v.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let cloned = Ref::clone(&self.v);
|
||||
let (next, remainder) = Ref::map_split(cloned, |v| (&v[0], &v[1..]));
|
||||
self.v = remainder;
|
||||
Some(next)
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Iterator`] over [`RefCellValueObserver`] of a [`DerefMut`] to `[T]`.
|
||||
#[derive(Debug)]
|
||||
pub struct RefCellValueObserverIterMut<'it, T> {
|
||||
v: Option<RefMut<'it, [T]>>,
|
||||
}
|
||||
|
||||
impl<'it, T: 'it, A: Debug + DerefMut<Target = [T]> + Serialize> AsIterMut<'it>
|
||||
for RefCellValueObserver<'_, A>
|
||||
{
|
||||
type RefMut = RefMut<'it, T>;
|
||||
type IntoIterMut = RefCellValueObserverIterMut<'it, T>;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut {
|
||||
Self::IntoIterMut {
|
||||
v: Some(RefMut::map(
|
||||
self.value.as_ref().borrow_mut(),
|
||||
DerefMut::deref_mut,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, T: 'it> Iterator for RefCellValueObserverIterMut<'it, T> {
|
||||
type Item = RefMut<'it, T>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(v) = self.v.take() {
|
||||
let next_slice = if v.len() > 1 {
|
||||
let (next, remainder) = RefMut::map_split(v, |v| v.split_at_mut(1));
|
||||
self.v = Some(remainder);
|
||||
next
|
||||
} else {
|
||||
v
|
||||
};
|
||||
Some(RefMut::map(next_slice, |v| &mut v[0]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Hash, A> Hash for RefCellValueObserver<'a, A>
|
||||
where
|
||||
T: Debug,
|
||||
A: Debug + Deref<Target = [T]> + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
(*self.get_ref()).hash(hasher);
|
||||
}
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
impl<T, A> libafl_bolts::HasLen for RefCellValueObserver<'_, A>
|
||||
where
|
||||
T: Debug,
|
||||
A: Debug + Deref<Target = [T]> + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
fn len(&self) -> usize {
|
||||
self.get_ref().len()
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
fn is_empty(&self) -> bool {
|
||||
self.get_ref().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug + Serialize + serde::de::DeserializeOwned> AsMut<Self>
|
||||
for RefCellValueObserver<'_, T>
|
||||
{
|
||||
fn as_mut(&mut self) -> &mut Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug + Serialize + serde::de::DeserializeOwned> AsRef<Self>
|
||||
for RefCellValueObserver<'_, T>
|
||||
{
|
||||
fn as_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> crate::observers::MapObserver for RefCellValueObserver<'_, A>
|
||||
where
|
||||
T: Copy + Debug + Default + Eq + Hash + num_traits::bounds::Bounded + 'static,
|
||||
A: Debug
|
||||
+ Default
|
||||
+ Deref<Target = [T]>
|
||||
+ DerefMut<Target = [T]>
|
||||
+ serde::de::DeserializeOwned
|
||||
+ Serialize
|
||||
+ 'static,
|
||||
{
|
||||
type Entry = T;
|
||||
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
fn get(&self, idx: usize) -> Self::Entry {
|
||||
self.get_ref()[idx]
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already borrowed (calls
|
||||
/// [`RefCell::borrow_mut`]).
|
||||
fn set(&mut self, idx: usize, val: Self::Entry) {
|
||||
self.get_ref_mut()[idx] = val;
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
fn hash_simple(&self) -> u64 {
|
||||
RandomState::with_seeds(0, 0, 0, 0).hash_one(self)
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
fn usable_count(&self) -> usize {
|
||||
self.get_ref().len()
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
fn count_bytes(&self) -> u64 {
|
||||
let default = Self::Entry::default();
|
||||
let mut count = 0;
|
||||
for entry in self.get_ref().iter() {
|
||||
if entry != &default {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already borrowed (calls
|
||||
/// [`RefCell::borrow_mut`]).
|
||||
fn reset_map(&mut self) -> Result<(), Error> {
|
||||
// This is less than optimal for `Vec`, for which we could use
|
||||
// `.clear()`. However, it makes the `impl` more general. Worth it?
|
||||
*self.get_ref_mut() = A::default();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
fn to_vec(&self) -> Vec<Self::Entry> {
|
||||
(*self.get_ref()).to_vec()
|
||||
}
|
||||
|
||||
/// Panics if the contained value is already mutably borrowed (calls
|
||||
/// [`RefCell::borrow`]).
|
||||
fn how_many_set(&self, indexes: &[usize]) -> usize {
|
||||
let default = Self::Entry::default();
|
||||
let mut count = 0;
|
||||
let arr = self.get_ref();
|
||||
for idx in indexes {
|
||||
if arr[*idx] != default {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
fn initial(&self) -> Self::Entry {
|
||||
Self::Entry::default()
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
//! Coverage accounting corpus scheduler, more details at <https://www.ndss-symposium.org/wp-content/uploads/2020/02/24422-paper.pdf>
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt::Debug;
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::{rands::Rand, AsSlice, AsSliceMut, HasLen, HasRefCnt};
|
||||
use libafl_bolts::{rands::Rand, HasLen, HasRefCnt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
@ -35,19 +38,15 @@ pub struct AccountingIndexesMetadata {
|
||||
|
||||
libafl_bolts::impl_serdeany!(AccountingIndexesMetadata);
|
||||
|
||||
impl AsSlice for AccountingIndexesMetadata {
|
||||
type Entry = usize;
|
||||
/// Convert to a slice
|
||||
fn as_slice(&self) -> &[usize] {
|
||||
self.list.as_slice()
|
||||
impl Deref for AccountingIndexesMetadata {
|
||||
type Target = [usize];
|
||||
fn deref(&self) -> &[usize] {
|
||||
&self.list
|
||||
}
|
||||
}
|
||||
impl AsSliceMut for AccountingIndexesMetadata {
|
||||
type Entry = usize;
|
||||
|
||||
/// Convert to a slice
|
||||
fn as_slice_mut(&mut self) -> &mut [usize] {
|
||||
self.list.as_slice_mut()
|
||||
impl DerefMut for AccountingIndexesMetadata {
|
||||
fn deref_mut(&mut self) -> &mut [usize] {
|
||||
&mut self.list
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use alloc::vec::Vec;
|
||||
use core::{any::type_name, cmp::Ordering, marker::PhantomData};
|
||||
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use libafl_bolts::{rands::Rand, serdeany::SerdeAny, AsSlice, HasRefCnt};
|
||||
use libafl_bolts::{rands::Rand, serdeany::SerdeAny, AsIter, HasRefCnt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
@ -89,7 +89,7 @@ impl<CS, F, M, O> RemovableScheduler for MinimizerScheduler<CS, F, M, O>
|
||||
where
|
||||
CS: RemovableScheduler,
|
||||
F: TestcaseScore<CS::State>,
|
||||
M: AsSlice<Entry = usize> + SerdeAny + HasRefCnt,
|
||||
M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt,
|
||||
CS::State: HasCorpus + HasMetadata + HasRand,
|
||||
O: CanTrack,
|
||||
{
|
||||
@ -130,13 +130,13 @@ where
|
||||
let factor = F::compute(state, &mut *old)?;
|
||||
if let Some(old_map) = old.metadata_map_mut().get_mut::<M>() {
|
||||
let mut e_iter = entries.iter();
|
||||
let mut map_iter = old_map.as_slice().iter(); // ASSERTION: guaranteed to be in order?
|
||||
let mut map_iter = old_map.as_iter(); // ASSERTION: guaranteed to be in order?
|
||||
|
||||
// manual set intersection
|
||||
let mut entry = e_iter.next();
|
||||
let mut map_entry = map_iter.next();
|
||||
while let Some(e) = entry {
|
||||
if let Some(me) = map_entry {
|
||||
if let Some(ref me) = map_entry {
|
||||
match e.cmp(me) {
|
||||
Ordering::Less => {
|
||||
entry = e_iter.next();
|
||||
@ -197,7 +197,7 @@ impl<CS, F, M, O> Scheduler for MinimizerScheduler<CS, F, M, O>
|
||||
where
|
||||
CS: Scheduler,
|
||||
F: TestcaseScore<CS::State>,
|
||||
M: AsSlice<Entry = usize> + SerdeAny + HasRefCnt,
|
||||
M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt,
|
||||
CS::State: HasCorpus + HasMetadata + HasRand,
|
||||
O: CanTrack,
|
||||
{
|
||||
@ -253,7 +253,7 @@ impl<CS, F, M, O> MinimizerScheduler<CS, F, M, O>
|
||||
where
|
||||
CS: Scheduler,
|
||||
F: TestcaseScore<CS::State>,
|
||||
M: AsSlice<Entry = usize> + SerdeAny + HasRefCnt,
|
||||
M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt,
|
||||
CS::State: HasCorpus + HasMetadata + HasRand,
|
||||
O: CanTrack,
|
||||
{
|
||||
@ -276,8 +276,8 @@ where
|
||||
))
|
||||
})?;
|
||||
let top_rateds = state.metadata_map().get::<TopRatedsMetadata>().unwrap();
|
||||
for elem in meta.as_slice() {
|
||||
if let Some(old_idx) = top_rateds.map.get(elem) {
|
||||
for elem in meta.as_iter() {
|
||||
if let Some(old_idx) = top_rateds.map.get(&*elem) {
|
||||
if *old_idx == idx {
|
||||
new_favoreds.push(*elem); // always retain current; we'll drop it later otherwise
|
||||
continue;
|
||||
@ -350,7 +350,7 @@ where
|
||||
type_name::<M>()
|
||||
))
|
||||
})?;
|
||||
for elem in meta.as_slice() {
|
||||
for elem in meta.as_iter() {
|
||||
acc.insert(*elem);
|
||||
}
|
||||
|
||||
|
@ -213,6 +213,7 @@ use core::{
|
||||
array::TryFromSliceError,
|
||||
fmt::{self, Display},
|
||||
num::{ParseIntError, TryFromIntError},
|
||||
ops::{Deref, DerefMut},
|
||||
time,
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
@ -674,68 +675,47 @@ pub trait IntoOwned {
|
||||
}
|
||||
|
||||
/// Can be converted to a slice
|
||||
pub trait AsSlice {
|
||||
/// Type of the entries in this slice
|
||||
type Entry;
|
||||
pub trait AsSlice<'a> {
|
||||
/// Type of the entries of this slice
|
||||
type Entry: 'a;
|
||||
/// Type of the reference to this slice
|
||||
type SliceRef: Deref<Target = [Self::Entry]>;
|
||||
|
||||
/// Convert to a slice
|
||||
fn as_slice(&self) -> &[Self::Entry];
|
||||
fn as_slice(&'a self) -> Self::SliceRef;
|
||||
}
|
||||
|
||||
impl<'a, T, R> AsSlice<'a> for R
|
||||
where
|
||||
T: 'a,
|
||||
R: Deref<Target = [T]>,
|
||||
{
|
||||
type Entry = T;
|
||||
type SliceRef = &'a [T];
|
||||
|
||||
fn as_slice(&'a self) -> Self::SliceRef {
|
||||
&*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Can be converted to a mutable slice
|
||||
pub trait AsSliceMut {
|
||||
/// Type of the entries in this mut slice
|
||||
type Entry;
|
||||
pub trait AsSliceMut<'a>: AsSlice<'a> {
|
||||
/// Type of the mutable reference to this slice
|
||||
type SliceRefMut: DerefMut<Target = [Self::Entry]>;
|
||||
|
||||
/// Convert to a slice
|
||||
fn as_slice_mut(&mut self) -> &mut [Self::Entry];
|
||||
fn as_slice_mut(&'a mut self) -> Self::SliceRefMut;
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T> AsSlice for Vec<T> {
|
||||
type Entry = T;
|
||||
impl<'a, T, R> AsSliceMut<'a> for R
|
||||
where
|
||||
T: 'a,
|
||||
R: DerefMut<Target = [T]>,
|
||||
{
|
||||
type SliceRefMut = &'a mut [T];
|
||||
|
||||
fn as_slice(&self) -> &[Self::Entry] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T> AsSliceMut for Vec<T> {
|
||||
type Entry = T;
|
||||
|
||||
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsSlice for &[T] {
|
||||
type Entry = T;
|
||||
|
||||
fn as_slice(&self) -> &[Self::Entry] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsSlice for [T] {
|
||||
type Entry = T;
|
||||
|
||||
fn as_slice(&self) -> &[Self::Entry] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsSliceMut for &mut [T] {
|
||||
type Entry = T;
|
||||
|
||||
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsSliceMut for [T] {
|
||||
type Entry = T;
|
||||
|
||||
fn as_slice_mut(&mut self) -> &mut [Self::Entry] {
|
||||
self
|
||||
fn as_slice_mut(&'a mut self) -> Self::SliceRefMut {
|
||||
&mut *self
|
||||
}
|
||||
}
|
||||
|
||||
@ -743,22 +723,51 @@ impl<T> AsSliceMut for [T] {
|
||||
pub trait AsIter<'it> {
|
||||
/// The item type
|
||||
type Item: 'it;
|
||||
/// The ref type
|
||||
type Ref: Deref<Target = Self::Item>;
|
||||
/// The iterator type
|
||||
type IntoIter: Iterator<Item = &'it Self::Item>;
|
||||
type IntoIter: Iterator<Item = Self::Ref>;
|
||||
|
||||
/// Create an iterator from &self
|
||||
fn as_iter(&'it self) -> Self::IntoIter;
|
||||
}
|
||||
|
||||
impl<'it, S, T> AsIter<'it> for S
|
||||
where
|
||||
S: AsSlice<'it, Entry = T, SliceRef = &'it [T]>,
|
||||
T: 'it,
|
||||
{
|
||||
type Item = S::Entry;
|
||||
type Ref = &'it Self::Item;
|
||||
type IntoIter = core::slice::Iter<'it, Self::Item>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an `Iterator` from a mutable reference
|
||||
pub trait AsIterMut<'it> {
|
||||
/// The item type
|
||||
type Item: 'it;
|
||||
pub trait AsIterMut<'it>: AsIter<'it> {
|
||||
/// The ref type
|
||||
type RefMut: DerefMut<Target = Self::Item>;
|
||||
/// The iterator type
|
||||
type IntoIter: Iterator<Item = &'it mut Self::Item>;
|
||||
type IntoIterMut: Iterator<Item = Self::RefMut>;
|
||||
|
||||
/// Create an iterator from &mut self
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter;
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut;
|
||||
}
|
||||
|
||||
impl<'it, S, T> AsIterMut<'it> for S
|
||||
where
|
||||
S: AsSliceMut<'it, Entry = T, SliceRef = &'it [T], SliceRefMut = &'it mut [T]>,
|
||||
T: 'it,
|
||||
{
|
||||
type RefMut = &'it mut Self::Item;
|
||||
type IntoIterMut = core::slice::IterMut<'it, Self::Item>;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut {
|
||||
self.as_slice_mut().iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// Has a length field
|
||||
|
@ -394,14 +394,14 @@ impl Listener {
|
||||
#[inline]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
unsafe fn shmem2page_mut<SHM: ShMem>(afl_shmem: &mut SHM) -> *mut LlmpPage {
|
||||
afl_shmem.as_slice_mut().as_mut_ptr() as *mut LlmpPage
|
||||
afl_shmem.as_mut_ptr() as *mut LlmpPage
|
||||
}
|
||||
|
||||
/// Get sharedmem from a page
|
||||
#[inline]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
unsafe fn shmem2page<SHM: ShMem>(afl_shmem: &SHM) -> *const LlmpPage {
|
||||
afl_shmem.as_slice().as_ptr() as *const LlmpPage
|
||||
afl_shmem.as_ptr() as *const LlmpPage
|
||||
}
|
||||
|
||||
/// Return, if a msg is contained in the current page
|
||||
@ -564,7 +564,7 @@ unsafe fn llmp_next_msg_ptr_checked<SHM: ShMem>(
|
||||
alloc_size: usize,
|
||||
) -> Result<*mut LlmpMsg, Error> {
|
||||
let page = map.page_mut();
|
||||
let map_size = map.shmem.as_slice().len();
|
||||
let map_size = map.shmem.len();
|
||||
let msg_begin_min = (page as *const u8).add(size_of::<LlmpPage>());
|
||||
// We still need space for this msg (alloc_size).
|
||||
let msg_begin_max = (page as *const u8).add(map_size - alloc_size);
|
||||
@ -662,7 +662,7 @@ impl LlmpMsg {
|
||||
/// Returns `true`, if the pointer is, indeed, in the page of this shared map.
|
||||
#[inline]
|
||||
pub fn in_shmem<SHM: ShMem>(&self, map: &mut LlmpSharedMap<SHM>) -> bool {
|
||||
let map_size = map.shmem.as_slice().len();
|
||||
let map_size = map.shmem.len();
|
||||
let buf_ptr = self.buf.as_ptr();
|
||||
let len = self.buf_len_padded as usize + size_of::<LlmpMsg>();
|
||||
unsafe {
|
||||
@ -1970,7 +1970,7 @@ where
|
||||
let offset = offset as usize;
|
||||
|
||||
let page = unsafe { self.page_mut() };
|
||||
let page_size = self.shmem.as_slice().len() - size_of::<LlmpPage>();
|
||||
let page_size = self.shmem.len() - size_of::<LlmpPage>();
|
||||
if offset > page_size {
|
||||
Err(Error::illegal_argument(format!(
|
||||
"Msg offset out of bounds (size: {page_size}, requested offset: {offset})"
|
||||
|
@ -10,7 +10,11 @@ use alloc::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{mem::ManuallyDrop, ptr::addr_of};
|
||||
use core::{
|
||||
mem::ManuallyDrop,
|
||||
ops::{Deref, DerefMut},
|
||||
ptr::addr_of,
|
||||
};
|
||||
#[cfg(target_vendor = "apple")]
|
||||
use std::fs;
|
||||
use std::{
|
||||
@ -40,7 +44,7 @@ use uds::{UnixListenerExt, UnixSocketAddr, UnixStreamExt};
|
||||
|
||||
use crate::{
|
||||
shmem::{ShMem, ShMemDescription, ShMemId, ShMemProvider},
|
||||
AsSlice, AsSliceMut, Error,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The default server name for our abstract shmem server
|
||||
@ -79,6 +83,26 @@ where
|
||||
server_fd: i32,
|
||||
}
|
||||
|
||||
impl<SH> Deref for ServedShMem<SH>
|
||||
where
|
||||
SH: ShMem,
|
||||
{
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<SH> DerefMut for ServedShMem<SH>
|
||||
where
|
||||
SH: ShMem,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<SH> ShMem for ServedShMem<SH>
|
||||
where
|
||||
SH: ShMem,
|
||||
@ -87,29 +111,6 @@ where
|
||||
let client_id = self.inner.id();
|
||||
ShMemId::from_string(&format!("{}:{client_id}", self.server_fd))
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<SH> AsSlice for ServedShMem<SH>
|
||||
where
|
||||
SH: ShMem,
|
||||
{
|
||||
type Entry = u8;
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
self.inner.as_slice()
|
||||
}
|
||||
}
|
||||
impl<SH> AsSliceMut for ServedShMem<SH>
|
||||
where
|
||||
SH: ShMem,
|
||||
{
|
||||
type Entry = u8;
|
||||
fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||
self.inner.as_slice_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<SP> ServedShMemProvider<SP>
|
||||
|
@ -6,7 +6,12 @@ use alloc::{
|
||||
slice::{Iter, IterMut},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{clone::Clone, fmt::Debug, slice};
|
||||
use core::{
|
||||
clone::Clone,
|
||||
fmt::Debug,
|
||||
ops::{Deref, DerefMut},
|
||||
slice,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
@ -455,11 +460,10 @@ impl<'a, T> From<OwnedMutSlice<'a, T>> for OwnedSlice<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Sized> AsSlice for OwnedSlice<'a, T> {
|
||||
type Entry = T;
|
||||
/// Get the [`OwnedSlice`] as slice.
|
||||
#[must_use]
|
||||
fn as_slice(&self) -> &[T] {
|
||||
impl<'a, T: Sized> Deref for OwnedSlice<'a, T> {
|
||||
type Target = [T];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match &self.inner {
|
||||
OwnedSliceInner::Ref(r) => r,
|
||||
OwnedSliceInner::RefRaw(rr, len, _) => unsafe { slice::from_raw_parts(*rr, *len) },
|
||||
@ -639,11 +643,10 @@ impl<'a, T: 'a + Sized> OwnedMutSlice<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Sized> AsSlice for OwnedMutSlice<'a, T> {
|
||||
type Entry = T;
|
||||
/// Get the value as slice
|
||||
#[must_use]
|
||||
fn as_slice(&self) -> &[T] {
|
||||
impl<'a, T: Sized> Deref for OwnedMutSlice<'a, T> {
|
||||
type Target = [T];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match &self.inner {
|
||||
OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe { slice::from_raw_parts(*rr, *len) },
|
||||
OwnedMutSliceInner::Ref(r) => r,
|
||||
@ -651,11 +654,9 @@ impl<'a, T: Sized> AsSlice 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_slice_mut(&mut self) -> &mut [T] {
|
||||
|
||||
impl<'a, T: Sized> DerefMut for OwnedMutSlice<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
match &mut self.inner {
|
||||
OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe {
|
||||
slice::from_raw_parts_mut(*rr, *len)
|
||||
|
@ -7,7 +7,11 @@ use alloc::{rc::Rc, string::ToString};
|
||||
use core::fmt::Display;
|
||||
#[cfg(feature = "alloc")]
|
||||
use core::{cell::RefCell, fmt, mem::ManuallyDrop};
|
||||
use core::{fmt::Debug, mem};
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
mem,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use std::env;
|
||||
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
||||
@ -31,7 +35,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::{AsSlice, AsSliceMut, Error};
|
||||
use crate::Error;
|
||||
|
||||
/// The standard sharedmem provider
|
||||
#[cfg(all(windows, feature = "std"))]
|
||||
@ -168,9 +172,10 @@ impl ShMemId {
|
||||
alloc::str::from_utf8(&self.id[..self.null_pos()]).unwrap()
|
||||
}
|
||||
}
|
||||
impl AsSlice for ShMemId {
|
||||
type Entry = u8;
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
|
||||
impl Deref for ShMemId {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.id
|
||||
}
|
||||
}
|
||||
@ -192,23 +197,15 @@ 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> + AsSliceMut<Entry = u8> {
|
||||
pub trait ShMem: Sized + Debug + Clone + DerefMut<Target = [u8]> {
|
||||
/// Get the id of this shared memory mapping
|
||||
fn id(&self) -> ShMemId;
|
||||
|
||||
/// Get the size of this mapping
|
||||
fn len(&self) -> usize;
|
||||
|
||||
/// Check if the mapping is empty
|
||||
fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Convert to a ptr of a given type, checking the size.
|
||||
/// If the map is too small, returns `None`
|
||||
fn as_ptr_of<T: Sized>(&self) -> Option<*const T> {
|
||||
if self.len() >= mem::size_of::<T>() {
|
||||
Some(self.as_slice().as_ptr() as *const T)
|
||||
Some(self.as_ptr() as *const T)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -218,7 +215,7 @@ pub trait ShMem: Sized + Debug + Clone + AsSlice<Entry = u8> + AsSliceMut<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_slice_mut().as_mut_ptr() as *mut T)
|
||||
Some(self.as_mut_ptr() as *mut T)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -339,31 +336,27 @@ where
|
||||
fn id(&self) -> ShMemId {
|
||||
self.internal.id()
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.internal.len()
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T> Deref for RcShMem<T>
|
||||
where
|
||||
T: ShMemProvider + Debug,
|
||||
{
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.internal
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T> AsSlice for RcShMem<T>
|
||||
impl<T> DerefMut for RcShMem<T>
|
||||
where
|
||||
T: ShMemProvider + Debug,
|
||||
{
|
||||
type Entry = u8;
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
self.internal.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T> AsSliceMut for RcShMem<T>
|
||||
where
|
||||
T: ShMemProvider + Debug,
|
||||
{
|
||||
type Entry = u8;
|
||||
fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||
self.internal.as_slice_mut()
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.internal
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,6 +555,13 @@ where
|
||||
/// Is needed on top.
|
||||
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
|
||||
pub mod unix_shmem {
|
||||
/// Mmap [`ShMem`] for Unix
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub use default::MmapShMem;
|
||||
/// Mmap [`ShMemProvider`] for Unix
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub use default::MmapShMemProvider;
|
||||
|
||||
#[cfg(doc)]
|
||||
use crate::shmem::{ShMem, ShMemProvider};
|
||||
|
||||
@ -578,18 +578,13 @@ pub mod unix_shmem {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub type UnixShMem = default::CommonUnixShMem;
|
||||
|
||||
/// Mmap [`ShMem`] for Unix
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub use default::MmapShMem;
|
||||
/// Mmap [`ShMemProvider`] for Unix
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub use default::MmapShMemProvider;
|
||||
|
||||
#[cfg(all(unix, feature = "std", not(target_os = "android")))]
|
||||
mod default {
|
||||
|
||||
use alloc::string::ToString;
|
||||
use core::{ptr, slice};
|
||||
use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
ptr, slice,
|
||||
};
|
||||
use std::{io::Write, process};
|
||||
|
||||
use libc::{
|
||||
@ -600,7 +595,7 @@ pub mod unix_shmem {
|
||||
use crate::{
|
||||
rands::{Rand, RandomSeed, StdRand},
|
||||
shmem::{ShMem, ShMemId, ShMemProvider},
|
||||
AsSlice, AsSliceMut, Error,
|
||||
Error,
|
||||
};
|
||||
|
||||
// This is macOS's limit
|
||||
@ -769,22 +764,18 @@ pub mod unix_shmem {
|
||||
fn id(&self) -> ShMemId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.map_size
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSlice for MmapShMem {
|
||||
type Entry = u8;
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
impl Deref for MmapShMem {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.map, self.map_size) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSliceMut for MmapShMem {
|
||||
type Entry = u8;
|
||||
fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||
impl DerefMut for MmapShMem {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(self.map, self.map_size) }
|
||||
}
|
||||
}
|
||||
@ -881,22 +872,18 @@ pub mod unix_shmem {
|
||||
fn id(&self) -> ShMemId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.map_size
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSlice for CommonUnixShMem {
|
||||
type Entry = u8;
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
impl Deref for CommonUnixShMem {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.map, self.map_size) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSliceMut for CommonUnixShMem {
|
||||
type Entry = u8;
|
||||
fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||
impl DerefMut for CommonUnixShMem {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(self.map, self.map_size) }
|
||||
}
|
||||
}
|
||||
@ -954,7 +941,10 @@ pub mod unix_shmem {
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
pub mod ashmem {
|
||||
use alloc::string::ToString;
|
||||
use core::{ptr, slice};
|
||||
use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
ptr, slice,
|
||||
};
|
||||
use std::ffi::CString;
|
||||
|
||||
use libc::{
|
||||
@ -964,7 +954,7 @@ pub mod unix_shmem {
|
||||
|
||||
use crate::{
|
||||
shmem::{ShMem, ShMemId, ShMemProvider},
|
||||
AsSlice, AsSliceMut, Error,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// An ashmem based impl for linux/android
|
||||
@ -1091,23 +1081,18 @@ pub mod unix_shmem {
|
||||
fn id(&self) -> ShMemId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.map_size
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSlice for AshmemShMem {
|
||||
type Entry = u8;
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
impl Deref for AshmemShMem {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.map, self.map_size) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSliceMut for AshmemShMem {
|
||||
type Entry = u8;
|
||||
|
||||
fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||
impl DerefMut for AshmemShMem {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(self.map, self.map_size) }
|
||||
}
|
||||
}
|
||||
@ -1177,23 +1162,15 @@ pub mod unix_shmem {
|
||||
/// Then `win32` implementation for shared memory.
|
||||
#[cfg(all(feature = "std", windows))]
|
||||
pub mod win32_shmem {
|
||||
|
||||
use alloc::string::String;
|
||||
use core::{
|
||||
ffi::c_void,
|
||||
fmt::{self, Debug, Formatter},
|
||||
ops::{Deref, DerefMut},
|
||||
slice,
|
||||
};
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
shmem::{ShMem, ShMemId, ShMemProvider},
|
||||
AsSlice, AsSliceMut, Error,
|
||||
};
|
||||
|
||||
const INVALID_HANDLE_VALUE: isize = -1;
|
||||
|
||||
use windows::{
|
||||
core::PCSTR,
|
||||
Win32::{
|
||||
@ -1205,6 +1182,13 @@ pub mod win32_shmem {
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
shmem::{ShMem, ShMemId, ShMemProvider},
|
||||
Error,
|
||||
};
|
||||
|
||||
const INVALID_HANDLE_VALUE: isize = -1;
|
||||
|
||||
/// The default [`ShMem`] impl for Windows using `shmctl` & `shmget`
|
||||
#[derive(Clone)]
|
||||
pub struct Win32ShMem {
|
||||
@ -1291,21 +1275,16 @@ pub mod win32_shmem {
|
||||
fn id(&self) -> ShMemId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.map_size
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSlice for Win32ShMem {
|
||||
type Entry = u8;
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
impl Deref for Win32ShMem {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.map, self.map_size) }
|
||||
}
|
||||
}
|
||||
impl AsSliceMut for Win32ShMem {
|
||||
type Entry = u8;
|
||||
fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||
impl DerefMut for Win32ShMem {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(self.map, self.map_size) }
|
||||
}
|
||||
}
|
||||
@ -1395,6 +1374,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] {
|
||||
use crate::AsSliceMut;
|
||||
&mut (self.inner.as_slice_mut()[self.pos..])
|
||||
}
|
||||
}
|
||||
@ -1442,6 +1422,7 @@ impl<T: ShMem> std::io::Seek for ShMemCursor<T> {
|
||||
let effective_new_pos = match pos {
|
||||
std::io::SeekFrom::Start(s) => s,
|
||||
std::io::SeekFrom::End(offset) => {
|
||||
use crate::AsSlice;
|
||||
let map_len = self.inner.as_slice().len();
|
||||
let signed_pos = i64::try_from(map_len).unwrap();
|
||||
let effective = signed_pos.checked_add(offset).unwrap();
|
||||
|
@ -195,9 +195,7 @@ where
|
||||
// # Safety
|
||||
// The index is modulo by the length, therefore it is always in bounds
|
||||
let len = self.hitcounts_map.len();
|
||||
self.hitcounts_map
|
||||
.as_slice_mut()
|
||||
.get_unchecked_mut(hash % len)
|
||||
self.hitcounts_map.get_unchecked_mut(hash % len)
|
||||
};
|
||||
*val = val.saturating_add(1);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use std::{
|
||||
borrow::Cow,
|
||||
fmt::Debug,
|
||||
hash::{Hash, Hasher},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use ahash::AHasher;
|
||||
@ -107,16 +108,16 @@ where
|
||||
{
|
||||
type Entry = O::ValueType;
|
||||
|
||||
fn get(&self, idx: usize) -> &Self::Entry {
|
||||
fn get(&self, idx: usize) -> Self::Entry {
|
||||
let initial = self.inner.initial();
|
||||
if *self.inner.get(idx) == initial {
|
||||
self.value_observer.default_value()
|
||||
if self.inner.get(idx) == initial {
|
||||
*self.value_observer.default_value()
|
||||
} else {
|
||||
self.value_observer.value()
|
||||
*self.value_observer.value()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, _idx: usize) -> &mut Self::Entry {
|
||||
fn set(&mut self, _idx: usize, _val: Self::Entry) {
|
||||
unimplemented!("Impossible to implement for a proxy map.")
|
||||
}
|
||||
|
||||
@ -148,7 +149,7 @@ where
|
||||
let value = *self.value_observer.value();
|
||||
self.inner
|
||||
.as_iter()
|
||||
.map(|&e| if e == initial { default } else { value })
|
||||
.map(|e| if *e == initial { default } else { value })
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -202,9 +203,10 @@ impl<'it, I, O, T> MappedEdgeMapIter<'it, I, O, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it, I, O, T> Iterator for MappedEdgeMapIter<'it, I, O, T>
|
||||
impl<'it, I, O, R, T> Iterator for MappedEdgeMapIter<'it, I, O, T>
|
||||
where
|
||||
I: Iterator<Item = &'it T>,
|
||||
I: Iterator<Item = R>,
|
||||
R: Deref<Target = T>,
|
||||
T: PartialEq + 'it,
|
||||
O: ValueObserver,
|
||||
{
|
||||
@ -225,6 +227,7 @@ where
|
||||
O: ValueObserver + 'it,
|
||||
{
|
||||
type Item = O::ValueType;
|
||||
type Ref = &'it Self::Item;
|
||||
type IntoIter = MappedEdgeMapIter<'it, <M as AsIter<'it>>::IntoIter, O, M::Entry>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
|
@ -185,19 +185,19 @@ mod observers {
|
||||
type Entry = u8;
|
||||
|
||||
#[inline]
|
||||
fn get(&self, idx: usize) -> &u8 {
|
||||
fn get(&self, idx: usize) -> u8 {
|
||||
let elem = self.intervals.query(idx..=idx).next().unwrap();
|
||||
let i = elem.value;
|
||||
let j = idx - elem.interval.start;
|
||||
unsafe { &(*addr_of!(COUNTERS_MAPS[*i])).as_slice()[j] }
|
||||
unsafe { (*addr_of!(COUNTERS_MAPS[*i])).as_slice()[j] }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut u8 {
|
||||
fn set(&mut self, idx: usize, val: u8) {
|
||||
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_slice_mut()[j] }
|
||||
unsafe { (*addr_of_mut!(COUNTERS_MAPS[*i])).as_slice_mut()[j] = val };
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -241,7 +241,7 @@ mod observers {
|
||||
let cnt = self.usable_count();
|
||||
let mut res = Vec::with_capacity(cnt);
|
||||
for i in 0..cnt {
|
||||
res.push(*self.get(i));
|
||||
res.push(self.get(i));
|
||||
}
|
||||
res
|
||||
}
|
||||
@ -252,7 +252,7 @@ mod observers {
|
||||
let cnt = self.usable_count();
|
||||
let mut res = 0;
|
||||
for i in indexes {
|
||||
if *i < cnt && *self.get(*i) != initial {
|
||||
if *i < cnt && self.get(*i) != initial {
|
||||
res += 1;
|
||||
}
|
||||
}
|
||||
@ -322,6 +322,7 @@ mod observers {
|
||||
|
||||
impl<'it, const DIFFERENTIAL: bool> AsIter<'it> for CountersMultiMapObserver<DIFFERENTIAL> {
|
||||
type Item = u8;
|
||||
type Ref = &'it Self::Item;
|
||||
type IntoIter = Flatten<Iter<'it, OwnedMutSlice<'static, u8>>>;
|
||||
|
||||
fn as_iter(&'it self) -> Self::IntoIter {
|
||||
@ -330,10 +331,10 @@ mod observers {
|
||||
}
|
||||
|
||||
impl<'it, const DIFFERENTIAL: bool> AsIterMut<'it> for CountersMultiMapObserver<DIFFERENTIAL> {
|
||||
type Item = u8;
|
||||
type IntoIter = Flatten<IterMut<'it, OwnedMutSlice<'static, u8>>>;
|
||||
type RefMut = &'it mut Self::Item;
|
||||
type IntoIterMut = Flatten<IterMut<'it, OwnedMutSlice<'static, u8>>>;
|
||||
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIter {
|
||||
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut {
|
||||
unsafe { COUNTERS_MAPS.iter_mut().flatten() }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user