Skip to content

Commit 1cf0db1

Browse files
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.
1 parent d825e35 commit 1cf0db1

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

src/libcore/pin.rs

+35-17
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@
376376

377377
use crate::cmp::{self, PartialEq, PartialOrd};
378378
use crate::fmt;
379+
use crate::hash::{Hash, Hasher};
379380
use crate::marker::{Sized, Unpin};
380381
use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
381382

@@ -390,55 +391,72 @@ use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
390391
/// [`Unpin`]: ../../std/marker/trait.Unpin.html
391392
/// [`pin` module]: ../../std/pin/index.html
392393
//
393-
// Note: the derives below, and the explicit `PartialEq` and `PartialOrd`
394-
// implementations, are allowed because they all only use `&P`, so they cannot move
395-
// the value behind `pointer`.
394+
// Note: the `Clone` derive below causes unsoundness as it's possible to implement
395+
// `Clone` for mutable references.
396+
// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311> for more details.
396397
#[stable(feature = "pin", since = "1.33.0")]
397398
#[lang = "pin"]
398399
#[fundamental]
399400
#[repr(transparent)]
400-
#[derive(Copy, Clone, Hash, Eq, Ord)]
401+
#[derive(Copy, Clone)]
401402
pub struct Pin<P> {
402403
pointer: P,
403404
}
404405

405-
#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")]
406-
impl<P, Q> PartialEq<Pin<Q>> for Pin<P>
406+
#[stable(feature = "pin_trait_impls", since = "1.41.0")]
407+
impl<P: Deref, Q: Deref> PartialEq<Pin<Q>> for Pin<P>
407408
where
408-
P: PartialEq<Q>,
409+
P::Target: PartialEq<Q::Target>,
409410
{
410411
fn eq(&self, other: &Pin<Q>) -> bool {
411-
self.pointer == other.pointer
412+
**self == **other
412413
}
413414

414415
fn ne(&self, other: &Pin<Q>) -> bool {
415-
self.pointer != other.pointer
416+
**self != **other
416417
}
417418
}
418419

419-
#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")]
420-
impl<P, Q> PartialOrd<Pin<Q>> for Pin<P>
420+
#[stable(feature = "pin_trait_impls", since = "1.41.0")]
421+
impl<P: Deref<Target: Eq>> Eq for Pin<P> {}
422+
423+
#[stable(feature = "pin_trait_impls", since = "1.41.0")]
424+
impl<P: Deref, Q: Deref> PartialOrd<Pin<Q>> for Pin<P>
421425
where
422-
P: PartialOrd<Q>,
426+
P::Target: PartialOrd<Q::Target>,
423427
{
424428
fn partial_cmp(&self, other: &Pin<Q>) -> Option<cmp::Ordering> {
425-
self.pointer.partial_cmp(&other.pointer)
429+
(**self).partial_cmp(other)
426430
}
427431

428432
fn lt(&self, other: &Pin<Q>) -> bool {
429-
self.pointer < other.pointer
433+
**self < **other
430434
}
431435

432436
fn le(&self, other: &Pin<Q>) -> bool {
433-
self.pointer <= other.pointer
437+
**self <= **other
434438
}
435439

436440
fn gt(&self, other: &Pin<Q>) -> bool {
437-
self.pointer > other.pointer
441+
**self > **other
438442
}
439443

440444
fn ge(&self, other: &Pin<Q>) -> bool {
441-
self.pointer >= other.pointer
445+
**self >= **other
446+
}
447+
}
448+
449+
#[stable(feature = "pin_trait_impls", since = "1.41.0")]
450+
impl<P: Deref<Target: Ord>> Ord for Pin<P> {
451+
fn cmp(&self, other: &Self) -> cmp::Ordering {
452+
(**self).cmp(other)
453+
}
454+
}
455+
456+
#[stable(feature = "pin_trait_impls", since = "1.41.0")]
457+
impl<P: Deref<Target: Hash>> Hash for Pin<P> {
458+
fn hash<H: Hasher>(&self, state: &mut H) {
459+
(**self).hash(state);
442460
}
443461
}
444462

0 commit comments

Comments
 (0)