You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On some platforms (at least GNU/Linux, but I hear Windows and several others too), if you link together two static libraries that both export a symbol of the same name, it's undefined which symbol actually gets linked. In practice on my machine, the first library seems to win. This lets you defeat type/memory safety without the unsafe keyword, by having two crates export a #[no_mangle] pub fn with different signatures but compatible calling conventions:
Despite the stated call to two::convert, it's actually one::convert that gets called, which interprets the argument as a &'static i32. (It may be clearer to understand with this simpler example, which doesn't break type safety.)
On at least GNU/Linux but not other platforms like Windows or Darwin, dynamically-linked symbols have the same ambiguity.
I don't know what the right response is here. The following options all seem pretty reasonable:
Acknowledge it and ignore it. Maybe document it as a possible source of unsafety, despite not using the unsafe keyword.
Have #[no_mangle] export both a mangled and un-mangled name, and have Rust crates call each other via mangled names only, on the grounds that #[no_mangle] is for external interfaces, not for crates linking to crates. ("External interfaces" includes other Rust code using FFI, but FFI is unsafe.) This is analogous to how extern "C" fns export both a Rust-ABI symbol as well as a C-ABI shim, and a direct, safe Rust call to those function happens through the Rust ABI, not through the C ABI. I'm pretty sure that all production uses of #[no_mangle] are extern "C", anyway (see e.g. Can't define unsafe extern "C" fn #10025).
Deprecate #[no_mangle] on safe functions and data, and introduce a new #[unsafe_no_mangle], so it substring-matches unsafe. (#[no_mangle] on unsafe functions or mutable statics is fine, since you need the unsafe keyword to get at them.)
On some platforms (at least GNU/Linux, but I hear Windows and several others too), if you link together two static libraries that both export a symbol of the same name, it's undefined which symbol actually gets linked. In practice on my machine, the first library seems to win. This lets you defeat type/memory safety without the
unsafekeyword, by having two crates export a#[no_mangle] pub fnwith different signatures but compatible calling conventions:Despite the stated call to
two::convert, it's actuallyone::convertthat gets called, which interprets the argument as a&'static i32. (It may be clearer to understand with this simpler example, which doesn't break type safety.)On at least GNU/Linux but not other platforms like Windows or Darwin, dynamically-linked symbols have the same ambiguity.
I don't know what the right response is here. The following options all seem pretty reasonable:
unsafekeyword.#[no_mangle]export both a mangled and un-mangled name, and have Rust crates call each other via mangled names only, on the grounds that#[no_mangle]is for external interfaces, not for crates linking to crates. ("External interfaces" includes other Rust code using FFI, but FFI is unsafe.) This is analogous to howextern "C" fns export both a Rust-ABI symbol as well as a C-ABI shim, and a direct, safe Rust call to those function happens through the Rust ABI, not through the C ABI. I'm pretty sure that all production uses of#[no_mangle]areextern "C", anyway (see e.g. Can't define unsafe extern "C" fn #10025).#[no_mangle]on safe functions and data, and introduce a new#[unsafe_no_mangle], so it substring-matchesunsafe. (#[no_mangle]on unsafe functions or mutable statics is fine, since you need theunsafekeyword to get at them.)All of these are, I think, backwards-compatible.