Add OwnedSlice::RefRaw to keep track of raw pointers (#448)

* add OwnedSlice::RefRaw to keep track of raw pointers

* clippy

* fmt

* new from ownedref

* clippy

* OwnedSliceInner

* fix,From

* as_slice()

* fmt

* fix doc

* OwnedSliceMut

* fixes

* clippy

* fix

* ownedmut -> owned

* to owned

* to_owned -> clone

* removed comment

Co-authored-by: tokatoka <tokazerkje@outlook.com>
This commit is contained in:
Dominik Maier 2022-01-05 01:15:23 +01:00 committed by GitHub
parent 6d9763c51f
commit 30eb1508de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 259 additions and 62 deletions

View File

@ -216,8 +216,13 @@ pub fn LLVMFuzzerRunDriver(
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut mgr, _core_id| { let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut mgr, _core_id| {
// Create an observation channel using the coverage map // Create an observation channel using the coverage map
let edges = unsafe { slice::from_raw_parts_mut(EDGES_MAP_PTR, MAX_EDGES_NUM) }; let edges_observer = unsafe {
let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges)); HitcountsMapObserver::new(StdMapObserver::new_from_ptr(
"edges",
EDGES_MAP_PTR,
MAX_EDGES_NUM,
))
};
// Create an observation channel to keep track of the execution time // Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time"); let time_observer = TimeObserver::new("time");

View File

@ -144,8 +144,9 @@ pub fn libafl_main() {
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr, _core_id| { let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr, _core_id| {
// Create an observation channel using the coverage map // Create an observation channel using the coverage map
let edges = edges_map_from_ptr(); let edges = unsafe { edges_map_from_ptr() };
let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges)); let edges_observer =
HitcountsMapObserver::new(StdMapObserver::new_from_ownedref("edges", edges));
// Create an observation channel to keep track of the execution time // Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time"); let time_observer = TimeObserver::new("time");

View File

@ -61,7 +61,7 @@ impl HasTargetBytes for PacketData {
fn target_bytes(&self) -> OwnedSlice<u8> { fn target_bytes(&self) -> OwnedSlice<u8> {
let mut serialized_data = Vec::with_capacity(self.serialized_size()); let mut serialized_data = Vec::with_capacity(self.serialized_size());
self.binary_serialize::<_, LittleEndian>(&mut serialized_data); self.binary_serialize::<_, LittleEndian>(&mut serialized_data);
OwnedSlice::Owned(serialized_data) OwnedSlice::from(serialized_data)
} }
} }

View File

@ -2,7 +2,7 @@
// The serialization is towards owned, allowing to serialize pointers without troubles. // The serialization is towards owned, allowing to serialize pointers without troubles.
use alloc::{boxed::Box, vec::Vec}; use alloc::{boxed::Box, vec::Vec};
use core::{clone::Clone, fmt::Debug}; use core::{clone::Clone, fmt::Debug, slice};
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// Trait to convert into an Owned type /// Trait to convert into an Owned type
@ -166,26 +166,31 @@ where
/// Wrap a slice and convert to a Vec on serialize /// Wrap a slice and convert to a Vec on serialize
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum OwnedSlice<'a, T: 'a + Sized> { enum OwnedSliceInner<'a, T: 'a + Sized> {
/// A ref to a raw slice and length
RefRaw(*const T, usize),
/// A ref to a slice /// A ref to a slice
Ref(&'a [T]), Ref(&'a [T]),
/// A ref to an owned [`Vec`] /// A ref to an owned [`Vec`]
Owned(Vec<T>), Owned(Vec<T>),
} }
impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSlice<'a, T> { impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSliceInner<'a, T> {
fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
{ {
match self { match self {
OwnedSlice::Ref(r) => r.serialize(se), OwnedSliceInner::RefRaw(rr, len) => unsafe {
OwnedSlice::Owned(b) => b.serialize(se), slice::from_raw_parts(*rr, *len).serialize(se)
},
OwnedSliceInner::Ref(r) => r.serialize(se),
OwnedSliceInner::Owned(b) => b.serialize(se),
} }
} }
} }
impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for OwnedSlice<'a, T> impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for OwnedSliceInner<'a, T>
where where
Vec<T>: Deserialize<'de>, Vec<T>: Deserialize<'de>,
{ {
@ -193,7 +198,79 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
Deserialize::deserialize(deserializer).map(OwnedSlice::Owned) Deserialize::deserialize(deserializer).map(OwnedSliceInner::Owned)
}
}
/// Wrap a slice and convert to a Vec on serialize
/// We use a hidden inner enum so the public API can be safe,
/// unless the user uses the unsafe [`OwnedSlice::from_raw_parts`]
#[allow(clippy::unsafe_derive_deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct OwnedSlice<'a, T: 'a + Sized> {
inner: OwnedSliceInner<'a, T>,
}
impl<'a, T: 'a + Clone> Clone for OwnedSlice<'a, T> {
fn clone(&self) -> Self {
Self {
inner: OwnedSliceInner::Owned(self.as_slice().to_vec()),
}
}
}
impl<'a, T> OwnedSlice<'a, T> {
/// Create a new [`OwnedSlice`] from a raw pointer and length
///
/// # Safety
///
/// The pointer must be valid and point to a map of the size `size_of<T>() * len`
/// The contents will be dereferenced in subsequent operations.
#[must_use]
pub unsafe fn from_raw_parts(ptr: *const T, len: usize) -> Self {
Self {
inner: OwnedSliceInner::RefRaw(ptr, len),
}
}
}
/// Create a new [`OwnedSlice`] from a vector
impl<'a, T> From<Vec<T>> for OwnedSlice<'a, T> {
fn from(vec: Vec<T>) -> Self {
Self {
inner: OwnedSliceInner::Owned(vec),
}
}
}
/// Create a new [`OwnedSlice`] from a vector reference
impl<'a, T> From<&'a Vec<T>> for OwnedSlice<'a, T> {
fn from(vec: &'a Vec<T>) -> Self {
Self {
inner: OwnedSliceInner::Ref(vec),
}
}
}
/// Create a new [`OwnedSlice`] from a reference to a slice
impl<'a, T> From<&'a [T]> for OwnedSlice<'a, T> {
fn from(r: &'a [T]) -> Self {
Self {
inner: OwnedSliceInner::Ref(r),
}
}
}
/// Create a new [`OwnedSlice`] from a [`OwnedSliceMut`]
impl<'a, T> From<OwnedSliceMut<'a, T>> for OwnedSlice<'a, T> {
fn from(mut_slice: OwnedSliceMut<'a, T>) -> Self {
Self {
inner: match mut_slice.inner {
OwnedSliceMutInner::RefRaw(ptr, len) => OwnedSliceInner::RefRaw(ptr as _, len),
OwnedSliceMutInner::Ref(r) => OwnedSliceInner::Ref(r as _),
OwnedSliceMutInner::Owned(v) => OwnedSliceInner::Owned(v),
},
}
} }
} }
@ -201,9 +278,10 @@ impl<'a, T: Sized> OwnedSlice<'a, T> {
/// Get the [`OwnedSlice`] as slice. /// Get the [`OwnedSlice`] as slice.
#[must_use] #[must_use]
pub fn as_slice(&self) -> &[T] { pub fn as_slice(&self) -> &[T] {
match self { match &self.inner {
OwnedSlice::Ref(r) => r, OwnedSliceInner::Ref(r) => r,
OwnedSlice::Owned(v) => v.as_slice(), OwnedSliceInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts(*rr, *len) },
OwnedSliceInner::Owned(v) => v.as_slice(),
} }
} }
} }
@ -214,43 +292,57 @@ where
{ {
#[must_use] #[must_use]
fn is_owned(&self) -> bool { fn is_owned(&self) -> bool {
match self { match self.inner {
OwnedSlice::Ref(_) => false, OwnedSliceInner::RefRaw(_, _) | OwnedSliceInner::Ref(_) => false,
OwnedSlice::Owned(_) => true, OwnedSliceInner::Owned(_) => true,
} }
} }
#[must_use] #[must_use]
fn into_owned(self) -> Self { fn into_owned(self) -> Self {
match self { match self.inner {
OwnedSlice::Ref(r) => OwnedSlice::Owned(r.to_vec()), OwnedSliceInner::RefRaw(rr, len) => Self {
OwnedSlice::Owned(v) => OwnedSlice::Owned(v), inner: OwnedSliceInner::Owned(unsafe { slice::from_raw_parts(rr, len).to_vec() }),
},
OwnedSliceInner::Ref(r) => Self {
inner: OwnedSliceInner::Owned(r.to_vec()),
},
OwnedSliceInner::Owned(v) => Self {
inner: OwnedSliceInner::Owned(v),
},
} }
} }
} }
/// Wrap a mutable slice and convert to a Vec on serialize /// Wrap a mutable slice and convert to a Vec on serialize
/// We use a hidden inner enum so the public API can be safe,
/// unless the user uses the unsafe [`OwnedSliceMut::from_raw_parts_mut`]
#[derive(Debug)] #[derive(Debug)]
pub enum OwnedSliceMut<'a, T: 'a + Sized> { pub enum OwnedSliceMutInner<'a, T: 'a + Sized> {
/// A raw ptr to a memory location and a length
RefRaw(*mut T, usize),
/// A ptr to a mutable slice of the type /// A ptr to a mutable slice of the type
Ref(&'a mut [T]), Ref(&'a mut [T]),
/// An owned [`Vec`] of the type /// An owned [`Vec`] of the type
Owned(Vec<T>), Owned(Vec<T>),
} }
impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSliceMut<'a, T> { impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSliceMutInner<'a, T> {
fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
{ {
match self { match self {
OwnedSliceMut::Ref(r) => r.serialize(se), OwnedSliceMutInner::RefRaw(rr, len) => {
OwnedSliceMut::Owned(b) => b.serialize(se), unsafe { slice::from_raw_parts_mut(*rr, *len) }.serialize(se)
}
OwnedSliceMutInner::Ref(r) => r.serialize(se),
OwnedSliceMutInner::Owned(b) => b.serialize(se),
} }
} }
} }
impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for OwnedSliceMut<'a, T> impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for OwnedSliceMutInner<'a, T>
where where
Vec<T>: Deserialize<'de>, Vec<T>: Deserialize<'de>,
{ {
@ -258,7 +350,35 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
Deserialize::deserialize(deserializer).map(OwnedSliceMut::Owned) Deserialize::deserialize(deserializer).map(OwnedSliceMutInner::Owned)
}
}
/// Wrap a mutable slice and convert to a Vec on serialize
#[allow(clippy::unsafe_derive_deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct OwnedSliceMut<'a, T: 'a + Sized> {
inner: OwnedSliceMutInner<'a, T>,
}
impl<'a, T: 'a + Sized> OwnedSliceMut<'a, T> {
/// Create a new [`OwnedSliceMut`] from a raw pointer and length
///
/// # Safety
///
/// The pointer must be valid and point to a map of the size `size_of<T>() * len`
/// The contents will be dereferenced in subsequent operations.
#[must_use]
pub unsafe fn from_raw_parts_mut(ptr: *mut T, len: usize) -> OwnedSliceMut<'a, T> {
if ptr.is_null() || len == 0 {
Self {
inner: OwnedSliceMutInner::Owned(Vec::new()),
}
} else {
Self {
inner: OwnedSliceMutInner::RefRaw(ptr, len),
}
}
} }
} }
@ -266,18 +386,20 @@ impl<'a, T: Sized> OwnedSliceMut<'a, T> {
/// Get the value as slice /// Get the value as slice
#[must_use] #[must_use]
pub fn as_slice(&self) -> &[T] { pub fn as_slice(&self) -> &[T] {
match self { match &self.inner {
OwnedSliceMut::Ref(r) => r, OwnedSliceMutInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts(*rr, *len) },
OwnedSliceMut::Owned(v) => v.as_slice(), OwnedSliceMutInner::Ref(r) => r,
OwnedSliceMutInner::Owned(v) => v.as_slice(),
} }
} }
/// Get the value as mut slice /// Get the value as mut slice
#[must_use] #[must_use]
pub fn as_mut_slice(&mut self) -> &mut [T] { pub fn as_mut_slice(&mut self) -> &mut [T] {
match self { match &mut self.inner {
OwnedSliceMut::Ref(r) => r, OwnedSliceMutInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts_mut(*rr, *len) },
OwnedSliceMut::Owned(v) => v.as_mut_slice(), OwnedSliceMutInner::Ref(r) => r,
OwnedSliceMutInner::Owned(v) => v.as_mut_slice(),
} }
} }
} }
@ -288,17 +410,68 @@ where
{ {
#[must_use] #[must_use]
fn is_owned(&self) -> bool { fn is_owned(&self) -> bool {
match self { match self.inner {
OwnedSliceMut::Ref(_) => false, OwnedSliceMutInner::RefRaw(_, _) | OwnedSliceMutInner::Ref(_) => false,
OwnedSliceMut::Owned(_) => true, OwnedSliceMutInner::Owned(_) => true,
} }
} }
#[must_use] #[must_use]
fn into_owned(self) -> Self { fn into_owned(self) -> Self {
match self { let vec = match self.inner {
OwnedSliceMut::Ref(r) => OwnedSliceMut::Owned(r.to_vec()), OwnedSliceMutInner::RefRaw(rr, len) => unsafe {
OwnedSliceMut::Owned(v) => OwnedSliceMut::Owned(v), slice::from_raw_parts_mut(rr, len).to_vec()
},
OwnedSliceMutInner::Ref(r) => r.to_vec(),
OwnedSliceMutInner::Owned(v) => v,
};
Self {
inner: OwnedSliceMutInner::Owned(vec),
}
}
}
impl<'a, T: 'a + Clone> Clone for OwnedSliceMut<'a, T> {
fn clone(&self) -> Self {
Self {
inner: OwnedSliceMutInner::Owned(self.as_slice().to_vec()),
}
}
}
/// Create a new [`OwnedSliceMut`] from a vector
impl<'a, T> From<Vec<T>> for OwnedSliceMut<'a, T> {
fn from(vec: Vec<T>) -> Self {
Self {
inner: OwnedSliceMutInner::Owned(vec),
}
}
}
/// Create a new [`OwnedSliceMut`] from a vector reference
impl<'a, T> From<&'a mut Vec<T>> for OwnedSliceMut<'a, T> {
fn from(vec: &'a mut Vec<T>) -> Self {
Self {
inner: OwnedSliceMutInner::Ref(vec),
}
}
}
/// Create a new [`OwnedSliceMut`] from a reference to ref to a slice
impl<'a, T> From<&'a mut [T]> for OwnedSliceMut<'a, T> {
fn from(r: &'a mut [T]) -> Self {
Self {
inner: OwnedSliceMutInner::Ref(r),
}
}
}
/// Create a new [`OwnedSliceMut`] from a reference to ref to a slice
#[allow(clippy::mut_mut)] // This makes use in some iterators easier
impl<'a, T> From<&'a mut &'a mut [T]> for OwnedSliceMut<'a, T> {
fn from(r: &'a mut &'a mut [T]) -> Self {
Self {
inner: OwnedSliceMutInner::Ref(r),
} }
} }
} }

