strings: remove wide pointer cast in CappedString impl
`CappedString::as_bytes` previously used a wide pointer cast to obtain a `&[u8]` from the `[MaybeUninit<u8>; N]` buffer; it cast a `*const [MaybeUninit<u8>]` to a `*const [u8]` as an intermediate step. Although this seems to be valid and did not cause any UB detected by MIRI, it seems to be generally accepted that `slice::from_raw_parts` is the preferred way to transmute slices since it makes explicit the metadata (length in this case) of the new wide pointer. This is in contrast to casting with `as`, which implicitly copies the metadata from the old wide pointer into the new one. Therefore, this patch replaces the `as *const [u8]` conversion with a call to `slice::from_raw_parts`.
This commit is contained in:
1 parent
7253d95010
commit
8309e19a68
1 file changed
+9
-10
+9
-10
@@ -4,7 +4,7 @@ use core::{
|
|||||||
fmt,
|
fmt,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
mem::MaybeUninit,
|
mem::MaybeUninit,
|
||||||
ops, ptr, str,
|
ops, ptr, slice, str,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
@@ -443,17 +443,16 @@ impl<const N: usize> CappedString<N> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
// Get the slice of the buffer containing initialised string data.
|
// Get a pointer to the start of the buffer and convert it from a `*const MaybeUninit<u8>`
|
||||||
// SAFETY:
|
// to a `*const u8`. This conversion is valid because `MaybeUninit<u8>` has the same memory
|
||||||
// It is an invariant of `CappedString` that `self.len <= N`, so `..self.len` is a valid
|
// layout as `u8`.
|
||||||
// range over `self.buf`.
|
let data_ptr = self.buf.as_ptr() as *const u8;
|
||||||
let data_slice = unsafe { self.buf.get_unchecked(..usize::from(self.len)) };
|
|
||||||
|
|
||||||
// Convert the `&[MaybeUninit<u8>]` to a `&[u8]`.
|
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// `MaybeUninit<u8>` has the same memory layout as `u8`, and the first `self.len` bytes of
|
// It is an invariant of `CappedString` that the first `self.len` bytes of the buffer are
|
||||||
// the buffer are initialised, so this conversion is valid.
|
// initialised, so `data_ptr` is valid for reads of `self.len` bytes. `data_ptr` is
|
||||||
unsafe { &*(data_slice as *const [MaybeUninit<u8>] as *const [u8]) }
|
// trivially properly aligned, since `u8` has an alignment of 1.
|
||||||
|
unsafe { slice::from_raw_parts(data_ptr, usize::from(self.len)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
|||||||
Reference in new issue
Block a user