Fix as_object UB discussed in #1748 (#1751)

* Fix as_object UB discussed in #1748

* More cleanup, more less UB

* Fix fixes

* Added uninit_on_shmem api

* clippy

* fmt

* trying to fix fuzzers, libfuzzer wrapper

* Add OwnedRefMit::owned constructor, libfuzzer fix

* Some more fixes

* Add BacktaceObserver::owned fn

* fmt

* more fmt
This commit is contained in:
Dominik Maier 2023-12-22 16:49:01 +01:00 committed by GitHub
parent 4e7d2caa9f
commit c93291ab57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 245 additions and 140 deletions

View File

@ -18,8 +18,9 @@ use libafl::{
};
use libafl_bolts::{
current_nanos,
ownedref::OwnedRefMut,
rands::StdRand,
shmem::{ShMem, ShMemProvider, StdShMemProvider},
shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list,
AsSlice,
};
@ -47,10 +48,10 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = unsafe { ConstMapObserver::<u8, 3>::from_mut_ptr("signals", map_ptr) };
// Create a stacktrace observer
let mut bt = shmem_provider.new_shmem_object::<Option<u64>>().unwrap();
let mut bt = shmem_provider.new_on_shmem::<Option<u64>>(None).unwrap();
let bt_observer = BacktraceObserver::new(
"BacktraceObserver",
unsafe { bt.as_object_mut::<Option<u64>>() },
unsafe { OwnedRefMut::from_shmem(&mut bt) },
libafl::observers::HarnessType::Child,
);

View File

