Skip to content

Commit d588ffc

Browse files
committed
Fix unaligned memory reads
1 parent 987b7f4 commit d588ffc

File tree

1 file changed

+33
-19
lines changed

1 file changed

+33
-19
lines changed

src/task_impl/unpark_handle.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::ptr;
2-
use core::mem::{forget, size_of};
2+
use core::mem::{self, forget, size_of};
33
use core::marker::PhantomData;
44
use core::cell::Cell;
55
use super::Unpark;
@@ -54,9 +54,9 @@ pub const MAX_UNPARK_BYTES : usize = _MAX_UNPARK_BYTES;
5454
/// A VTable that knows how to clone because the data has a maximum size.
5555
#[derive(Copy)]
5656
struct UnparkVtable {
57-
unpark: fn(*const ()),
58-
clone_to_byte_buffer: fn(*const ()) -> [u8; MAX_UNPARK_BYTES],
59-
drop_in_place: unsafe fn(*mut ()),
57+
unpark: unsafe fn(*const ()),
58+
clone_to_byte_buffer: unsafe fn(*const ()) -> [u8; MAX_UNPARK_BYTES],
59+
manual_drop: unsafe fn(*const ()),
6060
}
6161

6262
impl Clone for UnparkVtable {
@@ -67,29 +67,31 @@ impl Clone for UnparkVtable {
6767

6868
impl UnparkVtable {
6969
fn new<T: Unpark + Clone>() -> UnparkVtable {
70-
assert!(size_of::<T>() <= MAX_UNPARK_BYTES);
7170
UnparkVtable {
7271
unpark: Self::call_unpark::<T>,
7372
clone_to_byte_buffer: Self::clone_to_byte_buffer::<T>,
74-
drop_in_place: Self::drop_in_place::<T>,
73+
manual_drop: Self::manual_drop::<T>,
7574
}
7675
}
7776

78-
fn call_unpark<T: Unpark>(data: *const ()) {
79-
let downcasted = unsafe { &*(data as *const _ as *const T) };
80-
downcasted.unpark()
77+
/// Safe if data points to T.
78+
unsafe fn call_unpark<T: Unpark>(data: *const ()) {
79+
let downcasted = read_unaligned(data as *const _ as *const T);
80+
downcasted.unpark();
81+
forget(downcasted)
8182
}
8283

83-
/// Returns array with bytes of the cloned data. Safe if data is shorter than MAX_UNPARK_BYTES.
84+
/// Returns array with bytes of the cloned data. Safe if data points to T.
8485
/// The caller owns the new data and is responsible for dropping it with `drop_in_place<T>`.
85-
fn clone_to_byte_buffer<T: Clone>(data: *const ()) -> [u8; MAX_UNPARK_BYTES] {
86-
let downcasted = unsafe { &*(data as *const _ as *const T) };
87-
obliviate(downcasted.clone())
86+
unsafe fn clone_to_byte_buffer<T: Clone>(data: *const ()) -> [u8; MAX_UNPARK_BYTES] {
87+
let downcasted = read_unaligned(data as *const _ as *const T);
88+
let raw = obliviate(downcasted.clone());
89+
forget(downcasted);
90+
raw
8891
}
8992

90-
/// Make sure the original value is forgotten to avoid double free.
91-
unsafe fn drop_in_place<T>(data: *mut ()) {
92-
ptr::drop_in_place(&mut *(data as *mut _ as *mut T));
93+
unsafe fn manual_drop<T>(data: *const ()) {
94+
read_unaligned(data as *const _ as *const T);
9395
}
9496
}
9597

@@ -143,23 +145,25 @@ impl UnparkHandle {
143145
impl Drop for UnparkHandle {
144146
fn drop(&mut self) {
145147
unsafe {
146-
(self.vtable.drop_in_place)(&mut self.data as *mut _ as *mut ());
148+
(self.vtable.manual_drop)(&self.data as *const _ as *const ());
147149
}
148150
}
149151
}
150152

151153
impl Clone for UnparkHandle {
152154
fn clone(&self) -> Self {
153155
UnparkHandle {
154-
data: (self.vtable.clone_to_byte_buffer)(&self.data as *const _ as *const ()),
156+
data: unsafe { (self.vtable.clone_to_byte_buffer)(&self.data as *const _ as *const ()) },
155157
..*self
156158
}
157159
}
158160
}
159161

160162
impl Unpark for UnparkHandle {
161163
fn unpark(&self) {
162-
(self.vtable.unpark)(&self.data as *const _ as *const ())
164+
unsafe {
165+
(self.vtable.unpark)(&self.data as *const _ as *const ())
166+
}
163167
}
164168
}
165169

@@ -178,3 +182,13 @@ fn obliviate<T>(victim : T) -> [u8; MAX_UNPARK_BYTES] {
178182
forget(victim);
179183
buffer
180184
}
185+
186+
/// As implemented in core::ptr.
187+
/// When we drop support for rust < 1.17, use core::ptr::read_unaligned instead.
188+
unsafe fn read_unaligned<T>(src: *const T) -> T {
189+
let mut tmp: T = mem::uninitialized();
190+
ptr::copy_nonoverlapping(src as *const u8,
191+
&mut tmp as *mut T as *mut u8,
192+
size_of::<T>());
193+
tmp
194+
}

0 commit comments

Comments
 (0)