diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-06-12 09:34:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-12 09:34:16 -0700 |
commit | 62f186629419fc234c5a815490d3bb800f935c69 (patch) | |
tree | d8b44a522a489dad4795ac35151c8745a792a927 | |
parent | 31c06fb53e350e9eae8c1cfaab90bf857b1cc29e (diff) | |
parent | 21a44aa8de944adb84772a3544a5644ef15a945a (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.rs | 15 | ||||
-rw-r--r-- | tests/expectations/tests/issue-739-pointer-wide-bitfield.rs | 22 | ||||
-rw-r--r-- | tests/headers/issue-739-pointer-wide-bitfield.h | 8 |
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; +}; |