-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Open
Labels
A-associated-itemsArea: Associated items (types, constants & functions)Area: Associated items (types, constants & functions)A-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)A-type-systemArea: Type systemArea: Type systemC-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityHigh priorityT-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Description
This code results in undefined behavior in safe code.
use std::any::Any;
// `for<'a> Producer<&'a T>` is equivalent to the (non-existent) `for<'a> FnOnce() -> &'a T`
pub trait Producer<T>: FnOnce() -> T {}
impl<T, F: FnOnce() -> T> Producer<T> for F {}
// What does `P::Output` even mean in this context? If this was `FnOnce(&()) -> &T`, using `Output`
// would result in "Cannot use the assiciated type of a trait with uninferred generic parameters",
// even when hiding behind an extra trait
fn write_incoherent_p2<T, P: for<'a> Producer<&'a T>>(
weird: P::Output,
out: &mut &'static dyn Any,
) {
// `T` is not even `'static`, but `P::Output` seems to kind of
// resemble `for<'a> &'a T` (if that even means anything)
*out = weird;
}
fn write_incoherent_p1<T, P: for<'a> Producer<&'a T>>(p: P, out: &mut &'static dyn Any) {
// Producing and writing p() in one function doesn't work. Doing so requires T: 'static.
// Adding T: 'static to all functions also makes this not work.
// This fragility is why every line is its own function.
write_incoherent_p2::<T, P>(p(), out)
}
// Now we can trigger unsoundness by finding something that is `FnOnce() -> &'a T` for any `'a`
// `for<'a> FnOnce() -> &'a T` is basically just the signature of Box::leak
fn construct_implementor<T>(not_static: T, out: &mut &'static dyn Any) {
write_incoherent_p1::<T, _>(|| Box::leak(Box::new(not_static)), out);
}
fn make_static_and_drop<T: 'static>(t: T) -> &'static T {
let mut out: &'static dyn Any = &();
construct_implementor::<&T>(&t, &mut out);
*out.downcast_ref::<&T>().unwrap()
}
fn main() {
println!("{:?}", make_static_and_drop(vec![vec![1]])); // use after free
}
The earliest affected version is 1.72 1.67.0. Many All earlier versions reject construct_implementor
, but most just 1.70.0-1.72.0 ICE. Current nightly is also affected.
I am not entirely sure what is going on in this code; I was trying to create a function type that returns a reference of any requested lifetime (don't ask why), i.e. for<'a> Fn() -> &'a T
. For some reason it works when hiding behind a blanket implementation, though it is very fragile. Taking Fn::Output
of such a function type yields a type that seems to kind of resemble "for<'a> &'a T
" and allows assignment to &'static dyn Any
, even though T
is not 'static
.
theemathas, scottmcm, janriemer, fogti and aandrejevas
Metadata
Metadata
Assignees
Labels
A-associated-itemsArea: Associated items (types, constants & functions)Area: Associated items (types, constants & functions)A-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)A-type-systemArea: Type systemArea: Type systemC-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityHigh priorityT-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Type
Projects
Status
open/unblocked