Skip to content

Commit b5c89a6

Browse files
committed
Minimize safety hazards in slice_as_uninit[_mut].
In each function, explicitly use the implicit conversion of `&[T]` to `*const T`/`&mut [T]` to `* mut T` to eliminate one `as *const T`/`as *mut T` respectively. Instead of relying on the remaining cast in each function being valid for all `T`, reduce the scope of the assumption to `u8`, and add a TODO avoid eliminating the use of the assumption.
1 parent d77e000 commit b5c89a6

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

src/util.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,25 @@ pub fn uninit_slice_fill_zero(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] {
1717
}
1818

1919
#[inline(always)]
20-
pub fn slice_as_uninit<T>(slice: &[T]) -> &[MaybeUninit<T>] {
21-
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
22-
// There is no risk of writing a `MaybeUninit<T>` into the result since
20+
pub fn slice_as_uninit(slice: &[u8]) -> &[MaybeUninit<u8>] {
21+
// TODO: MSRV(1.76): Use `core::ptr::from_ref`.
22+
let ptr: *const [u8] = slice;
23+
// SAFETY: `MaybeUninit<u8>` is guaranteed to be layout-compatible with `u8`.
24+
// There is no risk of writing a `MaybeUninit<u8>` into the result since
2325
// the result isn't mutable.
24-
unsafe { &*(slice as *const [T] as *const [MaybeUninit<T>]) }
26+
// FIXME: Avoid relying on this assumption and eliminate this cast.
27+
unsafe { &*(ptr as *const [MaybeUninit<u8>]) }
2528
}
2629

2730
/// View an mutable initialized array as potentially-uninitialized.
2831
///
2932
/// This is unsafe because it allows assigning uninitialized values into
3033
/// `slice`, which would be undefined behavior.
3134
#[inline(always)]
32-
pub unsafe fn slice_as_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {
33-
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
34-
&mut *(slice as *mut [T] as *mut [MaybeUninit<T>])
35+
pub unsafe fn slice_as_uninit_mut(slice: &mut [u8]) -> &mut [MaybeUninit<u8>] {
36+
// TODO: MSRV(1.76): Use `core::ptr::from_mut`.
37+
let ptr: *mut [u8] = slice;
38+
// SAFETY: `MaybeUninit<u8>` is guaranteed to be layout-compatible with `u8`.
39+
// FIXME: Avoid relying on this assumption and eliminate this cast.
40+
&mut *(ptr as *mut [MaybeUninit<u8>])
3541
}

0 commit comments

Comments
 (0)