diff options
| author | Konrad Borowski <konrad@borowski.pw> | 2019-12-05 00:01:03 +0100 |
|---|---|---|
| committer | Konrad Borowski <konrad@borowski.pw> | 2019-12-05 13:44:03 +0100 |
| commit | 1cf0db19d45ca9fb4a3a10999dc116c37e06adf8 (patch) | |
| tree | c7ed4b8448ae906090cb7c042af688a50754d599 | |
| parent | d825e35ee8325146e6c175a4c61bcb645b347d5e (diff) | |
| download | rust-1cf0db19d45ca9fb4a3a10999dc116c37e06adf8.tar.gz rust-1cf0db19d45ca9fb4a3a10999dc116c37e06adf8.zip | |
Use deref target in Pin trait implementations
Using deref target instead of pointer itself avoids providing access to `&Rc<T>` for malicious implementations, which would allow calling `Rc::get_mut`. This is a breaking change necessary due to unsoundness, however the impact of it should be minimal. This only fixes the issue with malicious `PartialEq` implementations, other `Pin` soundness issues are still here. See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73> for more details.
| -rw-r--r-- | src/libcore/pin.rs | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 88fa718ae9e..f4e0e647434 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -376,6 +376,7 @@ use crate::cmp::{self, PartialEq, PartialOrd}; use crate::fmt; +use crate::hash::{Hash, Hasher}; use crate::marker::{Sized, Unpin}; use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; @@ -390,55 +391,72 @@ use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html // -// Note: the derives below, and the explicit `PartialEq` and `PartialOrd` -// implementations, are allowed because they all only use `&P`, so they cannot move -// the value behind `pointer`. +// Note: the `Clone` derive below causes unsoundness as it's possible to implement +// `Clone` for mutable references. +// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311> for more details. #[stable(feature = "pin", since = "1.33.0")] #[lang = "pin"] #[fundamental] #[repr(transparent)] -#[derive(Copy, Clone, Hash, Eq, Ord)] +#[derive(Copy, Clone)] pub struct Pin<P> { pointer: P, } -#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")] -impl<P, Q> PartialEq<Pin<Q>> for Pin<P> +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl<P: Deref, Q: Deref> PartialEq<Pin<Q>> for Pin<P> where - P: PartialEq<Q>, + P::Target: PartialEq<Q::Target>, { fn eq(&self, other: &Pin<Q>) -> bool { - self.pointer == other.pointer + **self == **other } fn ne(&self, other: &Pin<Q>) -> bool { - self.pointer != other.pointer + **self != **other } } -#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")] -impl<P, Q> PartialOrd<Pin<Q>> for Pin<P> +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl<P: Deref<Target: Eq>> Eq for Pin<P> {} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl<P: Deref, Q: Deref> PartialOrd<Pin<Q>> for Pin<P> where - P: PartialOrd<Q>, + P::Target: PartialOrd<Q::Target>, { fn partial_cmp(&self, other: &Pin<Q>) -> Option<cmp::Ordering> { - self.pointer.partial_cmp(&other.pointer) + (**self).partial_cmp(other) } fn lt(&self, other: &Pin<Q>) -> bool { - self.pointer < other.pointer + **self < **other } fn le(&self, other: &Pin<Q>) -> bool { - self.pointer <= other.pointer + **self <= **other } fn gt(&self, other: &Pin<Q>) -> bool { - self.pointer > other.pointer + **self > **other } fn ge(&self, other: &Pin<Q>) -> bool { - self.pointer >= other.pointer + **self >= **other + } +} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl<P: Deref<Target: Ord>> Ord for Pin<P> { + fn cmp(&self, other: &Self) -> cmp::Ordering { + (**self).cmp(other) + } +} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl<P: Deref<Target: Hash>> Hash for Pin<P> { + fn hash<H: Hasher>(&self, state: &mut H) { + (**self).hash(state); } } |
