Skip to content

Commit fd09d72

Browse files
committed
Add safety contract for uninit valraw byte conversion
1 parent 491a368 commit fd09d72

2 files changed

Lines changed: 18 additions & 10 deletions

File tree

crates/wasmtime/src/runtime/rr.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! This feature is currently not optimized and under development
44
use crate::ValRaw;
5-
use ::core::mem::MaybeUninit;
5+
use ::core::{mem::MaybeUninit, slice};
66

77
/// Component-async-ABI is not supported for record/replay yet; add a feature gate
88
//const _: () = {
@@ -19,13 +19,13 @@ use ::core::mem::MaybeUninit;
1919
reason = "trait used as a bound for hooks despite not calling methods directly"
2020
)]
2121
pub trait FlatBytes {
22-
fn bytes(&self, size: u8) -> &[u8];
22+
unsafe fn bytes(&self, size: u8) -> &[u8];
2323
fn from_bytes(value: &[u8]) -> Self;
2424
}
2525

2626
impl FlatBytes for ValRaw {
2727
#[inline]
28-
fn bytes(&self, size: u8) -> &[u8] {
28+
unsafe fn bytes(&self, size: u8) -> &[u8] {
2929
&self.get_bytes()[..size as usize]
3030
}
3131
#[inline]
@@ -36,12 +36,20 @@ impl FlatBytes for ValRaw {
3636

3737
impl FlatBytes for MaybeUninit<ValRaw> {
3838
#[inline]
39-
fn bytes(&self, size: u8) -> &[u8] {
40-
// Uninitialized data is assumed and serialized, so hence
41-
// may contain some undefined values. But these are irrelevant
42-
// when serializing to `RRFuncArgVals`
43-
let val = unsafe { self.assume_init_ref() };
44-
val.bytes(size)
39+
/// SAFETY: the caller must ensure that 'size' number of bytes provided
40+
/// are initialized for the underlying ValRaw.
41+
/// When serializing for record/replay, uninitialized parts of the ValRaw
42+
/// are not relevant, so this only accesses initialized values as long as
43+
/// the size contract is upheld.
44+
unsafe fn bytes(&self, size: u8) -> &[u8] {
45+
// The cleanest way for this would use MaybeUninit::as_bytes and an assume_init(),
46+
// but that is currently only available in nightly.
47+
let ptr = self.as_ptr().cast::<MaybeUninit<u8>>();
48+
// SAFETY: the caller must ensure that 'size' bytes are initialized
49+
unsafe {
50+
let s = slice::from_raw_parts(ptr, size as usize);
51+
&*(s as *const [MaybeUninit<u8>] as *const [u8])
52+
}
4553
}
4654
#[inline]
4755
fn from_bytes(value: &[u8]) -> Self {

crates/wasmtime/src/runtime/rr/core/events.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl RRFuncArgVals {
6868
let mut bytes = Vec::new();
6969
let mut sizes = Vec::new();
7070
for (flat_size, arg) in flat.zip(args.iter()) {
71-
bytes.extend_from_slice(&arg.bytes(flat_size));
71+
bytes.extend_from_slice(unsafe { &arg.bytes(flat_size) });
7272
sizes.push(flat_size);
7373
}
7474
RRFuncArgVals { bytes, sizes }

0 commit comments

Comments
 (0)