summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-06-12 09:34:16 -0700
committerGitHub <noreply@github.com>2017-06-12 09:34:16 -0700
commit62f186629419fc234c5a815490d3bb800f935c69 (patch)
treed8b44a522a489dad4795ac35151c8745a792a927
parent31c06fb53e350e9eae8c1cfaab90bf857b1cc29e (diff)
parent21a44aa8de944adb84772a3544a5644ef15a945a (diff)
Auto merge of #742 - emilio:bitfields-revamp, r=fitzgen
ir: Prevent integer overflow when using word-size bitfields.
-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;
+};