No more (direct) mutable references to mutable statics (#2550)

* No more (direct) mutable references to mutable statics

* More

* Fix build, but it's unsafe dude

* more

* fmt

* More fix

* more?
This commit is contained in:
Dominik Maier 2024-09-24 03:29:49 +02:00 committed by GitHub
parent 691fd1f8cb
commit f0d85aaaa5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 130 additions and 75 deletions

View File

@ -938,7 +938,7 @@ pub trait AdaptiveSerializer {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::ptr::addr_of_mut; use core::ptr::{addr_of, addr_of_mut};
use libafl_bolts::{current_time, tuples::tuple_list, Named}; use libafl_bolts::{current_time, tuples::tuple_list, Named};
use tuple_list::tuple_list_type; use tuple_list::tuple_list_type;
@ -955,7 +955,8 @@ mod tests {
#[test] #[test]
fn test_event_serde() { fn test_event_serde() {
let obv = unsafe { let obv = unsafe {
StdMapObserver::from_mut_ptr("test", addr_of_mut!(MAP) as *mut u32, MAP.len()) let len = (*addr_of!(MAP)).len();
StdMapObserver::from_mut_ptr("test", addr_of_mut!(MAP) as *mut u32, len)
}; };
let map = tuple_list!(obv); let map = tuple_list!(obv);
let observers_buf = postcard::to_allocvec(&map).unwrap(); let observers_buf = postcard::to_allocvec(&map).unwrap();

View File

@ -1,6 +1,12 @@
//! Hitcount map observer is for implementing AFL's hit count bucket //! Hitcount map observer is for implementing AFL's hit count bucket
use alloc::{borrow::Cow, vec::Vec}; use alloc::{borrow::Cow, vec::Vec};
use core::{fmt::Debug, hash::Hash, mem::size_of, slice}; use core::{
fmt::Debug,
hash::Hash,
mem::size_of,
ptr::{addr_of, addr_of_mut},
slice,
};
use libafl_bolts::{AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, Truncate}; use libafl_bolts::{AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, Truncate};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -35,17 +41,19 @@ static mut COUNT_CLASS_LOOKUP_16: Vec<u16> = vec![];
/// ///
/// # Safety /// # Safety
/// ///
/// Calling this from multiple threads may be racey and hence leak 65k mem /// Calling this from multiple threads may be racey and hence leak 65k mem or even create a broken lookup vec.
fn init_count_class_16() { fn init_count_class_16() {
unsafe { unsafe {
if !COUNT_CLASS_LOOKUP_16.is_empty() { let count_class_lookup_16 = &mut *addr_of_mut!(COUNT_CLASS_LOOKUP_16);
if !count_class_lookup_16.is_empty() {
return; return;
} }
COUNT_CLASS_LOOKUP_16 = vec![0; 65536]; *count_class_lookup_16 = vec![0; 65536];
for i in 0..256 { for i in 0..256 {
for j in 0..256 { for j in 0..256 {
COUNT_CLASS_LOOKUP_16[(i << 8) + j] = count_class_lookup_16[(i << 8) + j] =
(u16::from(COUNT_CLASS_LOOKUP[i]) << 8) | u16::from(COUNT_CLASS_LOOKUP[j]); (u16::from(COUNT_CLASS_LOOKUP[i]) << 8) | u16::from(COUNT_CLASS_LOOKUP[j]);
} }
} }
@ -117,7 +125,7 @@ where
#[allow(clippy::unused_enumerate_index)] #[allow(clippy::unused_enumerate_index)]
for (_i, item) in map16[0..cnt].iter_mut().enumerate() { for (_i, item) in map16[0..cnt].iter_mut().enumerate() {
unsafe { unsafe {
*item = *COUNT_CLASS_LOOKUP_16.get_unchecked(*item as usize); *item = *(*addr_of!(COUNT_CLASS_LOOKUP_16)).get_unchecked(*item as usize);
} }
} }

View File

@ -446,7 +446,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::ptr::addr_of_mut; use core::ptr::{addr_of, addr_of_mut};
use libafl_bolts::{ use libafl_bolts::{
ownedref::OwnedMutSlice, ownedref::OwnedMutSlice,
@ -461,9 +461,10 @@ mod tests {
#[test] #[test]
fn test_observer_serde() { fn test_observer_serde() {
let obv = tuple_list!(TimeObserver::new("time"), unsafe { let obv = tuple_list!(TimeObserver::new("time"), unsafe {
let len = (*addr_of!(MAP)).len();
StdMapObserver::from_ownedref( StdMapObserver::from_ownedref(
"map", "map",
OwnedMutSlice::from_raw_parts_mut(addr_of_mut!(MAP) as *mut u32, MAP.len()), OwnedMutSlice::from_raw_parts_mut(addr_of_mut!(MAP) as *mut u32, len),
) )
}); });
let vec = postcard::to_allocvec(&obv).unwrap(); let vec = postcard::to_allocvec(&obv).unwrap();

View File

@ -992,7 +992,7 @@ impl SimpleFdLogger {
// The passed-in `fd` has to be a legal file descriptor to log to. // The passed-in `fd` has to be a legal file descriptor to log to.
// We also access a shared variable here. // We also access a shared variable here.
unsafe { unsafe {
LIBAFL_RAWFD_LOGGER.set_fd(log_fd); (*ptr::addr_of_mut!(LIBAFL_RAWFD_LOGGER)).set_fd(log_fd);
log::set_logger(&*ptr::addr_of!(LIBAFL_RAWFD_LOGGER))?; log::set_logger(&*ptr::addr_of!(LIBAFL_RAWFD_LOGGER))?;
} }
Ok(()) Ok(())

View File

@ -118,7 +118,12 @@ pub mod serdeany_registry {
boxed::Box, boxed::Box,
string::{String, ToString}, string::{String, ToString},
}; };
use core::{any::TypeId, fmt, hash::BuildHasherDefault}; use core::{
any::TypeId,
fmt,
hash::BuildHasherDefault,
ptr::{addr_of, addr_of_mut},
};
use hashbrown::{ use hashbrown::{
hash_map::{Values, ValuesMut}, hash_map::{Values, ValuesMut},
@ -156,7 +161,7 @@ pub mod serdeany_registry {
let id: TypeRepr = visitor.next_element()?.unwrap(); let id: TypeRepr = visitor.next_element()?.unwrap();
let cb = unsafe { let cb = unsafe {
REGISTRY (*addr_of!(REGISTRY))
.deserializers .deserializers
.as_ref() .as_ref()
.ok_or_else(|| .ok_or_else(||
@ -228,7 +233,7 @@ pub mod serdeany_registry {
T: crate::serdeany::SerdeAny + Serialize + serde::de::DeserializeOwned, T: crate::serdeany::SerdeAny + Serialize + serde::de::DeserializeOwned,
{ {
unsafe { unsafe {
REGISTRY.register::<T>(); (*addr_of_mut!(REGISTRY)).register::<T>();
} }
} }
@ -239,7 +244,7 @@ pub mod serdeany_registry {
/// It dereferences the `REGISTRY` hashmap and adds the given type to it. /// It dereferences the `REGISTRY` hashmap and adds the given type to it.
pub fn finalize() { pub fn finalize() {
unsafe { unsafe {
REGISTRY.finalize(); (*addr_of_mut!(REGISTRY)).finalize();
} }
} }
} }
@ -366,7 +371,7 @@ pub mod serdeany_registry {
assert!( assert!(
unsafe { unsafe {
REGISTRY (*addr_of!(REGISTRY))
.deserializers .deserializers
.as_ref() .as_ref()
.expect(super::ERR_EMPTY_TYPES_REGISTER) .expect(super::ERR_EMPTY_TYPES_REGISTER)
@ -629,7 +634,7 @@ pub mod serdeany_registry {
assert!( assert!(
unsafe { unsafe {
REGISTRY (*addr_of!(REGISTRY))
.deserializers .deserializers
.as_ref() .as_ref()
.expect(super::ERR_EMPTY_TYPES_REGISTER) .expect(super::ERR_EMPTY_TYPES_REGISTER)

View File

@ -58,9 +58,8 @@ where
impl BreakpointId { impl BreakpointId {
pub fn new() -> Self { pub fn new() -> Self {
static mut BREAKPOINT_ID_COUNTER: OnceLock<AtomicU64> = OnceLock::new(); static BREAKPOINT_ID_COUNTER: OnceLock<AtomicU64> = OnceLock::new();
let counter = BREAKPOINT_ID_COUNTER.get_or_init(|| AtomicU64::new(0));
let counter = unsafe { BREAKPOINT_ID_COUNTER.get_or_init(|| AtomicU64::new(0)) };
BreakpointId(counter.fetch_add(1, Ordering::SeqCst)) BreakpointId(counter.fetch_add(1, Ordering::SeqCst))
} }

View File

@ -3,7 +3,7 @@ use std::fmt::Debug;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl::{ use libafl::{
inputs::{HasTargetBytes, UsesInput}, inputs::{HasTargetBytes, UsesInput},
prelude::{HasExecutions, State}, state::{HasExecutions, State},
}; };
use libafl_qemu_sys::GuestPhysAddr; use libafl_qemu_sys::GuestPhysAddr;

View File

@ -100,6 +100,7 @@ pub fn python_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
} }
m.add_submodule(&mmapm)?; m.add_submodule(&mmapm)?;
#[cfg(emulation_mode = "usermode")]
m.add_class::<sys::MapInfo>()?; m.add_class::<sys::MapInfo>()?;
#[cfg(emulation_mode = "usermode")] #[cfg(emulation_mode = "usermode")]

View File

@ -1,4 +1,4 @@
use core::{cell::UnsafeCell, fmt::Debug}; use core::{cell::UnsafeCell, fmt::Debug, ptr::addr_of_mut};
use capstone::prelude::*; use capstone::prelude::*;
use libafl::{ use libafl::{
@ -541,13 +541,13 @@ impl Default for FullBacktraceCollector {
impl FullBacktraceCollector { impl FullBacktraceCollector {
pub fn new() -> Self { pub fn new() -> Self {
unsafe { CALLSTACKS = Some(ThreadLocal::new()) }; unsafe { *(&mut *addr_of_mut!(CALLSTACKS)) = Some(ThreadLocal::new()) };
Self {} Self {}
} }
pub fn reset(&mut self) { pub fn reset(&mut self) {
unsafe { unsafe {
for tls in CALLSTACKS.as_mut().unwrap().iter_mut() { for tls in (*addr_of_mut!(CALLSTACKS)).as_mut().unwrap().iter_mut() {
(*tls.get()).clear(); (*tls.get()).clear();
} }
} }
@ -555,7 +555,7 @@ impl FullBacktraceCollector {
pub fn backtrace() -> Option<&'static [GuestAddr]> { pub fn backtrace() -> Option<&'static [GuestAddr]> {
unsafe { unsafe {
if let Some(c) = CALLSTACKS.as_mut() { if let Some(c) = (*addr_of_mut!(CALLSTACKS)).as_mut() {
Some(&*c.get_or_default().get()) Some(&*c.get_or_default().get())
} else { } else {
None None
@ -578,7 +578,12 @@ impl CallTraceCollector for FullBacktraceCollector {
{ {
// TODO handle Thumb // TODO handle Thumb
unsafe { unsafe {
(*CALLSTACKS.as_mut().unwrap().get_or_default().get()).push(pc + call_len as GuestAddr); (*(*addr_of_mut!(CALLSTACKS))
.as_mut()
.unwrap()
.get_or_default()
.get())
.push(pc + call_len as GuestAddr);
} }
} }
@ -594,7 +599,11 @@ impl CallTraceCollector for FullBacktraceCollector {
S: Unpin + UsesInput, S: Unpin + UsesInput,
{ {
unsafe { unsafe {
let v = &mut *CALLSTACKS.as_mut().unwrap().get_or_default().get(); let v = &mut *(*addr_of_mut!(CALLSTACKS))
.as_mut()
.unwrap()
.get_or_default()
.get();
if !v.is_empty() { if !v.is_empty() {
// if *v.last().unwrap() == ret_addr { // if *v.last().unwrap() == ret_addr {
// v.pop(); // v.pop();

View File

@ -1,5 +1,4 @@
use core::{fmt::Debug, ops::Range}; use core::{cell::UnsafeCell, fmt::Debug, hash::BuildHasher, ops::Range, ptr::addr_of_mut};
use std::{cell::UnsafeCell, hash::BuildHasher};
use hashbrown::HashSet; use hashbrown::HashSet;
use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple}; use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple};
@ -311,7 +310,7 @@ impl HasInstrumentationFilter<QemuInstrumentationAddressRangeFilter> for () {
} }
fn filter_mut(&mut self) -> &mut QemuInstrumentationAddressRangeFilter { fn filter_mut(&mut self) -> &mut QemuInstrumentationAddressRangeFilter {
unsafe { EMPTY_ADDRESS_FILTER.get_mut() } unsafe { (*addr_of_mut!(EMPTY_ADDRESS_FILTER)).get_mut() }
} }
} }
@ -321,7 +320,7 @@ impl HasInstrumentationFilter<QemuInstrumentationPagingFilter> for () {
} }
fn filter_mut(&mut self) -> &mut QemuInstrumentationPagingFilter { fn filter_mut(&mut self) -> &mut QemuInstrumentationPagingFilter {
unsafe { EMPTY_PAGING_FILTER.get_mut() } unsafe { (*addr_of_mut!(EMPTY_PAGING_FILTER)).get_mut() }
} }
} }

View File

@ -3,16 +3,18 @@
//! This module exposes the low-level QEMU library through [`Qemu`]. //! This module exposes the low-level QEMU library through [`Qemu`].
//! To access higher-level features of QEMU, it is recommended to use [`crate::Emulator`] instead. //! To access higher-level features of QEMU, it is recommended to use [`crate::Emulator`] instead.
use core::fmt; use core::{
use std::{
cmp::{Ordering, PartialOrd}, cmp::{Ordering, PartialOrd},
fmt,
ptr::{self, addr_of_mut},
};
use std::{
ffi::{c_void, CString}, ffi::{c_void, CString},
fmt::{Display, Formatter}, fmt::{Display, Formatter},
intrinsics::{copy_nonoverlapping, transmute}, intrinsics::{copy_nonoverlapping, transmute},
mem::MaybeUninit, mem::MaybeUninit,
ops::Range, ops::Range,
pin::Pin, pin::Pin,
ptr,
}; };
use libafl_bolts::os::unix_signals::Signal; use libafl_bolts::os::unix_signals::Signal;
@ -141,7 +143,7 @@ pub struct QemuMemoryChunk {
} }
#[allow(clippy::vec_box)] #[allow(clippy::vec_box)]
static mut GDB_COMMANDS: Vec<Box<FatPtr>> = vec![]; static mut GDB_COMMANDS: Vec<Box<FatPtr>> = Vec::new();
unsafe extern "C" fn gdb_cmd(data: *mut c_void, buf: *mut u8, len: usize) -> bool { unsafe extern "C" fn gdb_cmd(data: *mut c_void, buf: *mut u8, len: usize) -> bool {
unsafe { unsafe {
@ -768,16 +770,16 @@ impl Qemu {
id.remove(invalidate_block) id.remove(invalidate_block)
} }
// # Safety
// Calling this multiple times concurrently will access static variables and is unsafe.
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub fn add_gdb_cmd(&self, callback: Box<dyn FnMut(&Self, &str) -> bool>) { pub unsafe fn add_gdb_cmd(&self, callback: Box<dyn FnMut(&Self, &str) -> bool>) {
unsafe {
let fat: Box<FatPtr> = Box::new(transmute::< let fat: Box<FatPtr> = Box::new(transmute::<
Box<dyn for<'a, 'b> FnMut(&'a Qemu, &'b str) -> bool>, Box<dyn for<'a, 'b> FnMut(&'a Qemu, &'b str) -> bool>,
FatPtr, FatPtr,
>(callback)); >(callback));
libafl_qemu_add_gdb_cmd(Some(gdb_cmd), ptr::from_ref(&*fat) as *mut c_void); libafl_qemu_add_gdb_cmd(Some(gdb_cmd), ptr::from_ref(&*fat) as *mut c_void);
GDB_COMMANDS.push(fat); (*addr_of_mut!(GDB_COMMANDS)).push(fat);
}
} }
pub fn gdb_reply(&self, output: &str) { pub fn gdb_reply(&self, output: &str) {
@ -956,7 +958,10 @@ pub mod pybind {
static mut PY_GENERIC_HOOKS: Vec<(GuestAddr, PyObject)> = vec![]; static mut PY_GENERIC_HOOKS: Vec<(GuestAddr, PyObject)> = vec![];
extern "C" fn py_generic_hook_wrapper(idx: u64, _pc: GuestAddr) { extern "C" fn py_generic_hook_wrapper(idx: u64, _pc: GuestAddr) {
let obj = unsafe { &PY_GENERIC_HOOKS[idx as usize].1 }; let obj = unsafe {
let hooks = &mut *core::ptr::addr_of_mut!(PY_GENERIC_HOOKS);
&hooks[idx as usize].1
};
Python::with_gil(|py| { Python::with_gil(|py| {
obj.call0(py).expect("Error in the hook"); obj.call0(py).expect("Error in the hook");
}); });
@ -1032,8 +1037,9 @@ pub mod pybind {
fn set_hook(&self, addr: GuestAddr, hook: PyObject) { fn set_hook(&self, addr: GuestAddr, hook: PyObject) {
unsafe { unsafe {
let idx = PY_GENERIC_HOOKS.len(); let hooks = &mut *core::ptr::addr_of_mut!(PY_GENERIC_HOOKS);
PY_GENERIC_HOOKS.push((addr, hook)); let idx = hooks.len();
hooks.push((addr, hook));
self.qemu.hooks().add_instruction_hooks( self.qemu.hooks().add_instruction_hooks(
idx as u64, idx as u64,
addr, addr,
@ -1045,7 +1051,8 @@ pub mod pybind {
fn remove_hooks_at(&self, addr: GuestAddr) -> usize { fn remove_hooks_at(&self, addr: GuestAddr) -> usize {
unsafe { unsafe {
PY_GENERIC_HOOKS.retain(|(a, _)| *a != addr); let hooks = &mut *core::ptr::addr_of_mut!(PY_GENERIC_HOOKS);
hooks.retain(|(a, _)| *a != addr);
} }
self.qemu.hooks().remove_instruction_hooks_at(addr, true) self.qemu.hooks().remove_instruction_hooks_at(addr, true)
} }

View File

@ -261,7 +261,7 @@ pub mod pybind {
a6: u64, a6: u64,
a7: u64, a7: u64,
) -> SyscallHookResult { ) -> SyscallHookResult {
unsafe { PY_SYSCALL_HOOK.as_ref() }.map_or_else( unsafe { (*core::ptr::addr_of!(PY_SYSCALL_HOOK)).as_ref() }.map_or_else(
|| SyscallHookResult::new(None), || SyscallHookResult::new(None),
|obj| { |obj| {
let args = (sys_num, a0, a1, a2, a3, a4, a5, a6, a7); let args = (sys_num, a0, a1, a2, a3, a4, a5, a6, a7);
@ -340,7 +340,7 @@ pub mod pybind {
fn set_syscall_hook(&self, hook: PyObject) { fn set_syscall_hook(&self, hook: PyObject) {
unsafe { unsafe {
PY_SYSCALL_HOOK = Some(hook); *(&mut *core::ptr::addr_of_mut!(PY_SYSCALL_HOOK)) = Some(hook);
} }
self.qemu self.qemu
.hooks() .hooks()

View File

@ -1,4 +1,4 @@
use core::marker::PhantomData; use core::{marker::PhantomData, ptr::addr_of_mut};
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl::{ use libafl::{
@ -12,9 +12,11 @@ pub static mut FUNCTION_LIST: Lazy<HashMap<usize, usize>> = Lazy::new(HashMap::n
#[no_mangle] #[no_mangle]
/// The runtime code inserted at every callinst invokation (if you used the function-logging.cc) /// The runtime code inserted at every callinst invokation (if you used the function-logging.cc)
/// # Safety /// # Safety
/// unsafe because it touches pub static mut /// unsafe because it touches the pub static mut `FUNCTION_LIST`.
/// May not be called concurrently.
pub unsafe extern "C" fn __libafl_target_call_hook(id: usize) { pub unsafe extern "C" fn __libafl_target_call_hook(id: usize) {
*FUNCTION_LIST.entry(id).or_insert(0) += 1; let function_list = &mut *addr_of_mut!(FUNCTION_LIST);
*function_list.entry(id).or_insert(0) += 1;
} }
/// The empty struct to clear the `FUNCTION_LIST` before the execution /// The empty struct to clear the `FUNCTION_LIST` before the execution
@ -41,7 +43,13 @@ where
fn pre_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) { fn pre_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {
// clear it before the execution // clear it before the execution
unsafe { FUNCTION_LIST.clear() } // # Safety
// This typically happens while no other execution happens.
// In theory there is a race, but we can ignore it _for this use case_.
unsafe {
let function_list = &mut *addr_of_mut!(FUNCTION_LIST);
function_list.clear();
}
} }
fn post_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {} fn post_exec(&mut self, _state: &mut S, _input: &<S as UsesInput>::Input) {}

View File

@ -7,6 +7,7 @@
feature = "sancov_ctx" feature = "sancov_ctx"
))] ))]
use alloc::borrow::Cow; use alloc::borrow::Cow;
use core::ptr::addr_of_mut;
#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[cfg(any(target_os = "linux", target_vendor = "apple"))]
use libafl::{mutators::Tokens, Error}; use libafl::{mutators::Tokens, Error};
@ -157,7 +158,7 @@ pub fn edges_map_mut_ptr() -> *mut u8 {
assert!(!EDGES_MAP_PTR.is_null()); assert!(!EDGES_MAP_PTR.is_null());
EDGES_MAP_PTR EDGES_MAP_PTR
} else { } else {
EDGES_MAP.as_mut_ptr() addr_of_mut!(EDGES_MAP) as *mut u8
} }
} }
} }

View File

@ -1,6 +1,6 @@
//! [`LLVM` `8-bit-counters`](https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards) runtime for `LibAFL`. //! [`LLVM` `8-bit-counters`](https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards) runtime for `LibAFL`.
use alloc::vec::Vec; use alloc::vec::Vec;
use core::ptr::addr_of_mut; use core::ptr::{addr_of, addr_of_mut};
use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut}; use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut};
@ -14,7 +14,8 @@ pub static mut COUNTERS_MAPS: Vec<OwnedMutSlice<'static, u8>> = Vec::new();
/// You are responsible for ensuring there is no multi-mutability! /// You are responsible for ensuring there is no multi-mutability!
#[must_use] #[must_use]
pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> { pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> {
COUNTERS_MAPS let counter_maps = &*addr_of!(COUNTERS_MAPS);
counter_maps
.iter() .iter()
.map(|counters| { .map(|counters| {
OwnedMutSlice::from_raw_parts_mut( OwnedMutSlice::from_raw_parts_mut(
@ -31,7 +32,8 @@ pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> {
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) { pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) {
unsafe { unsafe {
for existing in &mut *addr_of_mut!(COUNTERS_MAPS) { let counter_maps = &mut *addr_of_mut!(COUNTERS_MAPS);
for existing in counter_maps {
let range = existing.as_slice_mut().as_mut_ptr() let range = existing.as_slice_mut().as_mut_ptr()
..=existing ..=existing
.as_slice_mut() .as_slice_mut()
@ -46,8 +48,10 @@ pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut
return; return;
} }
} }
let counter_maps = &mut *addr_of_mut!(COUNTERS_MAPS);
// we didn't overlap; keep going // we didn't overlap; keep going
COUNTERS_MAPS.push(OwnedMutSlice::from_raw_parts_mut( counter_maps.push(OwnedMutSlice::from_raw_parts_mut(
start, start,
stop.offset_from(start) as usize, stop.offset_from(start) as usize,
)); ));
@ -327,7 +331,10 @@ mod observers {
type IntoIter = Flatten<Iter<'it, OwnedMutSlice<'static, u8>>>; type IntoIter = Flatten<Iter<'it, OwnedMutSlice<'static, u8>>>;
fn as_iter(&'it self) -> Self::IntoIter { fn as_iter(&'it self) -> Self::IntoIter {
unsafe { COUNTERS_MAPS.iter().flatten() } unsafe {
let counters_maps = &*addr_of!(COUNTERS_MAPS);
counters_maps.iter().flatten()
}
} }
} }
@ -336,7 +343,10 @@ mod observers {
type IntoIterMut = Flatten<IterMut<'it, OwnedMutSlice<'static, u8>>>; type IntoIterMut = Flatten<IterMut<'it, OwnedMutSlice<'static, u8>>>;
fn as_iter_mut(&'it mut self) -> Self::IntoIterMut { fn as_iter_mut(&'it mut self) -> Self::IntoIterMut {
unsafe { COUNTERS_MAPS.iter_mut().flatten() } unsafe {
let counters_maps = &mut *addr_of_mut!(COUNTERS_MAPS);
counters_maps.iter_mut().flatten()
}
} }
} }

View File

@ -65,6 +65,8 @@ pub static SHR_4: Ngram4 = Ngram4::from_array([1, 1, 1, 1]);
#[rustversion::nightly] #[rustversion::nightly]
pub static SHR_8: Ngram8 = Ngram8::from_array([1, 1, 1, 1, 1, 1, 1, 1]); pub static SHR_8: Ngram8 = Ngram8::from_array([1, 1, 1, 1, 1, 1, 1, 1]);
static mut PC_TABLES: Vec<&'static [PcTableEntry]> = Vec::new();
use alloc::vec::Vec; use alloc::vec::Vec;
#[cfg(any( #[cfg(any(
feature = "sancov_ngram4", feature = "sancov_ngram4",
@ -184,17 +186,19 @@ unsafe fn update_ngram(pos: usize) -> usize {
let mut reduced = pos; let mut reduced = pos;
#[cfg(feature = "sancov_ngram4")] #[cfg(feature = "sancov_ngram4")]
{ {
PREV_ARRAY_4 = PREV_ARRAY_4.rotate_elements_right::<1>(); let prev_array_4 = &mut *core::ptr::addr_of_mut!(PREV_ARRAY_4);
PREV_ARRAY_4.shl_assign(SHR_4); *prev_array_4 = prev_array_4.rotate_elements_right::<1>();
PREV_ARRAY_4.as_mut_array()[0] = pos as u32; prev_array_4.shl_assign(SHR_4);
reduced = PREV_ARRAY_4.reduce_xor() as usize; prev_array_4.as_mut_array()[0] = pos as u32;
reduced = prev_array_4.reduce_xor() as usize;
} }
#[cfg(feature = "sancov_ngram8")] #[cfg(feature = "sancov_ngram8")]
{ {
PREV_ARRAY_8 = PREV_ARRAY_8.rotate_elements_right::<1>(); let prev_array_8 = &mut *core::ptr::addr_of_mut!(PREV_ARRAY_8);
PREV_ARRAY_8.shl_assign(SHR_8); *prev_array_8 = prev_array_8.rotate_elements_right::<1>();
PREV_ARRAY_8.as_mut_array()[0] = pos as u32; prev_array_8.shl_assign(SHR_8);
reduced = PREV_ARRAY_8.reduce_xor() as usize; prev_array_8.as_mut_array()[0] = pos as u32;
reduced = prev_array_8.reduce_xor() as usize;
} }
reduced %= EDGES_MAP_SIZE_IN_USE; reduced %= EDGES_MAP_SIZE_IN_USE;
reduced reduced
@ -269,7 +273,7 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: *mut u32) {
pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) { pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) {
#[cfg(feature = "pointer_maps")] #[cfg(feature = "pointer_maps")]
if EDGES_MAP_PTR.is_null() { if EDGES_MAP_PTR.is_null() {
EDGES_MAP_PTR = EDGES_MAP.as_mut_ptr(); EDGES_MAP_PTR = core::ptr::addr_of_mut!(EDGES_MAP) as *mut u8;
} }
if start == stop || *start != 0 { if start == stop || *start != 0 {
@ -292,8 +296,6 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32
} }
} }
static mut PC_TABLES: Vec<&'static [PcTableEntry]> = Vec::new();
#[no_mangle] #[no_mangle]
unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) { unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) {
// "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C." // "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C."
@ -312,7 +314,8 @@ unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *c
"Unaligned PC Table - start: {pcs_beg:x?} end: {pcs_end:x?}" "Unaligned PC Table - start: {pcs_beg:x?} end: {pcs_end:x?}"
); );
PC_TABLES.push(slice::from_raw_parts(pcs_beg as *const PcTableEntry, len)); let pc_tables = &mut *core::ptr::addr_of_mut!(PC_TABLES);
pc_tables.push(slice::from_raw_parts(pcs_beg as *const PcTableEntry, len));
} }
/// An entry to the `sanitizer_cov` `pc_table` /// An entry to the `sanitizer_cov` `pc_table`
@ -338,8 +341,11 @@ impl PcTableEntry {
} }
/// Returns an iterator over the PC tables. If no tables were registered, this will be empty. /// Returns an iterator over the PC tables. If no tables were registered, this will be empty.
pub fn sanitizer_cov_pc_table() -> impl Iterator<Item = &'static [PcTableEntry]> { pub fn sanitizer_cov_pc_table<'a>() -> impl Iterator<Item = &'a [PcTableEntry]> {
// SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So // SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So
// there's no TOCTOU issue. // there's no TOCTOU issue.
unsafe { PC_TABLES.iter().copied() } unsafe {
let pc_tables = &*core::ptr::addr_of!(PC_TABLES);
pc_tables.iter().copied()
}
} }