Array and Vec's Clone specialization is maybe unsound with conditionally Copy types. #132442
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