rust-lang / rust-lang/rust-bindgen

Avoid use of non-FFI safe type u128 for alignment

Open
#2,105 4 comments 3 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

Input C/C++ Header
typedef struct _Foo {} __attribute__((__aligned__(16))) Foo;
typedef struct _Bar {} __attribute__((__aligned__(16))) Bar;

Foo *foo_new();
Bar *bar_new();
Bindgen Invocation
$ bindgen input.h --allowlist-function '.*' --opaque-type Foo --opaque-type _Bar --no-layout-tests
Actual Results
/* automatically generated by rust-bindgen 0.59.1 */

pub type Foo = [u128; 0usize];
#[repr(C)]
#[repr(align(16))]
#[derive(Debug, Copy, Clone)]
pub struct _Bar {
    pub _bindgen_opaque_blob: [u128; 0usize],
}
pub type Bar = _Bar;
extern "C" {
    pub fn foo_new() -> *mut Foo;
}
extern "C" {
    pub fn bar_new() -> *mut Bar;
}
Expected Results

The issue with this codegen is that u128 is used to get the 16-bytes alignment, but its use causes warnings:

warning: `extern` block uses type `u128`, which is not FFI-safe
  --> new.rs:25:25
   |
25 |     pub fn foo_new() -> *mut Foo;
   |                         ^^^^^^^^ not FFI-safe
   |
   = note: `#[warn(improper_ctypes)]` on by default
   = note: 128-bit integers don't currently have a known stable ABI

Instead, it would be better if the generated code used the #[repr(align(16))] for alignment, and only used u8 for sizes. However, this isn't always easily doable.

I included both Foo and Bar examples because the bar one is easily fixable, replacing u128 with u8, as the struct is properly aligned.
However, in the case of Foo, #[repr(align(...))] cannot be used directly. A solution would be to codegen:

#[repr(align(16))]
pub struct Foo([u8; 0usize]);

or to do the same codegen as is done for _Bar:

#[repr(align(16))]
pub struct Foo {
    pub _bindgen_opaque_blob = [u8; 0usize],
}

i'm not entirely sure when bindgen decides to use a type alias, or use a struct with a single opaque field.

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 bindgen invocation with the supplied input.h and compare the generated representations of Foo and Bar. Trace the codegen path that chooses the type alias or opaque struct form; done means aligned opaque types use u8-based storage and avoid the u128 FFI-safety warning while preserving the required alignment.

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
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.