Skip to content

Commit 15708e0

Browse files
committed
Fix unsound transmute_copy
Reference: AlecGoncharow/message-passing-framework#1
1 parent efd7e99 commit 15708e0

File tree

1 file changed

+11
-17
lines changed

1 file changed

+11
-17
lines changed

hermes/src/message.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ impl<T: 'static + Copy + Sized + Send + Sync + std::fmt::Debug> Pod for T {}
1212

1313
pub trait Messageable: Pod {}
1414

15-
/// T represents an Enum which tells both sides what kind of message is being
15+
/// T represents should probably be a Enum which tells both sides what kind of message is being
1616
/// passed in the body of the message
1717
#[derive(Debug, Clone, Copy)]
1818
pub struct MessageHeader<T: Messageable> {
19-
/// The kind of invariant in the message body, used as an identifier
19+
/// Type of message`
2020
pub id: T,
2121
/// the length of the message in bytes
2222
pub size: u32,
@@ -54,19 +54,14 @@ impl<T: Messageable> Message<T> {
5454
unsafe {
5555
let data_ptr: *const V = &data;
5656
let byte_ptr: *const u8 = data_ptr as *const _;
57-
// SAFETY:
58-
// We are just reinterpetting the type as a slice of bytes and since the type is
59-
// constrained by the Pod trait we know everything on the type is actually on the type
60-
let byte_slice: &[u8] = std::slice::from_raw_parts(byte_ptr, std::mem::size_of::<V>());
61-
6257
// SAFETY:
6358
// Since we resized the Vec to fit the existing data along with the number of bytes in
6459
// the incoming type, we can be sure that there is enough space to copy the actual
6560
// data
6661
// The source is known to be aligned since it is just a reinterpetation of an existing
6762
// valid Pod type
6863
std::ptr::copy(
69-
&byte_slice[0],
64+
byte_ptr,
7065
self.body.as_mut_ptr().add(i),
7166
std::mem::size_of::<V>(),
7267
);
@@ -75,7 +70,7 @@ impl<T: Messageable> Message<T> {
7570
self.header.size = self.size();
7671
}
7772

78-
/// This will reinterpet the end of the message body's bytes as the type yo urequest,
73+
/// This will reinterpet the end of the message body's bytes as the type you request,
7974
/// there is no built in validation at the moment.
8075
pub fn pull<V: Pod>(&mut self) -> Result<V, MessageError> {
8176
let bytes = std::mem::size_of::<V>();
@@ -89,12 +84,6 @@ impl<T: Messageable> Message<T> {
8984
let new_len = self.body.len() - bytes;
9085

9186
let out: V = unsafe {
92-
// SAFETY:
93-
// We know the message has enough bytes to pull an instance of V out based on the
94-
// checks done above
95-
let data_ptr = self.body.as_ptr().add(new_len);
96-
let byte_slice: &[u8] = std::slice::from_raw_parts(data_ptr, bytes);
97-
9887
// SAFETY:
9988
// We know that the slice of bytes has the proper number of bytes to transmute into an
10089
// instance of `V` due to the above code deriving the values based on the `size_of` calls
@@ -104,7 +93,11 @@ impl<T: Messageable> Message<T> {
10493
// This call will reinterpet the bytes as an instance of `V`, there is currently not
10594
// parity check on the result of this reinterpetation, the burden of doing some
10695
// validation is currently on the caller
107-
std::mem::transmute_copy(&byte_slice[0])
96+
self.body
97+
.as_ptr()
98+
.offset(new_len as isize)
99+
.cast::<V>()
100+
.read_unaligned()
108101
};
109102

110103
self.body.resize(new_len, 0);
@@ -150,7 +143,8 @@ impl<T: Messageable> From<&[u8]> for Message<T> {
150143
panic!("no, this is not header");
151144
}
152145

153-
let header: MessageHeader<T> = unsafe { std::mem::transmute_copy(&bytes[0]) };
146+
let header: MessageHeader<T> =
147+
unsafe { bytes.as_ptr().cast::<MessageHeader<T>>().read_unaligned() };
154148

155149
if header.size != bytes_len as u32 {
156150
panic!(

0 commit comments

Comments
 (0)