rust-lang / rust-lang/rust-bindgen
Incorrect field offset when C struct is __attribute__((packed, aligned(8)))
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.3k
- Forks
- 829
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 15
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the wrapper.h struct and the generated bindings shown in the issue, then run the provided cargo test reproduction. Check how bindgen represents packed and aligned C structs; done means the generated layout preserves field offsets 0 and 4 while retaining the expected size and alignment.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, cpp, rust
- Domain
- compilers, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100