diff --git a/fuzzers/libafl_atheris/src/lib.rs b/fuzzers/libafl_atheris/src/lib.rs index d2e8219f0e..1ebd696a2f 100644 --- a/fuzzers/libafl_atheris/src/lib.rs +++ b/fuzzers/libafl_atheris/src/lib.rs @@ -216,8 +216,13 @@ pub fn LLVMFuzzerRunDriver( let mut run_client = |state: Option>, mut mgr, _core_id| { // 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 = HitcountsMapObserver::new(StdMapObserver::new("edges", edges)); + let edges_observer = unsafe { + HitcountsMapObserver::new(StdMapObserver::new_from_ptr( + "edges", + EDGES_MAP_PTR, + MAX_EDGES_NUM, + )) + }; // Create an observation channel to keep track of the execution time let time_observer = TimeObserver::new("time"); diff --git a/fuzzers/libfuzzer_libpng_ctx/src/lib.rs b/fuzzers/libfuzzer_libpng_ctx/src/lib.rs index a9119fe1b5..315bca5d12 100644 --- a/fuzzers/libfuzzer_libpng_ctx/src/lib.rs +++ b/fuzzers/libfuzzer_libpng_ctx/src/lib.rs @@ -144,8 +144,9 @@ pub fn libafl_main() { let mut run_client = |state: Option>, mut restarting_mgr, _core_id| { // Create an observation channel using the coverage map - let edges = edges_map_from_ptr(); - let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges)); + let edges = unsafe { edges_map_from_ptr() }; + let edges_observer = + HitcountsMapObserver::new(StdMapObserver::new_from_ownedref("edges", edges)); // Create an observation channel to keep track of the execution time let time_observer = TimeObserver::new("time"); diff --git a/fuzzers/tutorial/src/input.rs b/fuzzers/tutorial/src/input.rs index 599c9b5e94..bc3b216a37 100644 --- a/fuzzers/tutorial/src/input.rs +++ b/fuzzers/tutorial/src/input.rs @@ -61,7 +61,7 @@ impl HasTargetBytes for PacketData { fn target_bytes(&self) -> OwnedSlice { let mut serialized_data = Vec::with_capacity(self.serialized_size()); self.binary_serialize::<_, LittleEndian>(&mut serialized_data); - OwnedSlice::Owned(serialized_data) + OwnedSlice::from(serialized_data) } } diff --git a/libafl/src/bolts/ownedref.rs b/libafl/src/bolts/ownedref.rs index 52d292f397..025632d910 100644 --- a/libafl/src/bolts/ownedref.rs +++ b/libafl/src/bolts/ownedref.rs @@ -2,7 +2,7 @@ // The serialization is towards owned, allowing to serialize pointers without troubles. 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}; /// Trait to convert into an Owned type @@ -166,26 +166,31 @@ where /// Wrap a slice and convert to a Vec on serialize #[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 Ref(&'a [T]), /// A ref to an owned [`Vec`] Owned(Vec), } -impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSlice<'a, T> { +impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSliceInner<'a, T> { fn serialize(&self, se: S) -> Result where S: Serializer, { match self { - OwnedSlice::Ref(r) => r.serialize(se), - OwnedSlice::Owned(b) => b.serialize(se), + OwnedSliceInner::RefRaw(rr, len) => unsafe { + 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 Vec: Deserialize<'de>, { @@ -193,7 +198,79 @@ where where 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() * 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> for OwnedSlice<'a, T> { + fn from(vec: Vec) -> Self { + Self { + inner: OwnedSliceInner::Owned(vec), + } + } +} + +/// Create a new [`OwnedSlice`] from a vector reference +impl<'a, T> From<&'a Vec> for OwnedSlice<'a, T> { + fn from(vec: &'a Vec) -> 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> 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. #[must_use] pub fn as_slice(&self) -> &[T] { - match self { - OwnedSlice::Ref(r) => r, - OwnedSlice::Owned(v) => v.as_slice(), + match &self.inner { + OwnedSliceInner::Ref(r) => r, + OwnedSliceInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts(*rr, *len) }, + OwnedSliceInner::Owned(v) => v.as_slice(), } } } @@ -214,43 +292,57 @@ where { #[must_use] fn is_owned(&self) -> bool { - match self { - OwnedSlice::Ref(_) => false, - OwnedSlice::Owned(_) => true, + match self.inner { + OwnedSliceInner::RefRaw(_, _) | OwnedSliceInner::Ref(_) => false, + OwnedSliceInner::Owned(_) => true, } } #[must_use] fn into_owned(self) -> Self { - match self { - OwnedSlice::Ref(r) => OwnedSlice::Owned(r.to_vec()), - OwnedSlice::Owned(v) => OwnedSlice::Owned(v), + match self.inner { + OwnedSliceInner::RefRaw(rr, len) => Self { + 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 +/// 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)] -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 Ref(&'a mut [T]), /// An owned [`Vec`] of the type Owned(Vec), } -impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSliceMut<'a, T> { +impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSliceMutInner<'a, T> { fn serialize(&self, se: S) -> Result where S: Serializer, { match self { - OwnedSliceMut::Ref(r) => r.serialize(se), - OwnedSliceMut::Owned(b) => b.serialize(se), + OwnedSliceMutInner::RefRaw(rr, len) => { + 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 Vec: Deserialize<'de>, { @@ -258,7 +350,35 @@ where where 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() * 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 #[must_use] pub fn as_slice(&self) -> &[T] { - match self { - OwnedSliceMut::Ref(r) => r, - OwnedSliceMut::Owned(v) => v.as_slice(), + match &self.inner { + OwnedSliceMutInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts(*rr, *len) }, + OwnedSliceMutInner::Ref(r) => r, + OwnedSliceMutInner::Owned(v) => v.as_slice(), } } /// Get the value as mut slice #[must_use] pub fn as_mut_slice(&mut self) -> &mut [T] { - match self { - OwnedSliceMut::Ref(r) => r, - OwnedSliceMut::Owned(v) => v.as_mut_slice(), + match &mut self.inner { + OwnedSliceMutInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts_mut(*rr, *len) }, + OwnedSliceMutInner::Ref(r) => r, + OwnedSliceMutInner::Owned(v) => v.as_mut_slice(), } } } @@ -288,17 +410,68 @@ where { #[must_use] fn is_owned(&self) -> bool { - match self { - OwnedSliceMut::Ref(_) => false, - OwnedSliceMut::Owned(_) => true, + match self.inner { + OwnedSliceMutInner::RefRaw(_, _) | OwnedSliceMutInner::Ref(_) => false, + OwnedSliceMutInner::Owned(_) => true, } } #[must_use] fn into_owned(self) -> Self { - match self { - OwnedSliceMut::Ref(r) => OwnedSliceMut::Owned(r.to_vec()), - OwnedSliceMut::Owned(v) => OwnedSliceMut::Owned(v), + let vec = match self.inner { + OwnedSliceMutInner::RefRaw(rr, len) => unsafe { + 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> for OwnedSliceMut<'a, T> { + fn from(vec: Vec) -> Self { + Self { + inner: OwnedSliceMutInner::Owned(vec), + } + } +} + +/// Create a new [`OwnedSliceMut`] from a vector reference +impl<'a, T> From<&'a mut Vec> for OwnedSliceMut<'a, T> { + fn from(vec: &'a mut Vec) -> 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), } } } diff --git a/libafl/src/inputs/bytes.rs b/libafl/src/inputs/bytes.rs index 5ecea7ef2f..67ec943eff 100644 --- a/libafl/src/inputs/bytes.rs +++ b/libafl/src/inputs/bytes.rs @@ -75,7 +75,7 @@ impl HasBytesVec for BytesInput { impl HasTargetBytes for BytesInput { #[inline] fn target_bytes(&self) -> OwnedSlice { - OwnedSlice::Ref(&self.bytes) + OwnedSlice::from(&self.bytes) } } diff --git a/libafl/src/inputs/mod.rs b/libafl/src/inputs/mod.rs index eebf4d0406..50b5baafa2 100644 --- a/libafl/src/inputs/mod.rs +++ b/libafl/src/inputs/mod.rs @@ -76,7 +76,7 @@ impl Input for NopInput { } impl HasTargetBytes for NopInput { fn target_bytes(&self) -> OwnedSlice { - OwnedSlice::Owned(vec![0]) + OwnedSlice::from(vec![0]) } } diff --git a/libafl/src/observers/map.rs b/libafl/src/observers/map.rs index 5819abd9b0..cca20be32f 100644 --- a/libafl/src/observers/map.rs +++ b/libafl/src/observers/map.rs @@ -5,11 +5,7 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use core::{ - fmt::Debug, - hash::Hasher, - slice::{from_raw_parts, from_raw_parts_mut}, -}; +use core::{fmt::Debug, hash::Hasher, slice::from_raw_parts}; use intervaltree::IntervalTree; use num_traits::PrimInt; use serde::{Deserialize, Serialize}; @@ -188,7 +184,7 @@ where pub fn new(name: &'static str, map: &'a mut [T]) -> Self { let initial = if map.is_empty() { T::default() } else { map[0] }; Self { - map: OwnedSliceMut::Ref(map), + map: OwnedSliceMut::from(map), name: name.to_string(), initial, } @@ -199,7 +195,26 @@ where pub fn new_owned(name: &'static str, map: Vec) -> Self { let initial = if map.is_empty() { T::default() } else { map[0] }; 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(), initial, } @@ -212,7 +227,7 @@ where 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() }; StdMapObserver { - map: OwnedSliceMut::Ref(from_raw_parts_mut(map_ptr, len)), + map: OwnedSliceMut::from_raw_parts_mut(map_ptr, len), name: name.to_string(), initial, } @@ -309,7 +324,7 @@ where assert!(map.len() >= N); let initial = if map.is_empty() { T::default() } else { map[0] }; Self { - map: OwnedSliceMut::Ref(map), + map: OwnedSliceMut::from(map), name: name.to_string(), initial, } @@ -321,7 +336,7 @@ where assert!(map.len() >= N); let initial = if map.is_empty() { T::default() } else { map[0] }; Self { - map: OwnedSliceMut::Owned(map), + map: OwnedSliceMut::from(map), name: name.to_string(), initial, } @@ -334,7 +349,7 @@ where pub unsafe fn new_from_ptr(name: &'static str, map_ptr: *mut T) -> Self { let initial = if N > 0 { *map_ptr } else { T::default() }; ConstMapObserver { - map: OwnedSliceMut::Ref(from_raw_parts_mut(map_ptr, N)), + map: OwnedSliceMut::from_raw_parts_mut(map_ptr, N), name: name.to_string(), initial, } @@ -429,7 +444,7 @@ where 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] }; Self { - map: OwnedSliceMut::Ref(map), + map: OwnedSliceMut::from(map), size: OwnedRefMut::Ref(size), name: name.into(), initial, @@ -448,7 +463,7 @@ where ) -> Self { let initial = if max_len > 0 { *map_ptr } else { T::default() }; 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), name: name.into(), initial, @@ -715,7 +730,7 @@ where idx += l; builder.push(r); v += 1; - OwnedSliceMut::Ref(x) + OwnedSliceMut::from(x) }) .collect(); Self { @@ -745,7 +760,7 @@ where idx += l; builder.push(r); v += 1; - OwnedSliceMut::Owned(x) + OwnedSliceMut::from(x) }) .collect(); Self { diff --git a/libafl_targets/src/coverage.rs b/libafl_targets/src/coverage.rs index 49a8215fb5..feb2fb5b91 100644 --- a/libafl_targets/src/coverage.rs +++ b/libafl_targets/src/coverage.rs @@ -1,7 +1,6 @@ //! Coverage maps as static mut array use crate::EDGES_MAP_SIZE; -use core::slice::from_raw_parts_mut; /// The map for edges. #[no_mangle] @@ -21,14 +20,18 @@ pub use __afl_area_ptr as EDGES_MAP_PTR; #[no_mangle] pub static mut __afl_map_size: usize = EDGES_MAP_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. +/// +/// # 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] -pub fn edges_map_from_ptr<'a>() -> &'a mut [u8] { - unsafe { - debug_assert!(!EDGES_MAP_PTR.is_null()); - from_raw_parts_mut(EDGES_MAP_PTR, EDGES_MAP_PTR_SIZE) - } +pub unsafe fn edges_map_from_ptr<'a>() -> OwnedSliceMut<'a, u8> { + debug_assert!(!EDGES_MAP_PTR.is_null()); + OwnedSliceMut::from_raw_parts_mut(EDGES_MAP_PTR, EDGES_MAP_PTR_SIZE) } /// Gets the current maximum number of edges tracked.