@ -37,10 +37,8 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = unsafe { ConstMapObserver::<u8, 3>::from_mut_ptr("signals", array_ptr) };
// Create a stacktrace observer
let mut bt = None;
let bt_observer = BacktraceObserver::new(
let bt_observer = BacktraceObserver::owned(
"BacktraceObserver",
&mut bt,
libafl::observers::HarnessType::InProcess,
);

View File

@ -20,6 +20,7 @@ use libafl::{
};
use libafl_bolts::{
current_nanos,
ownedref::OwnedRefMut,
rands::StdRand,
shmem::{unix_shmem, ShMem, ShMemProvider},
tuples::tuple_list,
@ -32,7 +33,7 @@ pub fn main() {
let mut signals = shmem_provider.new_shmem(16).unwrap();
let signals_len = signals.len();
let signals_ptr = signals.as_mut_slice().as_mut_ptr();
let mut bt = shmem_provider.new_shmem_object::<Option<u64>>().unwrap();
let mut bt = shmem_provider.new_on_shmem::<Option<u64>>(None).unwrap();
let signals_set = |idx: usize| {
unsafe { write(signals_ptr.add(idx), 1) };
@ -69,7 +70,7 @@ pub fn main() {
// Create a stacktrace observer
let bt_observer = BacktraceObserver::new(
"BacktraceObserver",
unsafe { bt.as_object_mut::<Option<u64>>() },
unsafe { OwnedRefMut::from_shmem(&mut bt) },
libafl::observers::HarnessType::Child,
);

View File

@ -61,10 +61,8 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = unsafe { StdMapObserver::from_mut_ptr("signals", SIGNALS_PTR, SIGNALS.len()) };
// Create a stacktrace observer to add the observers tuple
let mut bt = None;
let bt_observer = BacktraceObserver::new(
let bt_observer = BacktraceObserver::owned(
"BacktraceObserver",
&mut bt,
libafl::observers::HarnessType::InProcess,
);

View File

@ -209,9 +209,7 @@ fn fuzz(
let edges = edges_shmem.as_mut_slice();
unsafe { EDGES_MAP_PTR = edges.as_mut_ptr() };
let mut cmp_shmem = shmem_provider
.new_shmem(core::mem::size_of::<CmpLogMap>())
.unwrap();
let mut cmp_shmem = shmem_provider.uninit_on_shmem::<CmpLogMap>().unwrap();
let cmplog = cmp_shmem.as_mut_slice();
// Beginning of a page should be properly aligned.

View File

@ -34,6 +34,7 @@ use libafl::{
};
use libafl_bolts::{
current_nanos, current_time,
ownedref::OwnedRefMut,
rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, Merge},
@ -204,6 +205,7 @@ pub fn main() {
}
/// The actual fuzzer
#[allow(clippy::too_many_arguments)]
fn fuzz(
corpus_dir: PathBuf,
objective_dir: PathBuf,
@ -340,12 +342,10 @@ fn fuzz(
if let Some(exec) = &cmplog_exec {
// The cmplog map shared between observer and executor
let mut cmplog_shmem = shmem_provider
.new_shmem(core::mem::size_of::<AFLppCmpLogMap>())
.unwrap();
let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap();
// let the forkserver know the shmid
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap();
let cmpmap = unsafe { cmplog_shmem.as_object_mut::<AFLppCmpLogMap>() };
let cmpmap = unsafe { OwnedRefMut::<AFLppCmpLogMap>::from_shmem(&mut cmplog_shmem) };
let cmplog_observer = StdCmpValuesObserver::new("cmplog", cmpmap, true);

View File

@ -34,6 +34,7 @@ use libafl::{
};
use libafl_bolts::{
current_nanos, current_time,
ownedref::OwnedRefMut,
rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, Merge},
@ -207,6 +208,7 @@ pub fn main() {
}
/// The actual fuzzer
#[allow(clippy::too_many_arguments)]
fn fuzz(
corpus_dir: PathBuf,
objective_dir: PathBuf,
@ -344,12 +346,10 @@ fn fuzz(
if let Some(exec) = &cmplog_exec {
// The cmplog map shared between observer and executor
let mut cmplog_shmem = shmem_provider
.new_shmem(core::mem::size_of::<AFLppCmpLogMap>())
.unwrap();
let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap();
// let the forkserver know the shmid
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap();
let cmpmap = unsafe { cmplog_shmem.as_object_mut::<AFLppCmpLogMap>() };
let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) };
let cmplog_observer = AFLppCmpLogObserver::new("cmplog", cmpmap, true);

View File

@ -333,11 +333,11 @@ where
{
/// Creates a new [`StdCmpObserver`] with the given name and map.
#[must_use]
pub fn new(name: &'static str, map: &'a mut CM, add_meta: bool) -> Self {
pub fn new(name: &'static str, map: OwnedRefMut<'a, CM>, add_meta: bool) -> Self {
Self {
name: name.to_string(),
size: None,
cmp_map: OwnedRefMut::Ref(map),
cmp_map: map,
add_meta,
data: M::Data::default(),
phantom: PhantomData,
@ -347,11 +347,16 @@ where
/// Creates a new [`StdCmpObserver`] with the given name, map, and auxiliary data used to
/// populate metadata
#[must_use]
pub fn with_data(name: &'static str, map: &'a mut CM, add_meta: bool, data: M::Data) -> Self {
pub fn with_data(
name: &'static str,
cmp_map: OwnedRefMut<'a, CM>,
add_meta: bool,
data: M::Data,
) -> Self {
Self {
name: name.to_string(),
size: None,
cmp_map: OwnedRefMut::Ref(map),
cmp_map,
add_meta,
data,
phantom: PhantomData,
@ -362,14 +367,14 @@ where
#[must_use]
pub fn with_size(
name: &'static str,
map: &'a mut CM,
cmp_map: OwnedRefMut<'a, CM>,
add_meta: bool,
size: &'a mut usize,
size: OwnedRefMut<'a, usize>,
) -> Self {
Self {
name: name.to_string(),
size: Some(OwnedRefMut::Ref(size)),
cmp_map: OwnedRefMut::Ref(map),
size: Some(size),
cmp_map,
add_meta,
data: M::Data::default(),
phantom: PhantomData,
@ -381,15 +386,15 @@ where
#[must_use]
pub fn with_size_data(
name: &'static str,
map: &'a mut CM,
cmp_map: OwnedRefMut<'a, CM>,
add_meta: bool,
data: M::Data,
size: &'a mut usize,
size: OwnedRefMut<'a, usize>,
) -> Self {
Self {
name: name.to_string(),
size: Some(OwnedRefMut::Ref(size)),
cmp_map: OwnedRefMut::Ref(map),
size: Some(size),
cmp_map,
add_meta,
data,
phantom: PhantomData,

View File

@ -127,12 +127,12 @@ impl<'a> BacktraceObserver<'a> {
#[must_use]
pub fn new(
observer_name: &str,
backtrace_hash: &'a mut Option<u64>,
backtrace_hash: OwnedRefMut<'a, Option<u64>>,
harness_type: HarnessType,
) -> Self {
Self {
observer_name: observer_name.to_string(),
hash: OwnedRefMut::Ref(backtrace_hash),
hash: backtrace_hash,
harness_type,
}
}
@ -142,17 +142,23 @@ impl<'a> BacktraceObserver<'a> {
#[must_use]
pub fn new(
observer_name: &str,
backtrace_hash: &'a mut Option<u64>,
backtrace_hash: OwnedRefMut<'a, Option<u64>>,
harness_type: HarnessType,
) -> Self {
init_ignored_frames!("rust", "cpp", "go");
Self {
observer_name: observer_name.to_string(),
hash: OwnedRefMut::Ref(backtrace_hash),
hash: backtrace_hash,
harness_type,
}
}
/// Creates a new [`BacktraceObserver`] with the given name, owning a new `backtrace_hash` variable.
#[must_use]
pub fn owned(observer_name: &str, harness_type: HarnessType) -> Self {
Self::new(observer_name, OwnedRefMut::owned(None), harness_type)
}
/// Updates the hash value of this observer.
fn update_hash(&mut self, hash: u64) {
*self.hash.as_mut() = Some(hash);

View File

@ -40,10 +40,10 @@ where
{
/// Creates a new [`ValueObserver`] with the given name.
#[must_use]
pub fn new(name: &'static str, value: &'a T) -> Self {
pub fn new(name: &'static str, value: OwnedRef<'a, T>) -> Self {
Self {
name: name.to_string(),
value: OwnedRef::Ref(value),
value,
}
}
@ -65,6 +65,7 @@ where
T: Clone,
{
match self.value {
OwnedRef::RefRaw(r, _) => unsafe { (*r).clone() },
OwnedRef::Ref(r) => r.clone(),
OwnedRef::Owned(v) => *v,
}
@ -119,10 +120,10 @@ where
{
/// Creates a new [`RefCellValueObserver`] with the given name.
#[must_use]
pub fn new(name: &'static str, value: &'a RefCell<T>) -> Self {
pub fn new(name: &'static str, value: OwnedRef<'a, RefCell<T>>) -> Self {
Self {
name: name.to_string(),
value: OwnedRef::Ref(value),
value,
}
}
@ -147,6 +148,7 @@ where
T: Clone,
{
match self.value {
OwnedRef::RefRaw(r, _) => unsafe { (*r).borrow().deref().clone() },
OwnedRef::Ref(r) => r.borrow().deref().clone(),
OwnedRef::Owned(v) => v.borrow().clone(),
}

View File

@ -10,7 +10,28 @@ use core::{clone::Clone, fmt::Debug, slice};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{AsMutSlice, AsSlice, IntoOwned, Truncate};
use crate::{shmem::ShMem, AsMutSlice, AsSlice, IntoOwned, Truncate};
/// Private part of the unsafe marker, making sure this cannot be initialized directly.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct UnsafeMarkerInner;
/// A struct or enum containing this [`UnsafeMarker`] cannot directly be instantiated.
/// Usually, this means you'll have to use a constructor like `unsafe { Self::new() }` or similar.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct UnsafeMarker(UnsafeMarkerInner);
impl UnsafeMarker {
/// Return a new unsafe marker.
/// This usually means you're about to do something unsafe.
///
/// # Safety
/// Instantiating an [`UnsafeMarker`] isn't unsafe, but the location you need it for
/// will likely have potential unsafety.
unsafe fn new() -> Self {
Self(UnsafeMarkerInner)
}
}
impl<'a, T> Truncate for &'a [T] {
fn truncate(&mut self, len: usize) {
@ -32,12 +53,54 @@ pub enum OwnedRef<'a, T>
where
T: 'a + ?Sized,
{
/// A pointer to a type
RefRaw(*const T, UnsafeMarker),
/// A ref to a type
Ref(&'a T),
/// An owned [`Box`] of a type
Owned(Box<T>),
}
impl<'a, T> OwnedRef<'a, T>
where
T: 'a + ?Sized,
{
/// Returns a new [`OwnedRef`], wrapping a pointer of type `T`.
///
/// # Safety
/// The pointer needs to point to a valid object of type `T`.
/// Any use of this [`OwnedRef`] will dereference the pointer accordingly.
pub unsafe fn from_ptr(ptr: *const T) -> Self {
assert!(
!ptr.is_null(),
"Null pointer passed to OwnedRef::ref_raw constructor!"
);
Self::RefRaw(ptr, UnsafeMarker::new())
}
}
impl<'a, T> OwnedRef<'a, T>
where
T: Sized + 'static,
{
/// Returns a new [`OwnedRef`], pointing to the given [`ShMem`].
///
/// # Panics
/// Panics if the given shared mem is too small
///
/// # Safety
/// The shared memory needs to start with a valid object of type `T`.
/// Any use of this [`OwnedRef`] will dereference a pointer to the shared memory accordingly.
pub unsafe fn from_shmem<S: ShMem>(shmem: &mut S) -> Self {
Self::from_ptr(shmem.as_mut_ptr_of().unwrap())
}
/// Returns a new [`OwnedRef`], owning the given value.
pub fn owned(val: T) -> Self {
Self::Owned(Box::new(val))
}
}
impl<'a, T> Serialize for OwnedRef<'a, T>
where
T: 'a + ?Sized + Serialize,
@ -47,6 +110,7 @@ where
S: Serializer,
{
match self {
OwnedRef::RefRaw(r, _) => unsafe { (*r).as_ref().unwrap() }.serialize(se),
OwnedRef::Ref(r) => r.serialize(se),
OwnedRef::Owned(b) => b.serialize(se),
}
@ -73,6 +137,7 @@ where
#[must_use]
fn as_ref(&self) -> &T {
match self {
OwnedRef::RefRaw(r, _) => unsafe { (*r).as_ref().unwrap() },
OwnedRef::Ref(r) => r,
OwnedRef::Owned(v) => v.as_ref(),
}
@ -86,7 +151,7 @@ where
#[must_use]
fn is_owned(&self) -> bool {
match self {
OwnedRef::Ref(_) => false,
OwnedRef::RefRaw(..) | OwnedRef::Ref(_) => false,
OwnedRef::Owned(_) => true,
}
}
@ -94,6 +159,9 @@ where
#[must_use]
fn into_owned(self) -> Self {
match self {
OwnedRef::RefRaw(r, _) => {
OwnedRef::Owned(Box::new(unsafe { r.as_ref().unwrap().clone() }))
}
OwnedRef::Ref(r) => OwnedRef::Owned(Box::new(r.clone())),
OwnedRef::Owned(v) => OwnedRef::Owned(v),
}
@ -102,13 +170,61 @@ where
/// Wrap a mutable reference and convert to a Box on serialize
#[derive(Debug)]
pub enum OwnedRefMut<'a, T: 'a + ?Sized> {
pub enum OwnedRefMut<'a, T>
where
T: 'a + ?Sized,
{
/// A mutable pointer to a type
RefRaw(*mut T, UnsafeMarker),
/// A mutable ref to a type
Ref(&'a mut T),
/// An owned [`Box`] of a type
Owned(Box<T>),
}
impl<'a, T> OwnedRefMut<'a, T>
where
T: 'a + ?Sized,
{
/// Returns a new [`OwnedRefMut`], wrapping a mutable pointer.
///
/// # Panics
/// Panics if the given pointer is `null`
///
/// # Safety
/// The pointer needs to point to a valid object of type `T`.
/// Any use of this [`OwnedRefMut`] will dereference the pointer accordingly.
pub unsafe fn from_mut_ptr(ptr: *mut T) -> Self {
assert!(
!ptr.is_null(),
"Null pointer passed to OwnedRefMut::from_mut_ptr constructor!"
);
Self::RefRaw(ptr, UnsafeMarker::new())
}
}
impl<'a, T> OwnedRefMut<'a, T>
where
T: Sized + 'static,
{
/// Returns a new [`OwnedRefMut`], pointing to the given [`ShMem`].
///
/// # Panics
/// Panics if the given shared mem is too small
///
/// # Safety
/// The shared memory needs to start with a valid object of type `T`.
/// Any use of this [`OwnedRefMut`] will dereference a pointer to the shared memory accordingly.
pub unsafe fn from_shmem<S: ShMem>(shmem: &mut S) -> Self {
Self::from_mut_ptr(shmem.as_mut_ptr_of().unwrap())
}
/// Returns a new [`OwnedRefMut`], owning the given value.
pub fn owned(val: T) -> Self {
Self::Owned(Box::new(val))
}
}
impl<'a, T: 'a + ?Sized + Serialize> Serialize for OwnedRefMut<'a, T> {
fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
where
@ -116,6 +232,7 @@ impl<'a, T: 'a + ?Sized + Serialize> Serialize for OwnedRefMut<'a, T> {
{
match self {
OwnedRefMut::Ref(r) => r.serialize(se),
OwnedRefMut::RefRaw(r, _) => unsafe { r.as_ref().unwrap().serialize(se) },
OwnedRefMut::Owned(b) => b.serialize(se),
}
}
@ -137,6 +254,7 @@ impl<'a, T: Sized> AsRef<T> for OwnedRefMut<'a, T> {
#[must_use]
fn as_ref(&self) -> &T {
match self {
OwnedRefMut::RefRaw(r, _) => unsafe { r.as_ref().unwrap() },
OwnedRefMut::Ref(r) => r,
OwnedRefMut::Owned(v) => v.as_ref(),
}
@ -147,6 +265,7 @@ impl<'a, T: Sized> AsMut<T> for OwnedRefMut<'a, T> {
#[must_use]
fn as_mut(&mut self) -> &mut T {
match self {
OwnedRefMut::RefRaw(r, _) => unsafe { r.as_mut().unwrap() },
OwnedRefMut::Ref(r) => r,
OwnedRefMut::Owned(v) => v.as_mut(),
}
@ -160,7 +279,7 @@ where
#[must_use]
fn is_owned(&self) -> bool {
match self {
OwnedRefMut::Ref(_) => false,
OwnedRefMut::RefRaw(..) | OwnedRefMut::Ref(_) => false,
OwnedRefMut::Owned(_) => true,
}
}
@ -168,6 +287,9 @@ where
#[must_use]
fn into_owned(self) -> Self {
match self {
OwnedRefMut::RefRaw(r, _) => unsafe {
OwnedRefMut::Owned(Box::new(r.as_ref().unwrap().clone()))
},
OwnedRefMut::Ref(r) => OwnedRefMut::Owned(Box::new(r.clone())),
OwnedRefMut::Owned(v) => OwnedRefMut::Owned(v),
}
@ -178,7 +300,7 @@ where
#[derive(Clone, Debug)]
enum OwnedSliceInner<'a, T: 'a + Sized> {
/// A ref to a raw slice and length
RefRaw(*const T, usize),
RefRaw(*const T, usize, UnsafeMarker),
/// A ref to a slice
Ref(&'a [T]),
/// A ref to an owned [`Vec`]
@ -191,7 +313,7 @@ impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSliceInner<'a, T> {
S: Serializer,
{
match self {
OwnedSliceInner::RefRaw(rr, len) => unsafe {
OwnedSliceInner::RefRaw(rr, len, _) => unsafe {
slice::from_raw_parts(*rr, *len).serialize(se)
},
OwnedSliceInner::Ref(r) => r.serialize(se),
@ -239,14 +361,14 @@ impl<'a, T> OwnedSlice<'a, T> {
#[must_use]
pub unsafe fn from_raw_parts(ptr: *const T, len: usize) -> Self {
Self {
inner: OwnedSliceInner::RefRaw(ptr, len),
inner: OwnedSliceInner::RefRaw(ptr, len, UnsafeMarker::new()),
}
}
/// Truncate the inner slice or vec returning the old size on success or `None` on failure
pub fn truncate(&mut self, new_len: usize) -> Option<usize> {
match &mut self.inner {
OwnedSliceInner::RefRaw(_rr, len) => {
OwnedSliceInner::RefRaw(_rr, len, _) => {
let tmp = *len;
if new_len <= tmp {
*len = new_len;
@ -323,7 +445,9 @@ impl<'a, T> From<OwnedMutSlice<'a, T>> for OwnedSlice<'a, T> {
fn from(mut_slice: OwnedMutSlice<'a, T>) -> Self {
Self {
inner: match mut_slice.inner {
OwnedMutSliceInner::RefRaw(ptr, len) => OwnedSliceInner::RefRaw(ptr as _, len),
OwnedMutSliceInner::RefRaw(ptr, len, unsafe_marker) => {
OwnedSliceInner::RefRaw(ptr as _, len, unsafe_marker)
}
OwnedMutSliceInner::Ref(r) => OwnedSliceInner::Ref(r as _),
OwnedMutSliceInner::Owned(v) => OwnedSliceInner::Owned(v),
},
@ -338,7 +462,7 @@ impl<'a, T: Sized> AsSlice for OwnedSlice<'a, T> {
fn as_slice(&self) -> &[T] {
match &self.inner {
OwnedSliceInner::Ref(r) => r,
OwnedSliceInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts(*rr, *len) },
OwnedSliceInner::RefRaw(rr, len, _) => unsafe { slice::from_raw_parts(*rr, *len) },
OwnedSliceInner::Owned(v) => v.as_slice(),
}
}
@ -351,7 +475,7 @@ where
#[must_use]
fn is_owned(&self) -> bool {
match self.inner {
OwnedSliceInner::RefRaw(_, _) | OwnedSliceInner::Ref(_) => false,
OwnedSliceInner::RefRaw(..) | OwnedSliceInner::Ref(_) => false,
OwnedSliceInner::Owned(_) => true,
}
}
@ -359,7 +483,7 @@ where
#[must_use]
fn into_owned(self) -> Self {
match self.inner {
OwnedSliceInner::RefRaw(rr, len) => Self {
OwnedSliceInner::RefRaw(rr, len, _) => Self {
inner: OwnedSliceInner::Owned(unsafe { slice::from_raw_parts(rr, len).to_vec() }),
},
OwnedSliceInner::Ref(r) => Self {
@ -392,7 +516,7 @@ where
#[derive(Debug)]
pub enum OwnedMutSliceInner<'a, T: 'a + Sized> {
/// A raw ptr to a memory location and a length
RefRaw(*mut T, usize),
RefRaw(*mut T, usize, UnsafeMarker),
/// A ptr to a mutable slice of the type
Ref(&'a mut [T]),
/// An owned [`Vec`] of the type
@ -405,7 +529,7 @@ impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedMutSliceInner<'a, T> {
S: Serializer,
{
match self {
OwnedMutSliceInner::RefRaw(rr, len) => {
OwnedMutSliceInner::RefRaw(rr, len, _) => {
unsafe { slice::from_raw_parts_mut(*rr, *len) }.serialize(se)
}
OwnedMutSliceInner::Ref(r) => r.serialize(se),
@ -466,7 +590,7 @@ impl<'a, T: 'a + Sized> OwnedMutSlice<'a, T> {
}
} else {
Self {
inner: OwnedMutSliceInner::RefRaw(ptr, len),
inner: OwnedMutSliceInner::RefRaw(ptr, len, UnsafeMarker::new()),
}
}
}
@ -474,7 +598,7 @@ impl<'a, T: 'a + Sized> OwnedMutSlice<'a, T> {
/// Truncate the inner slice or vec returning the old size on success or `None` on failure
pub fn truncate(&mut self, new_len: usize) -> Option<usize> {
match &mut self.inner {
OwnedMutSliceInner::RefRaw(_rr, len) => {
OwnedMutSliceInner::RefRaw(_rr, len, _) => {
let tmp = *len;
if new_len <= tmp {
*len = new_len;
@ -521,7 +645,7 @@ impl<'a, T: Sized> AsSlice for OwnedMutSlice<'a, T> {
#[must_use]
fn as_slice(&self) -> &[T] {
match &self.inner {
OwnedMutSliceInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts(*rr, *len) },
OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe { slice::from_raw_parts(*rr, *len) },
OwnedMutSliceInner::Ref(r) => r,
OwnedMutSliceInner::Owned(v) => v.as_slice(),
}
@ -533,7 +657,9 @@ impl<'a, T: Sized> AsMutSlice for OwnedMutSlice<'a, T> {
#[must_use]
fn as_mut_slice(&mut self) -> &mut [T] {
match &mut self.inner {
OwnedMutSliceInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts_mut(*rr, *len) },
OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe {
slice::from_raw_parts_mut(*rr, *len)
},
OwnedMutSliceInner::Ref(r) => r,
OwnedMutSliceInner::Owned(v) => v.as_mut_slice(),
}
@ -547,7 +673,7 @@ where
#[must_use]
fn is_owned(&self) -> bool {
match self.inner {
OwnedMutSliceInner::RefRaw(_, _) | OwnedMutSliceInner::Ref(_) => false,
OwnedMutSliceInner::RefRaw(..) | OwnedMutSliceInner::Ref(_) => false,
OwnedMutSliceInner::Owned(_) => true,
}
}
@ -555,7 +681,7 @@ where
#[must_use]
fn into_owned(self) -> Self {
let vec = match self.inner {
OwnedMutSliceInner::RefRaw(rr, len) => unsafe {
OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe {
slice::from_raw_parts_mut(rr, len).to_vec()
},
OwnedMutSliceInner::Ref(r) => r.to_vec(),

View File

@ -3,11 +3,11 @@
#[cfg(feature = "alloc")]
use alloc::{rc::Rc, string::ToString};
use core::fmt::Debug;
#[cfg(feature = "alloc")]
use core::fmt::Display;
#[cfg(feature = "alloc")]
use core::{cell::RefCell, fmt, mem::ManuallyDrop};
use core::{fmt::Debug, mem};
#[cfg(feature = "std")]
use std::env;
#[cfg(all(unix, feature = "std", not(target_os = "haiku")))]
@ -204,52 +204,24 @@ pub trait ShMem: Sized + Debug + Clone + AsSlice<Entry = u8> + AsMutSlice<Entry
self.len() == 0
}
/// Convert to an owned object reference
///
/// # Safety
/// This function is not safe as the object may be not initialized.
/// The user is responsible to initialize the object with something like
/// `*shmem.as_object_mut::<T>() = T::new();`
unsafe fn as_object<T: Sized + 'static>(&self) -> &T {
assert!(self.len() >= core::mem::size_of::<T>());
(self.as_slice().as_ptr() as *const () as *const T)
.as_ref()
.unwrap()
/// 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)
} else {
None
}
}
/// Convert to an owned object mutable reference
///
/// # Safety
/// This function is not safe as the object may be not initialized.
/// The user is responsible to initialize the object with something like
/// `*shmem.as_object_mut::<T>() = T::new();`
unsafe fn as_object_mut<T: Sized + 'static>(&mut self) -> &mut T {
assert!(self.len() >= core::mem::size_of::<T>());
(self.as_mut_slice().as_mut_ptr() as *mut () as *mut T)
.as_mut()
.unwrap()
/// Convert to a mut ptr of a given type, checking the size.
/// If the map is too small, returns `None`
fn as_mut_ptr_of<T: Sized>(&mut self) -> Option<*mut T> {
if self.len() >= mem::size_of::<T>() {
Some(self.as_mut_slice().as_mut_ptr() as *mut T)
} else {
None
}
/// Convert to a slice of type &\[T\]
///
/// # Safety
/// This function is not safe as the object may be not initialized.
/// The user is responsible to initialize the objects in the slice
unsafe fn as_objects_slice<T: Sized + 'static>(&self, len: usize) -> &[T] {
assert!(self.len() >= core::mem::size_of::<T>() * len);
let ptr = self.as_slice().as_ptr() as *const () as *const T;
core::slice::from_raw_parts(ptr, len)
}
/// Convert to a slice of type &mut \[T\]
///
/// # Safety
/// This function is not safe as the object may be not initialized.
/// The user is responsible to initialize the objects in the slice
unsafe fn as_objects_slice_mut<T: Sized + 'static>(&mut self, len: usize) -> &mut [T] {
assert!(self.len() >= core::mem::size_of::<T>() * len);
let ptr = self.as_mut_slice().as_mut_ptr() as *mut () as *mut T;
core::slice::from_raw_parts_mut(ptr, len)
}
/// Get the description of the shared memory mapping
@ -287,25 +259,20 @@ pub trait ShMemProvider: Clone + Default + Debug {
/// Get a mapping given its id and size
fn shmem_from_id_and_size(&mut self, id: ShMemId, size: usize) -> Result<Self::ShMem, Error>;
/// Create a new shared memory mapping to hold an object of the given type
fn new_shmem_object<T: Sized + 'static>(&mut self) -> Result<Self::ShMem, Error> {
self.new_shmem(core::mem::size_of::<T>())
/// Create a new shared memory mapping to hold an object of the given type, and initializes it with the given value.
fn new_on_shmem<T: Sized + 'static>(&mut self, value: T) -> Result<Self::ShMem, Error> {
self.uninit_on_shmem::<T>().map(|mut shmem| {
// # Safety
// The map has been created at this point in time, and is large enough.
// The map is fresh from the OS and, hence, the pointer should be properly aligned for any object.
unsafe { shmem.as_mut_ptr_of::<T>().unwrap().write_volatile(value) };
shmem
})
}
/// Create a new shared memory mapping to hold an array of objects of the given type
fn new_shmem_objects_array<T: Sized + 'static>(
&mut self,
len: usize,
) -> Result<Self::ShMem, Error> {
self.new_shmem(core::mem::size_of::<T>() * len)
}
/// Get a mapping given its id to hold an object of the given type
fn shmem_object_from_id<T: Sized + 'static>(
&mut self,
id: ShMemId,
) -> Result<Self::ShMem, Error> {
self.shmem_from_id_and_size(id, core::mem::size_of::<T>())
/// Create a new shared memory mapping to hold an object of the given type, and initializes it with the given value.
fn uninit_on_shmem<T: Sized + 'static>(&mut self) -> Result<Self::ShMem, Error> {
self.new_shmem(mem::size_of::<T>())
}
/// Get a mapping given a description

View File

@ -115,8 +115,6 @@ use mimalloc::MiMalloc;
#[cfg(feature = "mimalloc")]
static GLOBAL: MiMalloc = MiMalloc;
static mut BACKTRACE: Option<u64> = None;
#[allow(clippy::struct_excessive_bools)]
struct CustomMutationStatus {
std_mutational: bool,
@ -184,11 +182,13 @@ macro_rules! fuzz_with {
use rand::{thread_rng, RngCore};
use std::{env::temp_dir, fs::create_dir, path::PathBuf};
use crate::{BACKTRACE, CustomMutationStatus};
use crate::corpus::{ArtifactCorpus, LibfuzzerCorpus};
use crate::feedbacks::{LibfuzzerCrashCauseFeedback, LibfuzzerKeepFeedback, ShrinkMapFeedback};
use crate::misc::should_use_grimoire;
use crate::observers::{MappedEdgeMapObserver, SizeValueObserver};
use crate::{
CustomMutationStatus,
corpus::{ArtifactCorpus, LibfuzzerCorpus},
feedbacks::{LibfuzzerCrashCauseFeedback, LibfuzzerKeepFeedback, ShrinkMapFeedback},
misc::should_use_grimoire,
observers::{MappedEdgeMapObserver, SizeValueObserver},
};
let edge_maker = &$edge_maker;
@ -213,9 +213,8 @@ macro_rules! fuzz_with {
let cmplog_observer = CmpLogObserver::new("cmplog", true);
// Create a stacktrace observer
let backtrace_observer = BacktraceObserver::new(
let backtrace_observer = BacktraceObserver::owned(
"BacktraceObserver",
unsafe { &mut BACKTRACE },
if $options.forks().is_some() || $options.tui() { libafl::observers::HarnessType::Child } else { libafl::observers::HarnessType::InProcess }
);

View File

@ -428,7 +428,7 @@ pub static mut libafl_cmplog_map_extended: AFLppCmpLogMap = AFLppCmpLogMap {
pub use libafl_cmplog_map as CMPLOG_MAP;
pub use libafl_cmplog_map_extended as CMPLOG_MAP_EXTENDED;
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
#[repr(C, packed)]
/// Comparison map compatible with AFL++ cmplog instrumentation
pub struct AFLppCmpLogMap {

View File

@ -179,11 +179,15 @@ where
{
/// Creates a new [`AFLppCmpLogObserver`] with the given name and map.
#[must_use]
pub fn new(name: &'static str, map: &'a mut AFLppCmpLogMap, add_meta: bool) -> Self {
pub fn new(
name: &'static str,
cmp_map: OwnedRefMut<'a, AFLppCmpLogMap>,
add_meta: bool,
) -> Self {
Self {
name: name.to_string(),
size: None,
cmp_map: OwnedRefMut::Ref(map),
cmp_map,
add_meta,
original: false,
phantom: PhantomData,
@ -198,15 +202,15 @@ where
#[must_use]
pub fn with_size(
name: &'static str,
map: &'a mut AFLppCmpLogMap,
cmp_map: OwnedRefMut<'a, AFLppCmpLogMap>,
add_meta: bool,
original: bool,
size: &'a mut usize,
size: OwnedRefMut<'a, usize>,
) -> Self {
Self {
name: name.to_string(),
size: Some(OwnedRefMut::Ref(size)),
cmp_map: OwnedRefMut::Ref(map),
size: Some(size),
cmp_map,
add_meta,
original,
phantom: PhantomData,