Skip to content

Double free in Vec::from_iter specialization when drop panics #83618

@Qwaz

Description

@Qwaz
Contributor

// drop any remaining values at the tail of the source
src.drop_remaining();

pub(super) fn drop_remaining(&mut self) {
unsafe {
ptr::drop_in_place(self.as_mut_slice());
}
self.ptr = self.end;
}

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.

Activity

added
A-destructorsArea: Destructors (`Drop`, …)
I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness
T-libsRelevant to the library team, which will review and decide on the PR/issue.
on Mar 28, 2021
added
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Mar 28, 2021
the8472

the8472 commented on Mar 29, 2021

@the8472
Member

Thanks, I totally didn't consider that case!
According to #14875 panic during drop should result in the storage being leaked. That shouldn't be too difficult to achieve by forgetting the original allocation before the drop.

The question is whether it is necessary to attempt to drop the stuff moved to output vec or whether we can leak those too.

@rustbot claim

JohnTitor

JohnTitor commented on Mar 29, 2021

@JohnTitor
Member

Assigning P-critical as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.

added and removed
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Mar 29, 2021
added 3 commits that reference this issue on Apr 1, 2021
2433ef1
e25e2b9
542f441

5 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-collectionsArea: `std::collections`A-destructorsArea: Destructors (`Drop`, …)C-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-criticalCritical priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Participants

    @the8472@jonas-schievink@Qwaz@JohnTitor@rustbot

    Issue actions

      Double free in Vec::from_iter specialization when drop panics · Issue #83618 · rust-lang/rust