rust_libloading icon indicating copy to clipboard operation
rust_libloading copied to clipboard

Document unsafety of functions with 'static-containing return types.

Open tormol opened this issue 5 years ago • 2 comments

Return values from functions that contain 'static lifetimes are not reduced to the lifetime of the loaded library, and can outlive it. Preventing this is probably impossible (especially when the 'static is hidden inside a type like Wrapper(&'static u32)), but the docs could warn about it.

Here's one example that segfaults:

Cargo.toml:

[package]
name = "unsafe_libloading"
version = "0.0.0"

[lib]
path = "lib.rs"
name = "loadee"
crate-type = ["dylib"]

[[bin]]
name = "loader"
path = "main.rs"

[dependencies]
libloading = "0.5"

lib.rs:

#[no_mangle]
pub fn get_str() -> &'static str {
    "Hello, world"
}

main.rs:

extern crate libloading;

fn main() -> libloading::Result<()> {
    let lib = libloading::Library::new("libloadee.so")?;
    let return_value: &'static str = {
        let fun: libloading::Symbol<extern fn()->&'static str> = unsafe{ lib.get(b"get_str") }?;
        fun()
    };
    drop(lib);
    println!("return value: {}", return_value);
    Ok(())
}

I assume this issue also applies to loaded global variables, but dereferencing those produced bogus values even without dropping lib:

lib.rs:

#[no_mangle]
pub static REF: &'static u16 = &19;

main.rs:

extern crate libloading;

fn main() -> libloading::Result<()> {
    let lib = libloading::Library::new("libloadee.so")?;
    let var: libloading::Symbol<&'static u16> = unsafe{ lib.get(b"REF") }?;
    let dereferenced: u16 = **ref;
    println!("variable: {} = 0x{:x}", dereferenced, dereferenced);
    Ok(())
}

prints "variable: 27312 = 0x6ab0"

tormol avatar Aug 29 '18 14:08 tormol