Closed
Description
rust/library/alloc/src/vec/source_iter_marker.rs
Lines 71 to 72 in 4a20eb6
rust/library/alloc/src/vec/into_iter.rs
Lines 88 to 93 in 4a20eb6
SpecFromIter<T, I> for Vec<T>
calls Vec::IntoIter::drop_remaining()
. drop_remaining()
calls drop_in_place()
before overwriting the pointer. As a result, dropped elements are not invalidated and dropped again under panic.
PoC:
#![forbid(unsafe_code)]
use std::iter::FromIterator;
#[derive(Debug)]
enum MyEnum {
DroppedTwice(Box<i32>),
PanicOnDrop,
}
impl Drop for MyEnum {
fn drop(&mut self) {
match self {
MyEnum::DroppedTwice(_) => println!("Dropping!"),
MyEnum::PanicOnDrop => {
if !std::thread::panicking() {
panic!();
}
}
}
}
}
fn main() {
let v = vec![MyEnum::DroppedTwice(Box::new(123)), MyEnum::PanicOnDrop];
Vec::from_iter(v.into_iter().take(0));
}
Output:
Dropping!
thread 'main' panicked at 'explicit panic', src/main.rs:17:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Dropping!
free(): double free detected in tcache 2
Tested with rustc 1.51.0
. Here is a playground link to the code snippet.