-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Mutable slices as function parameters allow aliasing mutable references #40288
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
cc @rust-lang/compiler |
This is genuinely scary. I would've expected |
Single-function, use-after-free, and showing that the lifetime can become fn prove_static(_: [&'static str; 1]) {}
fn main() {
let mut out = ["foo"];
{
let mut x = String::from("bar");
let slice: &mut [_] = &mut out;
slice[0] = &x[..];
}
let _new = String::from("boo");
println!("{}", out[0]);
prove_static(out);
} |
General-purpose fn prove_static<T: 'static + ?Sized>(_: &'static T) {}
fn lifetime_transmute<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
let mut out = [x];
(&mut out as &mut [_])[0] = y;
out[0]
}
fn main() {
prove_static(lifetime_transmute("", &String::from("foo")));
} |
fn lifetime_transmute<'a, 'b, T: ?Sized>(x: &'a T, y: &'b T) -> &'a T {
let mut out = [x];
// Neither 'a nor 'b work here, they both error correctly.
(&mut out as &mut [&'b T])[0] = y;
out[0]
} Maybe we're using subtyping in the wrong direction, or should be using equality instead? EDIT: Yupp, subtyping alright (two more cases above and below). EDIT2: Just confirmed it was introduced by #24619, you get an error in 1.0. |
Good stuff, glad I caught this. |
triage: P-high |
…r=nikomatsakis Disallow subtyping between T and U in T: Unsize<U>. Because `&mut T` can be coerced to `&mut U`, `T` and `U` must be unified invariantly. Fixes rust-lang#40288. E.g. coercing `&mut [&'a X; N]` to `&mut [&'b X]` must require `'a` be equal to `'b`, otherwise you can convert between `&'a X` and `&'b X` (in either direction), potentially unsoundly lengthening lifetimes. Subtyping here was introduced with `Unsize` in rust-lang#24619 (landed in 1.1, original PR is rust-lang#23785).
…r=nikomatsakis Disallow subtyping between T and U in T: Unsize<U>. Because `&mut T` can be coerced to `&mut U`, `T` and `U` must be unified invariantly. Fixes rust-lang#40288. E.g. coercing `&mut [&'a X; N]` to `&mut [&'b X]` must require `'a` be equal to `'b`, otherwise you can convert between `&'a X` and `&'b X` (in either direction), potentially unsoundly lengthening lifetimes. Subtyping here was introduced with `Unsize` in rust-lang#24619 (landed in 1.1, original PR is rust-lang#23785).
…r=nikomatsakis Disallow subtyping between T and U in T: Unsize<U>. Because `&mut T` can be coerced to `&mut U`, `T` and `U` must be unified invariantly. Fixes rust-lang#40288. E.g. coercing `&mut [&'a X; N]` to `&mut [&'b X]` must require `'a` be equal to `'b`, otherwise you can convert between `&'a X` and `&'b X` (in either direction), potentially unsoundly lengthening lifetimes. Subtyping here was introduced with `Unsize` in rust-lang#24619 (landed in 1.1, original PR is rust-lang#23785).
…r=nikomatsakis Disallow subtyping between T and U in T: Unsize<U>. Because `&mut T` can be coerced to `&mut U`, `T` and `U` must be unified invariantly. Fixes rust-lang#40288. E.g. coercing `&mut [&'a X; N]` to `&mut [&'b X]` must require `'a` be equal to `'b`, otherwise you can convert between `&'a X` and `&'b X` (in either direction), potentially unsoundly lengthening lifetimes. Subtyping here was introduced with `Unsize` in rust-lang#24619 (landed in 1.1, original PR is rust-lang#23785).
…r=nikomatsakis Disallow subtyping between T and U in T: Unsize<U>. Because `&mut T` can be coerced to `&mut U`, `T` and `U` must be unified invariantly. Fixes rust-lang#40288. E.g. coercing `&mut [&'a X; N]` to `&mut [&'b X]` must require `'a` be equal to `'b`, otherwise you can convert between `&'a X` and `&'b X` (in either direction), potentially unsoundly lengthening lifetimes. Subtyping here was introduced with `Unsize` in rust-lang#24619 (landed in 1.1, original PR is rust-lang#23785).
…r=nikomatsakis Disallow subtyping between T and U in T: Unsize<U>. Because `&mut T` can be coerced to `&mut U`, `T` and `U` must be unified invariantly. Fixes rust-lang#40288. E.g. coercing `&mut [&'a X; N]` to `&mut [&'b X]` must require `'a` be equal to `'b`, otherwise you can convert between `&'a X` and `&'b X` (in either direction), potentially unsoundly lengthening lifetimes. Subtyping here was introduced with `Unsize` in rust-lang#24619 (landed in 1.1, original PR is rust-lang#23785).
…r=nikomatsakis Disallow subtyping between T and U in T: Unsize<U>. Because `&mut T` can be coerced to `&mut U`, `T` and `U` must be unified invariantly. Fixes rust-lang#40288. E.g. coercing `&mut [&'a X; N]` to `&mut [&'b X]` must require `'a` be equal to `'b`, otherwise you can convert between `&'a X` and `&'b X` (in either direction), potentially unsoundly lengthening lifetimes. Subtyping here was introduced with `Unsize` in rust-lang#24619 (landed in 1.1, original PR is rust-lang#23785).
This currently affects all 3 release channels.
If you have a mutable slice of references as an input to a function, it allows borrows to escape and cause aliasing. The following example compiles and prints "3", but it shouldn't compile at all (Playground):
This appears to be tied to slices as the non-slice equivalent fails to compile as expected (Playground):
cc seanmonstar/httparse#34
The text was updated successfully, but these errors were encountered: