-
-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Cloning a Pin<Box> with a custom allocator can violate the pinning invariant #157089
Copy link
Copy link
Open
Labels
A-allocatorsArea: Custom and system allocatorsArea: Custom and system allocatorsA-boxArea: Our favorite opsem complicationArea: Our favorite opsem complicationA-coherenceArea: CoherenceArea: CoherenceA-pinArea: PinArea: PinA-varianceArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)Area: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)C-bugCategory: This is a bug.Category: This is a bug.I-types-nominatedNominated for discussion during a types team meeting.Nominated for discussion during a types team meeting.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-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
Metadata
Metadata
Assignees
Labels
A-allocatorsArea: Custom and system allocatorsArea: Custom and system allocatorsA-boxArea: Our favorite opsem complicationArea: Our favorite opsem complicationA-coherenceArea: CoherenceArea: CoherenceA-pinArea: PinArea: PinA-varianceArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)Area: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)C-bugCategory: This is a bug.Category: This is a bug.I-types-nominatedNominated for discussion during a types team meeting.Nominated for discussion during a types team meeting.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-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
Type
Fields
Give feedbackNo fields configured for issues without a type.
View all comments
This unsoundness is caused by a violation of #152667. I discovered this after @Darksonn noted a discrepancy at #156935 (comment).
Cloning a
Pin<Box<T, A>>, causes<Box<T, A>>::clone()to run, and thenPin::new_unchecked()is called on the result.<Box<T, A>>::clone()can be user-defined code, sinceBoxis a fundamental type. Therefore, it is possible to callPin::new_unchecked()on an arbitrary value ofBox<T, A>in safe code.In most cases, calling
Pin::new_unchecked()on aBox<T, A>is harmless, as it is usually equivalent toBox::into_pin(). However,Box::into_pin()actually has anA: 'staticbound. This is because, ifAis not'static, then the memory in the allocator may be reused/deallocated after'aexpires, without actually running the destructor ofT, violating the pinning invariant.In order to produce a
Pin<Box<T, A>>with a non-'staticallocatorAin the first place, so we could call clone, we can create a pinned box with a'staticallocator, and then use a subtype coercion to turn it into a non-'staticallocator.The below code exploits this. (Tested with
pin-projectversion 1.1.13, andbumpaloversion 3.20.3 with theallocator_apifeature.)On my computer, the code prints the following:
Based on the output, we can see that the program pins a 1024-byte value at a certain memory, and then (without running the value's destructor) proceeds to reuse an overlapping chunk of memory for something else. This violates the pinning invariant.
Meta
rustc --version --verbose: