Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect field offset when C struct is __attribute__((packed, aligned(8))) #2878

Open
kurtmcmillan opened this issue Aug 7, 2024 · 0 comments

Comments

@kurtmcmillan
Copy link

Input C/C++ Header

struct foo
{
    int a;
    long b;
} __attribute__((packed, aligned(8)));

Bindgen Invocation

    let bindings = bindgen::Builder::default()
        .header("wrapper.h")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        .generate()
        .expect("Unable to generate bindings");

Actual Results

$ RUST_BACKTRACE=1 cargo test
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.02s
     Running unittests src/lib.rs (target/debug/deps/bindgen-8ef8fba8e13f0c4e)

running 1 test
test bindings::bindgen_test_layout_foo ... FAILED

failures:

---- bindings::bindgen_test_layout_foo stdout ----
thread 'bindings::bindgen_test_layout_foo' panicked at /home/kumcmill/bindgen/target/debug/build/bindgen-7cb8e559bd3e3745/out/bindings.rs:28:5:
assertion `left == right` failed: Offset of field: foo::b
  left: 8
 right: 4
stack backtrace:
   0: rust_begin_unwind
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/std/src/panicking.rs:652:5
   1: core::panicking::panic_fmt
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/panicking.rs:72:14
   2: core::panicking::assert_failed_inner
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/panicking.rs:403:23
   3: core::panicking::assert_failed
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/panicking.rs:363:5
   4: bindgen::bindings::bindgen_test_layout_foo
             at ./target/debug/build/bindgen-7cb8e559bd3e3745/out/bindings.rs:28:5
   5: bindgen::bindings::bindgen_test_layout_foo::{{closure}}
             at ./target/debug/build/bindgen-7cb8e559bd3e3745/out/bindings.rs:10:29
   6: core::ops::function::FnOnce::call_once
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/ops/function.rs:250:5
   7: core::ops::function::FnOnce::call_once
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.


failures:
    bindings::bindgen_test_layout_foo

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s

and/or

/* automatically generated by rust-bindgen 0.69.4 */

#[repr(C, packed(8))]
#[derive(Debug, Copy, Clone)]
pub struct foo {
    pub a: ::std::os::raw::c_int,
    pub b: ::std::os::raw::c_long,
}
#[test]
fn bindgen_test_layout_foo() {
    const UNINIT: ::std::mem::MaybeUninit<foo> = ::std::mem::MaybeUninit::uninit();
    let ptr = UNINIT.as_ptr();
    assert_eq!(
        ::std::mem::size_of::<foo>(),
        16usize,
        concat!("Size of: ", stringify!(foo))
    );
    assert_eq!(
        ::std::mem::align_of::<foo>(),
        8usize,
        concat!("Alignment of ", stringify!(foo))
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize },
        0usize,
        concat!("Offset of field: ", stringify!(foo), "::", stringify!(a))
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize },
        4usize,
        concat!("Offset of field: ", stringify!(foo), "::", stringify!(b))
    );
}

Expected Results

A data structure with two fields. The first field at offset 0 and the second field at offset 4.

I initially filed this issue against rust-lang/rust (#128373). It turned out to be a duplicate of E0587 error on packed and aligned structures from C.

The suggestion from rust-lang/rust in #127373 was to file this against bindgen with the recommendation to handle this case by generating a packed inner struct wrapped in an align(8) outer struct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant