gnzlbg / ctest

Automatic testing of FFI bindings for Rust
https://docs.rs/ctest
Apache License 2.0
122 stars 29 forks source link

Use of uninitialized warns on 1.36.0 #84

Open sfackler opened 5 years ago

sfackler commented 5 years ago
warning: the type `unsafe extern "C" fn() -> !` does not permit being left uninitialized
    --> /home/sfackler/code/rstack/target/debug/build/dw-systest-b765583e4de77b6a/out/all.rs:7830:34
     |
7830 |                   let mut y: U = uninitialized();
     |                                  ^^^^^^^^^^^^^^^
     |                                  |
     |                                  this code causes undefined behavior when executed
     |                                  help: use `MaybeUninit<T>` instead
     |
     = note: Function pointers must be non-null
gnzlbg commented 5 years ago

@sfackler I don't think there is a good and simple way to fix this

cc @ralfj

gnzlbg commented 5 years ago

The code that generates that use of uninitialized tests the "call ABI" of a type. It does this by initializing a value of that type to a byte pattern where each byte contains a different value, and then passing it by value to some C code that test that these bytes did not change value.

On Rust >= 1.36.0 we could just use MaybeUninit<T> for this, and pass the MaybeUninit to C instead (its repr(transparent) so the call ABI of the T is used). But on Rust < 1.36.0... I don't think there is anything that we can do.

If the Rust version is old enough repr(transparent) isn't available, so we can't use any kind of wrapper type to avoid violating the validity invariant (and if repr(transparent) is available, we can really provide our own MaybeUninit type without proper unions and other features that were stabilized later or haven't even been stabilized yet). Without any of that, there isn't really a way to avoid violating the validity invariant somewhere.

gnzlbg commented 5 years ago

warning: the type unsafe extern "C" fn() -> !

@sfackler - slightly unrelated, but if you are using unsafe extern "C" fn() -> ! in your library FFI as a "return value" (or output argument) of C, you need to make sure that C guarantees that it never sets it to null, or else that's UB. Using Option<unsafe extern "C" fn() -> !> fixes that issue in your library, but not in ctest tests because creating an uninitialized Option is UB as well.