rust-bindgen
rust-bindgen copied to clipboard
SIGSEGV / Segfault in 0.61.0
I just upgraded bindgen to 0.63.0 and was greeted with a segfault. A little bit of manual bisect yielded version 0.61.0 as the first offender.
I'll start digging deeper into the issue soon, I plan to do a git bisect to figure out the commit that introduced the issue and if that doesn't help try to get my build-system running with gdb attached for a backtrace. I'm also open to other debugging suggestions.
Note: this could be duplicate of #2035, but bindgen still works fine for me up until the segfault in 0.61.0 and above.
Input C/C++ Header
It's a large code base with long build times, I'd rather not try to find a minimal reproducer if possible.
Bindgen Invocation
bindgen::Builder::default()
.derive_debug(true)
.derive_default(true)
.impl_debug(true)
.generate_comments(true)
.default_enum_style(bindgen::EnumVariation::NewType {
is_bitfield: false,
is_global: false, // new in `0.61.0`, same crash with `true`
})
.header("wrapper.h")
.clang_args(crate::bindgen_clang_args()) // extracted from build target
.allowlist_*("...")
.blocklist_function("main_loop_wait") // bindgen issue #1313
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
Actual Results
error: failed to run custom build command for `crate`
Caused by:
process didn't exit successfully: `/crate-b7933947bb539228/build-script-build` (signal: 11, SIGSEGV: invalid memory reference)
Expected Results
No segfault.
These kind of errors are usually bugs while using the clang-sys crate so I suspect that the introduction of the EnumVariation::NewType::is_global field is not the issue as that PR only changed code generation.
I'd be grateful if you could either try and git bisect this as you mentioned or provide case that I can actually run.
There you go:
a5848cf44e02645cddf020609ea67340cf6e3d24 is the first bad commit
commit a5848cf44e02645cddf020609ea67340cf6e3d24
Author: Collin Baker <[email protected]>
Date: Wed Jul 20 11:57:16 2022 -0400
Generate opaque type for template param dependent bit field width
libclang's API does not provide a straightforward way to check for
this, and calling clang_getFieldDeclBitWidth is actively unsafe in
this case. See https://github.com/llvm/llvm-project/issues/56644
We probably can't generate reasonable bindings for such a type, so
make the binding opaque.
Ideally libclang would report if the bit width could not be
evaluated. Unfortunately making such a change would mean bumping the
minimum libclang version from 6.0 to 15.0.
Instead, add logic to traverse the AST subtree starting from the
field's bit width specifier looking for template parameters. If we
find one, we make the resulting type opaque.
src/clang.rs | 96 +++++++++++++++++++++-
src/ir/comp.rs | 26 +++++-
.../issue-2239-template-dependent-bit-width.rs | 19 +++++
.../issue-2239-template-dependent-bit-width.hpp | 10 +++
4 files changed, 147 insertions(+), 4 deletions(-)
create mode 100644 tests/expectations/tests/issue-2239-template-dependent-bit-width.rs
create mode 100644 tests/headers/issue-2239-template-dependent-bit-width.hpp
Ugh... it's no surprise this has to do with C++ templates.
The issue is still present in 0.66.1 and because LLVM 16 is now hitting the distros I can't now no longer build using the 0.60.1 due to #2319.
If we can't figure this issue out in the near future I would appreciate a backport of the #2319 fix.
could you give me a reproducible example so we can work on it?
Yes, but it is far from minimized:
- clone
https://github.com/fuzzware-fuzzer/hoedur.git - bump version in
qemu-build/Cargo.toml - fix
qemu-build/src/bindings.rs(is_global: false) cargo build -p qemu-sys --features arm
So I have done some work on this.
The offender is
typedef struct a a;
struct a {
a *b;
};
enum { c };
_Static_assert(!(sizeof(struct {
int : (__builtin_types_compatible_p(typeof(0), typeof((a *)0)) ? 0 : 1);
}) <= c), "Static assertion failed");
This segfaults bindgen 0.69.4 in a docker container with clang 17. It segfaults bindgen on my mac with clang 15. Interestingly it doesn't segfault 0.60.1 bindgen on my mac.
I have attached the preprocessed headers in one file (gzipped) if that is helpful. __bindgen.i.gz
The creduce output was
typedef struct a a;
struct a {
a *b
};
enum { c };
_Static_assert(!sizeof(struct {
int : __builtin_types_compatible_p(typeof(0), typeof((a *)0)) ?: 1
}) <= c);
which I modified to get rid of some clang warnings.
Thread 1 "bindgen" received signal SIGSEGV, Segmentation fault.
0x0000555557d40fd6 in core::ptr::const_ptr::{impl#0}::is_aligned_to<isize> (self=0x7ffff7ea5bf0, align=8) at /home/boydjohnson/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/const_ptr.rs:1605
1605 pub const fn is_aligned_to(self, align: usize) -> bool {
(gdb) bt
#0 0x0000555557d40fd6 in core::ptr::const_ptr::{impl#0}::is_aligned_to<isize> (self=0x7ffff7ea5bf0, align=8)
at /home/boydjohnson/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/const_ptr.rs:1605
#1 0x0000555557d3e7b0 in core::ptr::const_ptr::{impl#0}::is_aligned<isize> (self=0x7ffff7ea5bf0)
at /home/boydjohnson/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/const_ptr.rs:1494
#2 0x0000555557fb54c1 in core::intrinsics::is_aligned_and_not_null<isize> (ptr=0x7ffff7ea5bf0)
This is the head of the gdb output.
Thanks for you work :)
Interestingly it doesn't segfault 0.60.1 bindgen on my mac.
That's expected, 0.60.1 is the last version without the troublesome commit.