Skip to content

Double-drops when control jumps out of borrow of slice literal construction #30822

Closed
@pnkfelix

Description

@pnkfelix

(this is related to #30018, but it is also a distinct problem in its own right.)

We appear to be creating copies of values that should be moved when doing slice literal construction.

The copies can be observed because double-drop (of the same abstract value) can occur when there is a break of control out of the slice literal during evaluation of one of the elements.

Here is an example (playpen):

struct D(&'static str);

impl Drop for D {
    fn drop(&mut self) {
        println!("Dropping D({})", self.0);
    }
}

fn main() {
    println!("Start");
    loop {
        let _r = &[D("1"),
                   D("2"),
                   { let _tmp = D("3"); break; },
                   D("4")];
    }
    println!("Finis");
}

outputs (in release mode):

Start
Dropping D(3)
Dropping D(2)
Dropping D(1)
Dropping D(1)
Dropping D(2)
Finis

The crucial point is that we see double drops of D(1) and D(2) in the output above. This would correspond, at least in theory, to deallocating a backing buffer multiple times -- that is, it is wrong. (Types like Vec probably defend themselves against such an attack since they currently use unsafe_no_drop_flag and thus should have an embedded drop flag state that it is maintaining itself, but other types that implement Drop do not necessary take that tack.)

(In debug mode there is a sigtrap at the end of that example; that is due to #30018, but again, that is not this ticket.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-destructorsArea: Destructors (`Drop`, …)T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions