summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2017-11-01 15:57:50 -0700
committerNick Fitzgerald <fitzgen@gmail.com>2017-11-01 16:17:01 -0700
commit8592f3677b7d9624ac6bd64df46a962c92b4561f (patch)
treed969538f9276d9860f7ad7d2528629e49bfeaefd
parentddb680b27db6581070b7b4fb03ea1119167a0bd3 (diff)
Avoid divide-by-zero when checking if a field will merge with bitfields
-rw-r--r--src/codegen/struct_layout.rs7
-rw-r--r--tests/expectations/tests/divide-by-zero-in-struct-layout.rs45
-rw-r--r--tests/headers/divide-by-zero-in-struct-layout.h22
3 files changed, 72 insertions, 2 deletions
diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs
index c3c781cb..ca46947d 100644
--- a/src/codegen/struct_layout.rs
+++ b/src/codegen/struct_layout.rs
@@ -335,9 +335,12 @@ impl<'a> StructLayoutTracker<'a> {
new_field_layout
);
+ // Avoid divide-by-zero errors if align is 0.
+ let align = cmp::max(1, layout.align);
+
if self.last_field_was_bitfield &&
- new_field_layout.align <= layout.size % layout.align &&
- new_field_layout.size <= layout.size % layout.align
+ new_field_layout.align <= layout.size % align &&
+ new_field_layout.size <= layout.size % align
{
// The new field will be coalesced into some of the remaining bits.
//
diff --git a/tests/expectations/tests/divide-by-zero-in-struct-layout.rs b/tests/expectations/tests/divide-by-zero-in-struct-layout.rs
new file mode 100644
index 00000000..9fb429af
--- /dev/null
+++ b/tests/expectations/tests/divide-by-zero-in-struct-layout.rs
@@ -0,0 +1,45 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct WithBitfield {
+ pub _bitfield_1: [u8; 0usize],
+ pub __bindgen_padding_0: u32,
+ pub a: ::std::os::raw::c_uint,
+}
+impl WithBitfield {
+ #[inline]
+ pub fn new_bitfield_1() -> u8 {
+ 0
+ }
+}
+#[repr(C, packed)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct WithBitfieldAndAttrPacked {
+ pub _bitfield_1: [u8; 0usize],
+ pub a: ::std::os::raw::c_uint,
+ pub __bindgen_padding_0: u8,
+}
+impl WithBitfieldAndAttrPacked {
+ #[inline]
+ pub fn new_bitfield_1() -> u8 {
+ 0
+ }
+}
+#[repr(C, packed)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct WithBitfieldAndPacked {
+ pub _bitfield_1: [u8; 0usize],
+ pub a: ::std::os::raw::c_uint,
+ pub __bindgen_padding_0: u8,
+}
+impl WithBitfieldAndPacked {
+ #[inline]
+ pub fn new_bitfield_1() -> u8 {
+ 0
+ }
+}
diff --git a/tests/headers/divide-by-zero-in-struct-layout.h b/tests/headers/divide-by-zero-in-struct-layout.h
new file mode 100644
index 00000000..470250d3
--- /dev/null
+++ b/tests/headers/divide-by-zero-in-struct-layout.h
@@ -0,0 +1,22 @@
+// bindgen-flags: --no-layout-tests
+//
+// Unfortunately, we aren't translating the second and third structs correctly
+// yet. But we definitely shouldn't divide-by-zero when we see it...
+//
+// Once we fix #981 we should remove the `--no-layout-tests`.
+
+struct WithBitfield {
+ unsigned : 7;
+ unsigned a;
+};
+
+struct WithBitfieldAndAttrPacked {
+ unsigned : 7;
+ unsigned a;
+} __attribute__((packed));
+
+#pragma pack(1)
+struct WithBitfieldAndPacked {
+ unsigned : 7;
+ unsigned a;
+};