Open
Description
This compiles and prints "p is not null and 0x0":
pub mod bad {
#[allow(improper_ctypes)]
extern {
pub fn malloc(x: usize) -> &'static mut ();
}
#[no_mangle]
pub fn bar() {
let _m = malloc as unsafe extern "C" fn(usize) -> &'static mut ();
}
}
pub mod good {
extern {
fn malloc(x: usize) -> *const u8;
}
pub fn foo() {
unsafe {
let p = malloc(0x13371337deadbeef); // your computer doesn't have enough memory
if p.is_null() {
panic!("p is null");
} else {
panic!("p is not null and {:?}", p);
}
}
}
}
fn main() {
bad::bar();
good::foo();
}
The problem is that we have two declarations of the "malloc" symbol, but LLVM uses a global namespace for these. So during codegen, the 2nd declaration we generate overwrites the first. In this case, the "ill-typed" malloc declaration (bad::malloc
) comes last, up putting a nonnull
attribute on malloc
, which causes mod good
to be miscompiled.
Here's another example that does not involve malloc
. It does not get miscompiled currently, but it demonstrates the issue.
See here for a document that summarizes why this happens, and what our options are.
Metadata
Metadata
Assignees
Labels
Area: Foreign function interface (FFI)Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generationCategory: This is a bug.Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessMedium priorityRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the language team, which will review and decide on the PR/issue.