-
-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Unsoundness due to #[pin_v2] incorrectly handles packed structs. #157011
Copy link
Copy link
Open
Labels
A-destructorsArea: Destructors (`Drop`, …)Area: Destructors (`Drop`, …)A-reprArea: the `#[repr(stuff)]` attributeArea: the `#[repr(stuff)]` attributeA-repr-packedArea: the naughtiest reprArea: the naughtiest reprC-bugCategory: This is a bug.Category: This is a bug.F-pin_ergonomics`#![feature(pin_ergonomics)]``#![feature(pin_ergonomics)]`I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Metadata
Metadata
Assignees
Labels
A-destructorsArea: Destructors (`Drop`, …)Area: Destructors (`Drop`, …)A-reprArea: the `#[repr(stuff)]` attributeArea: the `#[repr(stuff)]` attributeA-repr-packedArea: the naughtiest reprArea: the naughtiest reprC-bugCategory: This is a bug.Category: This is a bug.F-pin_ergonomics`#![feature(pin_ergonomics)]``#![feature(pin_ergonomics)]`I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Type
Fields
Give feedbackNo fields configured for issues without a type.
Projects
StatusShow more project fields
No status
When the destructor of a
repr(packed)struct runs, if it has a field which is unaligned and has a destructor, that field will be moved to an aligned place before the destructor of that field is ran. (See also #143411, taiki-e/pin-project-lite#89, taiki-e/pin-project#34.)The
#[pin_v2]attribute does not take this into account. This allows aDropimpl of a type to access a value of that type via&mut, even after pin-projection was used to access a value of that same type viaPin<&mut>.The below code demonstrates this unsoundness. The two addresses it prints are different, showing that the invariant of
Pinwas violated.Here's an explanation of the various parts this code:
Onestruct is packed to an alignment of 4 bytes. This causes theThingfield to also be aligned to 4 bytes, which allows projectingpinned_onetopinned_thingwithout causing a compile error due to an unaligned reference toThing.Twostruct is aligned to more than 4 bytes. This means that, when the destructor ofOneis ran, it notices that its field has an alignment of 65536. Therefore, thisTwofield is moved to an aligned place beforeTwo's destructor is ran.Onestruct needs to be generic, to work around a compile error that prevents me from directly putting arepr(align)type inside arepr(packed)type.Meta
Reproducible on the playground with version
1.98.0-nightly (2026-05-26 d1fc603d1788cc3c0eeb)