View File

@ -75,7 +75,7 @@ impl HasBytesVec for BytesInput {
impl HasTargetBytes for BytesInput { impl HasTargetBytes for BytesInput {
#[inline] #[inline]
fn target_bytes(&self) -> OwnedSlice<u8> { fn target_bytes(&self) -> OwnedSlice<u8> {
OwnedSlice::Ref(&self.bytes) OwnedSlice::from(&self.bytes)
} }
} }

View File

@ -76,7 +76,7 @@ impl Input for NopInput {
} }
impl HasTargetBytes for NopInput { impl HasTargetBytes for NopInput {
fn target_bytes(&self) -> OwnedSlice<u8> { fn target_bytes(&self) -> OwnedSlice<u8> {
OwnedSlice::Owned(vec![0]) OwnedSlice::from(vec![0])
} }
} }

View File

@ -5,11 +5,7 @@ use alloc::{
string::{String, ToString}, string::{String, ToString},
vec::Vec, vec::Vec,
}; };
use core::{ use core::{fmt::Debug, hash::Hasher, slice::from_raw_parts};
fmt::Debug,
hash::Hasher,
slice::{from_raw_parts, from_raw_parts_mut},
};
use intervaltree::IntervalTree; use intervaltree::IntervalTree;
use num_traits::PrimInt; use num_traits::PrimInt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -188,7 +184,7 @@ where
pub fn new(name: &'static str, map: &'a mut [T]) -> Self { pub fn new(name: &'static str, map: &'a mut [T]) -> Self {
let initial = if map.is_empty() { T::default() } else { map[0] }; let initial = if map.is_empty() { T::default() } else { map[0] };
Self { Self {
map: OwnedSliceMut::Ref(map), map: OwnedSliceMut::from(map),
name: name.to_string(), name: name.to_string(),
initial, initial,
} }
@ -199,7 +195,26 @@ where
pub fn new_owned(name: &'static str, map: Vec<T>) -> Self { pub fn new_owned(name: &'static str, map: Vec<T>) -> Self {
let initial = if map.is_empty() { T::default() } else { map[0] }; let initial = if map.is_empty() { T::default() } else { map[0] };
Self { Self {
map: OwnedSliceMut::Owned(map), map: OwnedSliceMut::from(map),
name: name.to_string(),
initial,
}
}
/// Creates a new [`MapObserver`] from an [`OwnedSliceMut`] map.
///
/// # Safety
/// Will dereference the owned slice with up to len elements.
#[must_use]
pub fn new_from_ownedref(name: &'static str, map: OwnedSliceMut<'a, T>) -> Self {
let map_slice = map.as_slice();
let initial = if map_slice.is_empty() {
T::default()
} else {
map_slice[0]
};
Self {
map,
name: name.to_string(), name: name.to_string(),
initial, initial,
} }
@ -212,7 +227,7 @@ where
pub unsafe fn new_from_ptr(name: &'static str, map_ptr: *mut T, len: usize) -> Self { pub unsafe fn new_from_ptr(name: &'static str, map_ptr: *mut T, len: usize) -> Self {
let initial = if len > 0 { *map_ptr } else { T::default() }; let initial = if len > 0 { *map_ptr } else { T::default() };
StdMapObserver { StdMapObserver {
map: OwnedSliceMut::Ref(from_raw_parts_mut(map_ptr, len)), map: OwnedSliceMut::from_raw_parts_mut(map_ptr, len),
name: name.to_string(), name: name.to_string(),
initial, initial,
} }
@ -309,7 +324,7 @@ where
assert!(map.len() >= N); assert!(map.len() >= N);
let initial = if map.is_empty() { T::default() } else { map[0] }; let initial = if map.is_empty() { T::default() } else { map[0] };
Self { Self {
map: OwnedSliceMut::Ref(map), map: OwnedSliceMut::from(map),
name: name.to_string(), name: name.to_string(),
initial, initial,
} }
@ -321,7 +336,7 @@ where
assert!(map.len() >= N); assert!(map.len() >= N);
let initial = if map.is_empty() { T::default() } else { map[0] }; let initial = if map.is_empty() { T::default() } else { map[0] };
Self { Self {
map: OwnedSliceMut::Owned(map), map: OwnedSliceMut::from(map),
name: name.to_string(), name: name.to_string(),
initial, initial,
} }
@ -334,7 +349,7 @@ where
pub unsafe fn new_from_ptr(name: &'static str, map_ptr: *mut T) -> Self { pub unsafe fn new_from_ptr(name: &'static str, map_ptr: *mut T) -> Self {
let initial = if N > 0 { *map_ptr } else { T::default() }; let initial = if N > 0 { *map_ptr } else { T::default() };
ConstMapObserver { ConstMapObserver {
map: OwnedSliceMut::Ref(from_raw_parts_mut(map_ptr, N)), map: OwnedSliceMut::from_raw_parts_mut(map_ptr, N),
name: name.to_string(), name: name.to_string(),
initial, initial,
} }
@ -429,7 +444,7 @@ where
pub fn new(name: &'static str, map: &'a mut [T], size: &'a mut usize) -> Self { pub fn new(name: &'static str, map: &'a mut [T], size: &'a mut usize) -> Self {
let initial = if map.is_empty() { T::default() } else { map[0] }; let initial = if map.is_empty() { T::default() } else { map[0] };
Self { Self {
map: OwnedSliceMut::Ref(map), map: OwnedSliceMut::from(map),
size: OwnedRefMut::Ref(size), size: OwnedRefMut::Ref(size),
name: name.into(), name: name.into(),
initial, initial,
@ -448,7 +463,7 @@ where
) -> Self { ) -> Self {
let initial = if max_len > 0 { *map_ptr } else { T::default() }; let initial = if max_len > 0 { *map_ptr } else { T::default() };
VariableMapObserver { VariableMapObserver {
map: OwnedSliceMut::Ref(from_raw_parts_mut(map_ptr, max_len)), map: OwnedSliceMut::from_raw_parts_mut(map_ptr, max_len),
size: OwnedRefMut::Ref(size), size: OwnedRefMut::Ref(size),
name: name.into(), name: name.into(),
initial, initial,
@ -715,7 +730,7 @@ where
idx += l; idx += l;
builder.push(r); builder.push(r);
v += 1; v += 1;
OwnedSliceMut::Ref(x) OwnedSliceMut::from(x)
}) })
.collect(); .collect();
Self { Self {
@ -745,7 +760,7 @@ where
idx += l; idx += l;
builder.push(r); builder.push(r);
v += 1; v += 1;
OwnedSliceMut::Owned(x) OwnedSliceMut::from(x)
}) })
.collect(); .collect();
Self { Self {

View File

@ -1,7 +1,6 @@
//! Coverage maps as static mut array //! Coverage maps as static mut array
use crate::EDGES_MAP_SIZE; use crate::EDGES_MAP_SIZE;
use core::slice::from_raw_parts_mut;
/// The map for edges. /// The map for edges.
#[no_mangle] #[no_mangle]
@ -21,14 +20,18 @@ pub use __afl_area_ptr as EDGES_MAP_PTR;
#[no_mangle] #[no_mangle]
pub static mut __afl_map_size: usize = EDGES_MAP_SIZE; pub static mut __afl_map_size: usize = EDGES_MAP_SIZE;
pub use __afl_map_size as EDGES_MAP_PTR_SIZE; pub use __afl_map_size as EDGES_MAP_PTR_SIZE;
use libafl::bolts::ownedref::OwnedSliceMut;
/// Gets the edges map from the `EDGES_MAP_PTR` raw pointer. /// Gets the edges map from the `EDGES_MAP_PTR` raw pointer.
///
/// # Safety
///
/// This function will crash if `EDGES_MAP_PTR` is not a valid pointer.
/// The `EDGES_MAP_PTR_SIZE` needs to be smaller than, or equal to the size of the map.
#[must_use] #[must_use]
pub fn edges_map_from_ptr<'a>() -> &'a mut [u8] { pub unsafe fn edges_map_from_ptr<'a>() -> OwnedSliceMut<'a, u8> {
unsafe {
debug_assert!(!EDGES_MAP_PTR.is_null()); debug_assert!(!EDGES_MAP_PTR.is_null());
from_raw_parts_mut(EDGES_MAP_PTR, EDGES_MAP_PTR_SIZE) OwnedSliceMut::from_raw_parts_mut(EDGES_MAP_PTR, EDGES_MAP_PTR_SIZE)
}
} }
/// Gets the current maximum number of edges tracked. /// Gets the current maximum number of edges tracked.