From 4d293c33be8ac6d56bf14a2dba2235602d310336 Mon Sep 17 00:00:00 2001 From: NathanW Date: Mon, 19 Apr 2021 14:29:57 -0600 Subject: [PATCH] [bevy_core/bytes] Fix UB with accessing memory with incorrect alignment --- crates/bevy_core/src/bytes.rs | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/crates/bevy_core/src/bytes.rs b/crates/bevy_core/src/bytes.rs index f5846c67bce56..b18ee94d72275 100644 --- a/crates/bevy_core/src/bytes.rs +++ b/crates/bevy_core/src/bytes.rs @@ -46,14 +46,16 @@ pub trait FromBytes { impl FromBytes for T where - T: Byteable + Clone, + T: Byteable + Copy, { fn from_bytes(bytes: &[u8]) -> Self { - unsafe { - let byte_ptr = bytes.as_ptr(); - let ptr = byte_ptr as *const Self; - (*ptr).clone() - } + assert_eq!( + bytes.len(), + std::mem::size_of::(), + "Cannot convert byte slice `&[u8]` to type `{}`. They are not the same size.", + std::any::type_name::() + ); + unsafe { bytes.as_ptr().cast::().read_unaligned() } } } @@ -62,7 +64,7 @@ where T: Byteable, { fn as_bytes(&self) -> &[u8] { - let len = std::mem::size_of_val(self); + let len = std::mem::size_of::(); unsafe { core::slice::from_raw_parts(self as *const Self as *const u8, len) } } } @@ -166,15 +168,23 @@ where impl FromBytes for Vec where - T: Sized + Clone + Byteable, + T: Sized + Copy + Byteable, { fn from_bytes(bytes: &[u8]) -> Self { + assert_eq!( + bytes.len() % std::mem::size_of::(), + 0, + "Cannot convert byte slice `&[u8]` to type `Vec<{0}>`. Slice length is not a multiple of std::mem::size_of::<{0}>.", + std::any::type_name::(), + ); + + let len = bytes.len() / std::mem::size_of::(); + let mut vec = Vec::::with_capacity(len); unsafe { - let byte_ptr = bytes.as_ptr() as *const T; - let len = bytes.len() / std::mem::size_of::(); - let slice = core::slice::from_raw_parts::(byte_ptr, len); - slice.to_vec() + std::ptr::copy_nonoverlapping(bytes.as_ptr(), vec.as_mut_ptr() as *mut u8, bytes.len()); + vec.set_len(len); } + vec } }