From 21b5950cf92a978f88dd65f408382637b60c52b5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Nov 2018 08:55:17 +0100 Subject: [PATCH 1/3] Unique/NonNull::from: make sure we convert to raw pointers ASAP By going through a shared reference, we share the destination as read-only, meaning we can read but not write with the raw pointers --- src/libcore/ptr.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 0387708033b53..452f7a62f4b33 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2815,14 +2815,14 @@ impl fmt::Pointer for Unique { #[unstable(feature = "ptr_internals", issue = "0")] impl<'a, T: ?Sized> From<&'a mut T> for Unique { fn from(reference: &'a mut T) -> Self { - Unique { pointer: unsafe { NonZero(reference as _) }, _marker: PhantomData } + Unique { pointer: unsafe { NonZero(reference as *mut T) }, _marker: PhantomData } } } #[unstable(feature = "ptr_internals", issue = "0")] impl<'a, T: ?Sized> From<&'a T> for Unique { fn from(reference: &'a T) -> Self { - Unique { pointer: unsafe { NonZero(reference as _) }, _marker: PhantomData } + Unique { pointer: unsafe { NonZero(reference as *const T) }, _marker: PhantomData } } } @@ -3025,7 +3025,7 @@ impl From> for NonNull { impl<'a, T: ?Sized> From<&'a mut T> for NonNull { #[inline] fn from(reference: &'a mut T) -> Self { - NonNull { pointer: unsafe { NonZero(reference as _) } } + NonNull { pointer: unsafe { NonZero(reference as *mut T) } } } } @@ -3033,6 +3033,6 @@ impl<'a, T: ?Sized> From<&'a mut T> for NonNull { impl<'a, T: ?Sized> From<&'a T> for NonNull { #[inline] fn from(reference: &'a T) -> Self { - NonNull { pointer: unsafe { NonZero(reference as _) } } + NonNull { pointer: unsafe { NonZero(reference as *const T) } } } } From b0c4a35a969aa94f6667cb885eebb184ee318a6d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Nov 2018 08:57:26 +0100 Subject: [PATCH 2/3] VecDeque::drain: make sure the 'drain' raw pointer is actually still usable --- src/liballoc/collections/vec_deque.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index c8ee40f3d2735..60b5d8063bff2 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1019,14 +1019,19 @@ impl VecDeque { // the drain is complete and the Drain destructor is run. self.head = drain_tail; + // `deque` and `ring` overlap in what they point to, so we must make sure + // that `ring` is "derived-from" `deque`, or else even just creating ring + // from `self` already invalidates `deque`. + let deque = NonNull::from(&mut *self); + Drain { - deque: NonNull::from(&mut *self), + deque, after_tail: drain_head, after_head: head, iter: Iter { tail: drain_tail, head: drain_head, - ring: unsafe { self.buffer_as_mut_slice() }, + ring: unsafe { (&mut *deque.as_ptr()).buffer_as_mut_slice() }, }, } } From feb775c834361f635df9e3824f9d2ae9582becbb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Nov 2018 16:03:24 +0100 Subject: [PATCH 3/3] Drain only needs a shared reference --- src/liballoc/collections/vec_deque.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 60b5d8063bff2..4a3604f202f73 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1019,19 +1019,17 @@ impl VecDeque { // the drain is complete and the Drain destructor is run. self.head = drain_tail; - // `deque` and `ring` overlap in what they point to, so we must make sure - // that `ring` is "derived-from" `deque`, or else even just creating ring - // from `self` already invalidates `deque`. - let deque = NonNull::from(&mut *self); - Drain { - deque, + deque: NonNull::from(&mut *self), after_tail: drain_head, after_head: head, iter: Iter { tail: drain_tail, head: drain_head, - ring: unsafe { (&mut *deque.as_ptr()).buffer_as_mut_slice() }, + // Crucially, we only create shared references from `self` here and read from + // it. We do not write to `self` nor reborrow to a mutable reference. + // Hence the raw pointer we created above, for `deque`, remains valid. + ring: unsafe { self.buffer_as_slice() }, }, } }