rust-lang / rust-lang/rust-bindgen

Struct containing a pointer to multi-dimensional array that has one zero sized dimension.

Open
#1,153 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug I-failing-layout-test
Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

Hello,
I'm working on generating some valid C headers as property tests for bindgen, issue #970.
While filling in the generation logic I'm starting to come across code that makes
the csmith-fuzzing/predicate.py script cough. I don't know how many of these there
might be (or how many might be false alarms like #1151) so I'm open to just keeping a
public running list somewhere if raising issues as I encounter them isn't the preference.
I'm also open to sharing some of the generated
bonkers preliminary code
that bindgen is handling happily.

This also seems related to issue #684 which the property tests have run into as well.
This one only fails the csmith-fuzzing/predicate.py script though,
rustc seems to compile without errors so I thought I'd bring it up.

Sorry if the code looks insane, it's generated! 😰

Here's the result of rustup show:

Default host: x86_64-unknown-linux-gnu

installed toolchains
--------------------

stable-x86_64-unknown-linux-gnu
nightly-x86_64-unknown-linux-gnu (default)

active toolchain
----------------

nightly-x86_64-unknown-linux-gnu (default)
rustc 1.23.0-nightly (ff0f5de3b 2017-11-14)

Input C/C++ Header
struct {
    char *decl_4_0[0][4]; // fails
} struct_2_0;

// struct {
//     char decl_4_0[0][4]; // succeeds
// } struct_2_0;

// struct {
//     char *decl_4_0[1][4]; // succeeds
// } struct_2_0;
Bindgen Invocation

I've been using the csmith-fuzzing/predicate.py script to test so the failing invocation would look like this assuming that definition is in a header named prop_test.h

$ ./csmith-fuzzing/predicate.py prop_test.h
Actual Results

Script output:

Running: ['cargo', 'run', '--manifest-path', '/home/username/src/rust-bindgen/Cargo.toml', '--', 'prop_test.h', '-o', '/tmp/bindings-7_gwph30.rs', '--with-derive-partialeq', '--with-derive-eq', '--with-derive-partialord', '--with-derive-ord', '--with-derive-hash', '--with-derive-default']
Running: ['rustc', '--crate-type', 'lib', '--test', '-o', '/tmp/layout-tests-br4ipbog', '/tmp/bindings-7_gwph30.rs']
Running: ['/tmp/layout-tests-br4ipbog']
Error: running the compiled bindings' layout tests failed
+
+running 1 test
+test bindgen_test_layout__bindgen_ty_1 ... FAILED
+
+failures:
+
+---- bindgen_test_layout__bindgen_ty_1 stdout ----
+	thread 'bindgen_test_layout__bindgen_ty_1' panicked at 'assertion failed: `(left == right)`
+  left: `1`,
+ right: `8`: Alignment of _bindgen_ty_1', /tmp/bindings-7_gwph30.rs:52:4
+stack backtrace:
+   0:     0x55f6f4d49f63 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::h58b4c7cfb400b18c
+                               at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
+   1:     0x55f6f4d463ec - std::sys_common::backtrace::_print::h091e19687805d26e
+                               at /checkout/src/libstd/sys_common/backtrace.rs:68
+   2:     0x55f6f4d4c3b1 - std::panicking::default_hook::{{closure}}::h839e2a2e96c19d98
+                               at /checkout/src/libstd/sys_common/backtrace.rs:57
+                               at /checkout/src/libstd/panicking.rs:381
+   3:     0x55f6f4d4c0ac - std::panicking::default_hook::h892c050099854db5
+                               at /checkout/src/libstd/panicking.rs:391
+   4:     0x55f6f4d4c884 - std::panicking::rust_panic_with_hook::h09c5f7a0435ac463
+                               at /checkout/src/libstd/panicking.rs:577
+   5:     0x55f6f4d4c6bc - std::panicking::begin_panic::h321753ef82401d62
+                               at /checkout/src/libstd/panicking.rs:538
+   6:     0x55f6f4d4c639 - std::panicking::begin_panic_fmt::h24fe390b9054223d
+                               at /checkout/src/libstd/panicking.rs:522
+   7:     0x55f6f4d0839c - bindings_7_gwph30::bindgen_test_layout__bindgen_ty_1::hbdde4efabb33c38f
+   8:     0x55f6f4d17f61 - <F as test::FnBox<T>>::call_box::hc30672f430bdb600
+                               at /checkout/src/libtest/lib.rs:1491
+                               at /checkout/src/libcore/ops/function.rs:223
+                               at /checkout/src/libtest/lib.rs:142
+   9:     0x55f6f4d54ebe - __rust_maybe_catch_panic
+                               at /checkout/src/libpanic_unwind/lib.rs:99
+  10:     0x55f6f4d093b0 - std::sys_common::backtrace::__rust_begin_short_backtrace::h904f706bf2295342
+                               at /checkout/src/libstd/panicking.rs:459
+                               at /checkout/src/libstd/panic.rs:365
+                               at /checkout/src/libtest/lib.rs:1430
+                               at /checkout/src/libstd/sys_common/backtrace.rs:133
+  11:     0x55f6f4d0a052 - std::panicking::try::do_call::hba965e573c3ab44f
+                               at /checkout/src/libstd/thread/mod.rs:406
+                               at /checkout/src/libstd/panic.rs:300
+                               at /checkout/src/libstd/panicking.rs:480
+  12:     0x55f6f4d54ebe - __rust_maybe_catch_panic
+                               at /checkout/src/libpanic_unwind/lib.rs:99
+  13:     0x55f6f4d11942 - <F as alloc::boxed::FnBox<A>>::call_box::h3f8cad64dddfc3c1
+                               at /checkout/src/libstd/panicking.rs:459
+                               at /checkout/src/libstd/panic.rs:365
+                               at /checkout/src/libstd/thread/mod.rs:405
+                               at /checkout/src/liballoc/boxed.rs:762
+  14:     0x55f6f4d4b78b - std::sys::imp::thread::Thread::new::thread_start::he0774ede68aa21ab
+                               at /checkout/src/liballoc/boxed.rs:772
+                               at /checkout/src/libstd/sys_common/thread.rs:23
+                               at /checkout/src/libstd/sys/unix/thread.rs:90
+  15:     0x7f5de07de6b9 - start_thread
+  16:     0x7f5de02fe3dc - clone
+  17:                0x0 - <unknown>
+
+
+failures:
+    bindgen_test_layout__bindgen_ty_1
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
+

rustc output when given the generated code:

warning: found zero-sized type composed only of phantom-data in a foreign-function.
  --> err.rs:60:32
   |
60 |     pub static mut struct_2_0: _bindgen_ty_1;
   |                                ^^^^^^^^^^^^^
   |
   = note: #[warn(improper_ctypes)] on by default

Generated code:

/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Default)]
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
impl<T> __IncompleteArrayField<T> {
    #[inline]
    pub fn new() -> Self {
        __IncompleteArrayField(::std::marker::PhantomData)
    }
    #[inline]
    pub unsafe fn as_ptr(&self) -> *const T {
        ::std::mem::transmute(self)
    }
    #[inline]
    pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
        ::std::mem::transmute(self)
    }
    #[inline]
    pub unsafe fn as_slice(&self, len: usize) -> &[T] {
        ::std::slice::from_raw_parts(self.as_ptr(), len)
    }
    #[inline]
    pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
        ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
    }
}
impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        fmt.write_str("__IncompleteArrayField")
    }
}
impl<T> ::std::clone::Clone for __IncompleteArrayField<T> {
    #[inline]
    fn clone(&self) -> Self {
        Self::new()
    }
}
impl<T> ::std::marker::Copy for __IncompleteArrayField<T> {}
#[repr(C)]
#[derive(Debug)]
pub struct _bindgen_ty_1 {
    pub decl_4_0: __IncompleteArrayField<[*mut ::std::os::raw::c_char; 4usize]>,
}
#[test]
fn bindgen_test_layout__bindgen_ty_1() {
    assert_eq!(
        ::std::mem::size_of::<_bindgen_ty_1>(),
        0usize,
        concat!("Size of: ", stringify!(_bindgen_ty_1))
    );
    assert_eq!(
        ::std::mem::align_of::<_bindgen_ty_1>(),
        8usize,
        concat!("Alignment of ", stringify!(_bindgen_ty_1))
    );
}
extern "C" {
    #[link_name = "\u{1}_Z10struct_2_0"]
    pub static mut struct_2_0: _bindgen_ty_1;
}
Expected Results

🙃 I'm not quite fluent enough in bindgen output to answer this one.

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 with the reduced C++ header and run csmith-fuzzing/predicate.py prop_test.h to reproduce the generated layout-test failure. Inspect the generated Rust binding and the alignment assertion, then establish the expected handling for a pointer array with a zero-sized dimension; done means the predicate test reflects correct layout behavior without this failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, cpp, python, rust
Domain
devtools, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.