summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-06-10 13:44:06 +0200
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-06-10 13:44:59 +0200
commit21a44aa8de944adb84772a3544a5644ef15a945a (patch)
treec97b037c5ac18c8ef08640487795c1f7c7e4517d
parentc0389c3c7a77187c36ebeffc63bc5e6e43a0d11a (diff)
ir: Prevent integer overflow when using word-size bitfields.
Fixes #739
-rw-r--r--src/ir/comp.rs15
-rw-r--r--tests/expectations/tests/issue-739-pointer-wide-bitfield.rs22
-rw-r--r--tests/headers/issue-739-pointer-wide-bitfield.h8
3 files changed, 44 insertions, 1 deletions
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 5be20416..171f130c 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -293,8 +293,21 @@ impl Bitfield {
/// Get the mask value that when &'ed with this bitfield's allocation unit
/// produces this bitfield's value.
+ ///
+ /// TODO(emilio): This should probably use the target's word size, and what
+ /// about bitfields that are bigger than that?
pub fn mask(&self) -> usize {
- ((1usize << self.width()) - 1usize) << self.offset_into_unit()
+ use std::mem;
+ use std::usize;
+
+ let unoffseted_mask =
+ if self.width() as usize == mem::size_of::<usize>() * 8 {
+ usize::MAX
+ } else {
+ ((1usize << self.width()) - 1usize)
+ };
+
+ unoffseted_mask << self.offset_into_unit()
}
/// Get the bit width of this bitfield.
diff --git a/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs b/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs
new file mode 100644
index 00000000..17e63981
--- /dev/null
+++ b/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs
@@ -0,0 +1,22 @@
+/* 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)]
+pub struct Foo {
+ pub _bitfield_1: [u64; 4usize],
+ pub __bindgen_align: [u64; 0usize],
+}
+#[test]
+fn bindgen_test_layout_Foo() {
+ assert_eq!(::std::mem::size_of::<Foo>() , 32usize , concat ! (
+ "Size of: " , stringify ! ( Foo ) ));
+ assert_eq! (::std::mem::align_of::<Foo>() , 8usize , concat ! (
+ "Alignment of " , stringify ! ( Foo ) ));
+}
+impl Clone for Foo {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/headers/issue-739-pointer-wide-bitfield.h b/tests/headers/issue-739-pointer-wide-bitfield.h
new file mode 100644
index 00000000..611dab1d
--- /dev/null
+++ b/tests/headers/issue-739-pointer-wide-bitfield.h
@@ -0,0 +1,8 @@
+#define POINTER_WIDTH (sizeof(void*) * 8)
+
+struct Foo {
+ unsigned long m_bitfield: POINTER_WIDTH;
+ unsigned long m_bar: POINTER_WIDTH;
+ unsigned long foo: 1;
+ unsigned long bar: POINTER_WIDTH;
+};