-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Add MaybeUninit::assume_init_read Safety constraint: it can easily break !Send invariant #148083
Copy link
Copy link
Open
Labels
A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsArea: Documentation for any part of the project, including the compiler, standard library, and toolsI-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/SoundnessP-mediumMedium priorityMedium priorityT-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.
Metadata
Metadata
Assignees
Labels
A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsArea: Documentation for any part of the project, including the compiler, standard library, and toolsI-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/SoundnessP-mediumMedium priorityMedium priorityT-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.
Type
Fields
Give feedbackNo fields configured for issues without a type.
Location (URL)
https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#method.assume_init_read
Summary
MaybeUninit::<T>::assume_init_read, together withimpl<T: Sync> Sync for MaybeUninit<T>, can be (mis)used to break theSendinvariant: whenT: Sync, one can share&MaybeUninit<T>across threads (since&MaybeUninit<T>: Send) and thenassume_init_reada fresh ownedTon another thread. IfT: Sync + !Send, this constitutes a transfer of ownership of a!Sendvalue between threads, which violatesSend's safety contract and can lead to undefined behavior (such as data races). The current Safety section does not mention this class of misuse.Concretely, consider the following code (Playground):
This does not violate the two explicit constraints in the current documentation (the value is initialized, and not duplicated), yet it breaks the
Sendinvariant forT, sendingT:Sync + !Sendacross threads. ViolatingSend/Syncinvariants may cause undefined behavior such as data races.Request: Extend the Safety section with wording like:
ptr::readcan cause this kind of issue and doesn't document this danger, but raw pointers are neitherSyncnorSend.MaybeUninit::assume_init_readcan exploit this and we haveimpl<T: Sync> Sync for MaybeUninit<T>, so I believe we need a good documentation.I can send a PR as soon as we agree that this is actually a problem and that an additional Safety invariant documentation is a good way to resolve this! I don't think anyone wants to resolve this by introducing
unsafe impl<T: Send + Sync> Sync for MaybeUninit<T>, but I'd like to be sure.