-
Notifications
You must be signed in to change notification settings - Fork 14k
Closed
Labels
A-collectionsArea: `std::collections`Area: `std::collections`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-criticalCritical priorityCritical 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.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Description
rust/library/alloc/src/vec/mod.rs
Lines 1608 to 1637 in d8af907
| let mut gap = FillGapOnDrop { read: 1, write: 1, vec: self }; | |
| let ptr = gap.vec.as_mut_ptr(); | |
| /* Drop items while going through Vec, it should be more efficient than | |
| * doing slice partition_dedup + truncate */ | |
| /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr | |
| * are always in-bounds and read_ptr never aliases prev_ptr */ | |
| unsafe { | |
| while gap.read < len { | |
| let read_ptr = ptr.add(gap.read); | |
| let prev_ptr = ptr.add(gap.write.wrapping_sub(1)); | |
| if same_bucket(&mut *read_ptr, &mut *prev_ptr) { | |
| /* We have found duplicate, drop it in-place */ | |
| ptr::drop_in_place(read_ptr); | |
| } else { | |
| let write_ptr = ptr.add(gap.write); | |
| /* Because `read_ptr` can be equal to `write_ptr`, we either | |
| * have to use `copy` or conditional `copy_nonoverlapping`. | |
| * Looks like the first option is faster. */ | |
| ptr::copy(read_ptr, write_ptr, 1); | |
| /* We have filled that place, so go further */ | |
| gap.write += 1; | |
| } | |
| gap.read += 1; | |
| } |
gap.read is not updated (line 1636) when drop_in_place (line 1623) panics. This lets FillGapOnDrop's Drop implementation to retain the already dropped element.
The bug was introduced in #82191 and affects stable Rust versions >= 1.52. Here is the playground link that demonstrates the double free without using unsafe Rust code.
Meta
rustc --version --verbose:
rustc 1.52.1 (9bc8c42bb 2021-05-09)
binary: rustc
commit-hash: 9bc8c42bb2f19e745a63f3445f1ac248fb015e53
commit-date: 2021-05-09
host: x86_64-unknown-linux-gnu
release: 1.52.1
LLVM version: 12.0.0
scottmcm and Soveu
Metadata
Metadata
Assignees
Labels
A-collectionsArea: `std::collections`Area: `std::collections`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-criticalCritical priorityCritical 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.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.