Skip to content

Pin is unsound due to transitive effects of CoerceUnsized #68015

@nikomatsakis

Description

@nikomatsakis
Contributor

Split out from #66544. It is possible to exploit Pin on nightly Rust (but not stable) by creating smart pointers that implement CoerceUnsized but have strange behavior. See the dedicated internals thread for more details -- also, please keep conversation on the thread, and not on the Github issue. ❤️

Activity

added
T-langRelevant to the language team
I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness
on Jan 9, 2020
added a commit that references this issue on Mar 21, 2020
16338b1
added a commit that references this issue on Mar 26, 2020
b0a63cb
added
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Jun 10, 2020
removed
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Jun 10, 2020
nikomatsakis

nikomatsakis commented on Jun 23, 2020

@nikomatsakis
ContributorAuthor

Lowering the priority of this to medium, adding as a blocker to #27732 (coerce unsized stabilization).

mzji

mzji commented on Jul 4, 2020

@mzji
steffahn

steffahn commented on May 9, 2021

@steffahn
Member

Update: It is possible to abuse existing CoerceUnsized implementations on stable. See #85099 (although I created that issue before reading any of this issue and its IRLO thread, so don’t expect any syntactic similarity to the unsoundness examples of this issue).

The type Pin<&LocalType> implements Deref<Target = LocalType> but it doesn’t implement DerefMut. The types Pin and & are #[fundamental] so that an impl DerefMut for Pin<&LocalType>> is possible. You can use LocalType == SomeLocalStruct or LocalType == dyn LocalTrait and you can coerce Pin<Pin<&SomeLocalStruct>> into Pin<Pin<&dyn LocalTrait>>. (Indeed, two layers of Pin!!) This allows creating a pair of “smart pointers that implement CoerceUnsized but have strange behavior” on stable (Pin<&SomeLocalStruct> and Pin<&dyn LocalTrait> become the smart pointers with “strange behavior” and they already implement CoerceUnsized).

More concretely: Since Pin<&dyn LocalTrait>: Deref<dyn LocalTrait>, a “strange behavior” DerefMut implementation of Pin<&dyn LocalTrait> can be used to dereference an underlying Pin<&SomeLocalStruct> into, effectively, a target type (wrapped in the trait object) that’s different from SomeLocalStruct. The struct SomeLocalStruct might always be Unpin while the different type behind the &mut dyn LocalTrait returned by DerefMut can be !Unpin. Having SomeLocalStruct: Unpin allows for easy creation of the Pin<Pin<&SomeLocalStruct>> which coerces into Pin<Pin<&dyn LocalTrait>> even though Pin<&dyn LocalTrait>::Target: !Unpin (and even the actual Target type inside of the trait object being returned by the DerefMut can be !Unpin).

Methods on LocalTrait can be used both to make the DerefMut implementation possible and to convert the Pin<&mut dyn LocalTrait> (from a Pin::as_mut call on &mut Pin<Pin<&dyn LocalTrait>>) back into a pinned mutable referene to the concrete “type behind the &mut dyn LocalTrait returned by DerefMut.

added
E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
on Oct 11, 2023
Darksonn

Darksonn commented on Aug 4, 2025

@Darksonn
Contributor

I just came across this. I believe this was solved by the addition of PinCoerceUnsized. See also this section of the derive(SmartPointer) RFC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable ExampleF-coerce_unsizedThe `CoerceUnsized` traitI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityT-langRelevant to the language teamrequires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @nikomatsakis@Darksonn@jonas-schievink@steffahn@mzji

        Issue actions