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:
Langston Barrett 2024-04-27 12:36:56 -04:00 committed by GitHub
parent 28c43b332f
commit b0248461e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 620 additions and 671 deletions

View File

@ -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)

View File

@ -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)
{

View File

@ -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
}
}

View File

@ -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()
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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()
}
}

View File

@ -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
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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})"

View File

@ -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>

View File

@ -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)

View File

@ -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();

View File

@ -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);
}

View File

@ -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 {

View File

@ -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() }
}
}