Rust-bindgen: bindgen generates union with u128 member for alignment which is UB for FFI

Created on 12 May 2019  路  3Comments  路  Source: rust-lang/rust-bindgen

Input C/C++ Header

typedef union __declspec(align(16)) TestUnion
{
    unsigned long Longs[2];
    unsigned int  Ints[4];
} TestUnion;

Bindgen Invocation

bindgen .\test.h -o test.rs

Actual Results

#[repr(C)]
#[repr(align(16))]
#[derive(Copy, Clone)]
pub union TestUnion {
    pub Longs: [::std::os::raw::c_ulong; 2usize],
    pub Ints: [::std::os::raw::c_uint; 4usize],
    _bindgen_union_align: u128,
}

Expected Results

I believe the u128 member of the union is unnessecary and actually triggers a warning (improper_ctypes) as u128s are not stable across the FFI boundary. My understanding here is that #[repr(align(16))] is sufficient to ensure the correct alignment for this union.

I-bogus-codegen bug help wanted

All 3 comments

@emilio Would this be the desired behavior?

  • If the Rust version is => 1.25: Use #[repr(align(n))]. Do not add fields to the struct.
  • If the Rust version is < 1.25: Align up the struct size by adding fields to it, as long as these are stable across FFI boundaries (therefore, do not use u128). Do not use #[repr(align(n))]

Yes, that's right, though it's even simpler, given support for repr(align) predates support for u128 / i128. So we should just not generate that alignment field if repr(align) is supported, and add a test.

Was this page helpful?
0 / 5 - 0 ratings