rust-lang / rust-lang/rust-bindgen

Wrong code generated for union with bitfields

Open
#3,184 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

The below outputs are with bindgen 0.71.1 (no flags) on x86_64-pc-windows-msvc.

Consider the union below. There are two issues:

  • The accessors for bitfld_b and bitfld_c use bit offsets of 4 and 8, respectively, while they should be 0.
  • The generated type has the wrong size, resulting in a compile error. The C type has size 4 and alignment 1, but the generated type has size 2. (On x86_64-unknown-linux-gnu it happens to compile(!) because the alignment is 4 which makes the size also 4.) Therefore, padding needs to be added.

Don't ask me why someone put a bitfield in a union. (The case I found was an anonymous union in a struct, but that doesn't seem to make a difference.)

Header file
union Union {
    int bitfld_a : 4;
    int bitfld_b : 4;
    int bitfld_c : 4;
};
Generated code (excerpt)
#[repr(C)]
#[derive(Copy, Clone)]
pub union Union {
    pub _bitfield_align_1: [u8; 0],
    pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>,
    //                                          ^^^^^^ should be 4usize
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of Union"][::std::mem::size_of::<Union>() - 4usize];
    ["Alignment of Union"][::std::mem::align_of::<Union>() - 1usize];
};
impl Union {
    // ...
    pub fn bitfld_b(&self) -> ::std::os::raw::c_int {
        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) }
        //                                                  ^^^^^^ should be 0usize
    }
    // ...
}
Compile error
error[E0080]: evaluation of constant value failed
   --> bindings.rs:148:23
    |
148 |     ["Size of Union"][::std::mem::size_of::<Union>() - 4usize];
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `2_usize - 4_usize`, which would overflow
Full output

Generated code
Debug log

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the issue from the C union in the report with bindgen 0.71.1, then inspect the generated bindings.rs output and the bitfield layout/accessor generation path. Add regression coverage for the union case and verify that the generated accessors use the correct offsets and that the type has size 4 and alignment 1.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, rust
Domain
compilers, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.