Skip to content

Commit

Permalink
[bevy_core/bytes] Fix UB with accessing memory with incorrect alignment
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanSWard committed Apr 20, 2021
1 parent 20673db commit 4d293c3
Showing 1 changed file with 22 additions and 12 deletions.
34 changes: 22 additions & 12 deletions crates/bevy_core/src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ pub trait FromBytes {

impl<T> 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::<T>(),
"Cannot convert byte slice `&[u8]` to type `{}`. They are not the same size.",
std::any::type_name::<T>()
);
unsafe { bytes.as_ptr().cast::<T>().read_unaligned() }
}
}

Expand All @@ -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::<T>();
unsafe { core::slice::from_raw_parts(self as *const Self as *const u8, len) }
}
}
Expand Down Expand Up @@ -166,15 +168,23 @@ where

impl<T> FromBytes for Vec<T>
where
T: Sized + Clone + Byteable,
T: Sized + Copy + Byteable,
{
fn from_bytes(bytes: &[u8]) -> Self {
assert_eq!(
bytes.len() % std::mem::size_of::<T>(),
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::<T>(),
);

let len = bytes.len() / std::mem::size_of::<T>();
let mut vec = Vec::<T>::with_capacity(len);
unsafe {
let byte_ptr = bytes.as_ptr() as *const T;
let len = bytes.len() / std::mem::size_of::<T>();
let slice = core::slice::from_raw_parts::<T>(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
}
}

Expand Down

0 comments on commit 4d293c3

Please sign in to comment.