Closed
Description
The gist is that the kind-checker permits putting borrowed pointers into traits, which will cause the compiler to forget about the lifetime. The following program uses this to return a borrowed pointer outside of its stack frame, and then collides another stack frame into it to implement type coercion.
This will be fixed by #3569.
trait Foo<T> {
fn get(@self) -> T;
}
struct Bar<'self, T> {
x: &'self Option<T>,
}
impl <'self, T: Copy> Foo<T> for Bar<'self, T> {
#[inline(always)] // Needed to avoid clobbering too early!
fn get(@self) -> T {
copy *self.x.get_ref()
}
}
fn foo<T: 'static + Copy>(val: Option<T>) -> @Foo<T> {
let x = val;
let bar = Bar { x: &x };
return @bar as @Foo<T>; // this is the line that should be illegal
}
fn coerce<A: 'static + Copy, B: 'static + Copy>(val: A) -> B {
// Contains a borrowed pointer past the end of the stack.
let x = foo(None::<B>);
// The value passed in collides with the stack location pointed to inside x.
// Need to call it "_z", not "_", because the latter will immediately get freed.
let _z = foo(Some(val));
x.get()
}
fn main() {
let y: ~str = coerce(~[0x31u8, 0x33, 0x33, 0x37, 0]);
println(fmt!("%?", y));
}