Skip to content

Array and Vec's Clone specialization is maybe unsound with conditionally Copy types. #132442

Open
@theemathas

Description

Currently, the Clone impl for [T; N] uses specialization. If T implements Copy, then cloning a [T; N] will do a memcpy (ignoring T's Clone impl). If T doesn't implement Copy, then it will iterate and call T's Clone impl.

However, specialization doesn't look at lifetimes. Therefore, even if T implements Copy for only some lifetimes, cloning a [T; N] will do a memcopy. This is incorrect in the case where T actually doesn't implement Copy. For example:

struct Weird<'a>(&'a i32);

impl Clone for Weird<'_> {
    fn clone(&self) -> Self {
        println!("clone() called");
        Weird(self.0)
    }
}

impl Copy for Weird<'static> {}

fn main() {
    let local = 1;
    let _ = [Weird(&local)].clone();
}

In the above code, Weird only implements Copy when its lifetime is 'static. Therefore, I think that cloning a [Weird<'a>; 1] should call the clone() method. However, running the above code in either stable (1.82.0) or nightly (1.84.0-nightly (2024-10-30 759e07f063fb8e6306ff)) rust doesn't print anything. I believe that this is incorrect.

I am unsure whether or not this can cause UB in purely safe code, (hence the "maybe" in the issue title). But maybe someone else could figure out how to do that?

However, I have written this code, which uses unsafe code to implement a WeirdCow type whose public API I believe is sound on its own, but can be used in combination with array's Clone specialization to cause use-after-free. Either this WeirdCow type is unsound, or the array's Clone implementation is unsound, and I can't figure out which.

@rustbot label +I-unsound

Activity

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

Metadata

Assignees

No one assigned

    Labels

    A-specializationArea: Trait impl specializationC-bugCategory: This is a bug.E-needs-investigationCall for partcipation: This issues needs some investigation to determine current statusI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-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

    Development

    No branches or pull requests

    Issue actions