Closed
Description
fn foo(x: &mut ~u8) {
*x = ~5;
}
fn main() {
foo(&mut ~4);
}
crashes with a double free, because the glue call in main
tries to free the originally allocated memory that was already freed by the assignment in foo
.
define void @"_ZN4main16_9c508369d68e95d7_0$x2e0E"({ i64, %tydesc*, i8*, i8*, i8 }*) #4 {
"function top level":
%1 = alloca i8*
%2 = alloca { i8*, i32 }
%3 = alloca i8*
%4 = alloca i8*
%5 = call i8* @"_ZN2rt11global_heap15exchange_malloc16_a0e6b1fccad656a7_0$x2e0E"({ i64, %tydesc*, i8*, i8*, i8 }* undef, i64 1)
store i8 4, i8* %5
store i8* %5, i8** %1
invoke void @"_ZN3foo17_6b2c235046b35a5e7_0$x2e0E"({ i64, %tydesc*, i8*, i8*, i8 }* undef, i8** %1)
to label %"normal return" unwind label %unwind
"normal return": ; preds = %"function top level"
store i8* %5, i8** %4
%6 = bitcast i8** %4 to i32**
call void @"_ZN8_$UP$u3217_7656cd521ad1a3b614glue_free_3306E"({}* null, i32** %6)
ret void
unwind: ; preds = %"function top level"
%7 = landingpad { i8*, i32 } personality i32 ()* @upcall_rust_personality
cleanup
call void @upcall_reset_stack_limit()
store { i8*, i32 } %7, { i8*, i32 }* %2
br label %cleanup
cleanup: ; preds = %unwind
store i8* %5, i8** %3 // BAD: %5 the original value, not the new one
%8 = bitcast i8** %3 to i32**
call void @"_ZN8_$UP$u3217_7656cd521ad1a3b614glue_free_3306E"({}* null, i32** %8)
%9 = load { i8*, i32 }* %2
resume { i8*, i32 } %9
}