-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
VecDeque::shrink_to leads to UB if handle_alloc_error unwinds. #123369
Copy link
Copy link
Closed
Labels
C-bugCategory: This is a bug.Category: This is a bug.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/SoundnessP-mediumMedium priorityMedium priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Metadata
Metadata
Assignees
Labels
C-bugCategory: This is a bug.Category: This is a bug.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/SoundnessP-mediumMedium priorityMedium priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Type
Fields
Give feedbackNo fields configured for issues without a type.
I tried this code:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=a2e4bd9f59882c88c4f232379cbb0001
I expected to see this happen:
shrink_to_fitcauses an alloc error, the thread unwinds,Foo(0)andFoo(1)are dropped in some order.Instead, this happened:
(the exact value printed differs between runs, which makes sense if it's reading uninit memory)
This occurs because of the way
VecDeque::shrink_tois implemented: It first moves the memory around to fit the new capacity, then callsRawVec::shrink_to_fit(new_capacity)with no regards to potential unwinding. Specifically, this would look something like this:shrink_tocopies the head to just behind the tail:shrink_tocallsRawVec::shrink_to_fitcallsAllocator::shrinkwhich returns an alloc error, the error handler unwinds, leaving the buffer looking like this:Dropimpl ofVecDequedrops its elements, reading the uninit memory.Meta
While this specific setup requires nightly to manually set the alloc error handle hook and to trigger the alloc error in
shrink, this same bug could occur on stable ifshrinkOOMs. The docs forhandle_alloc_erroralso explicitly state that it may either abort or unwind.I'm not sure what would be the best way to fix this. Maybe just
catch_unwindthe call toRawVec::shrink_to_fitand manually abort the process would work well enough?