diff options
| author | kennytm <kennytm@gmail.com> | 2019-02-16 00:55:54 +0800 |
|---|---|---|
| committer | kennytm <kennytm@gmail.com> | 2019-02-16 14:11:41 +0800 |
| commit | 13b055d5db67ab6c88d6379b7677069482db6077 (patch) | |
| tree | c7dcd62b3c74dbf6e0a303cdbd4844ed53467d6a | |
| parent | 092d191965597c80e01bae7029324bce5b994b8f (diff) | |
| parent | 719be246ae708508a19436a0b8ee1be29882e21e (diff) | |
| download | rust-13b055d5db67ab6c88d6379b7677069482db6077.tar.gz rust-13b055d5db67ab6c88d6379b7677069482db6077.zip | |
Rollup merge of #58429 - RalfJung:box, r=TimNN
fix Box::into_unique effecitvely transmuting to a raw ptr Miri/Stacked Borrows treat `Box` specially: they assert that it is unique, and tag it appropriately. However, currently, `Box::into_inner` is not aware of that and returns a raw pointer (wrapped in a `Unique`) that carries the same tag as the box, meaning it carries a `Uniq` tag. This leads to all sorts of problems when people use the raw pointer they get out of the `Unique` type. In the future, it'd be interesting to make `Unique` also carry some kind of uniqueness. In that case, something like this would instead be needed whenever a raw pointer is extracted from a `Unique`. However, that is out-of-scope for the current version of Stacked Borrows. So until then, this changes `into_unique` to perform a proper reference-to-raw-ptr-cast, which clears the tag.
| -rw-r--r-- | src/liballoc/boxed.rs | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 51549f92d4d..0cd2373c7f0 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -202,10 +202,15 @@ impl<T: ?Sized> Box<T> { #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")] #[inline] #[doc(hidden)] - pub fn into_unique(b: Box<T>) -> Unique<T> { - let unique = b.0; + pub fn into_unique(mut b: Box<T>) -> Unique<T> { + // Box is kind-of a library type, but recognized as a "unique pointer" by + // Stacked Borrows. This function here corresponds to "reborrowing to + // a raw pointer", but there is no actual reborrow here -- so + // without some care, the pointer we are returning here still carries + // the `Uniq` tag. We round-trip through a mutable reference to avoid that. + let unique = unsafe { b.0.as_mut() as *mut T }; mem::forget(b); - unique + unsafe { Unique::new_unchecked(unique) } } /// Consumes and leaks the `Box`, returning a mutable reference, |
