rust-lang / rust-lang/rust-bindgen

bitfields: inconsistent size between --opaque-type and not (both wrong)

Open
#3,349 0 comments 0 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

bindgen version: 0.72.1

for the following struct

typedef struct
{
    NvU32 vic                     : 8;
    NvU32 pixelRepeat             : 5;
    NvU32 colorSpace              : 3;
    NvU32 colorimetry             : 3;
    NvU32 extendedColorimetry     : 4;
    NvU32 rgbQuantizationRange    : 3;
    NvU32 yccQuantizationRange    : 3;
    NvU32 itContent               : 2;
    NvU32 contentTypes            : 3;
    NvU32 scanInfo                : 3;
    NvU32 activeFormatInfoPresent : 2;
    NvU32 activeFormatAspectRatio : 5;
    NvU32 picAspectRatio          : 3;
    NvU32 nonuniformScaling       : 3;
    NvU32 barInfo                 : 3;
    NvU32 top_bar                 : 17;
    NvU32 bottom_bar              : 17;
    NvU32 left_bar                : 17;
    NvU32 right_bar               : 17;
    NvU32 Future17                : 2;
    NvU32 Future47                : 2;
} NV_INFOFRAME_VIDEO;

bindgen gives:

  • a 23 * 8 size struct (which doesn't pass assertions) normally
  • a 4 * 32 size struct (which is wrong) with --opaque-type

The right size would be probably [32; 6] because this is a struct built with 32 bit integers (so aligned on 4 bytes) as both latest clang and msvc report: godbolt.

Notably bindgen outputs the right alignment (#[repr(align(4))]) but then ignores it when computing what the actual size of the struct should be.

normal output

#[repr(C)]
pub struct NV_INFOFRAME_VIDEO {
    pub _bitfield_align_1: [u32; 0],
    pub _bitfield_1: __BindgenBitfieldUnit<[u8; 23usize]>,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of NV_INFOFRAME_VIDEO"][::core::mem::size_of::<NV_INFOFRAME_VIDEO>() - 16usize];
    ["Alignment of NV_INFOFRAME_VIDEO"][::core::mem::align_of::<NV_INFOFRAME_VIDEO>() - 4usize];
};

output with --opaque-type

#[repr(C)]
#[repr(align(4))]
pub struct NV_INFOFRAME_VIDEO {
    pub _bindgen_opaque_blob: [u32; 4usize],
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of NV_INFOFRAME_VIDEO"][::core::mem::size_of::<NV_INFOFRAME_VIDEO>() - 16usize];
    ["Alignment of NV_INFOFRAME_VIDEO"][::core::mem::align_of::<NV_INFOFRAME_VIDEO>() - 4usize];
};

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 NV_INFOFRAME_VIDEO example with bindgen 0.72.1, both normally and with --opaque-type, and compare the generated Rust size and alignment assertions with clang and MSVC results from the linked Godbolt example. Done means both paths agree on the correct 32-bit integer layout and the generated size and alignment assertions pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, rust
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.