diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-06-10 13:44:06 +0200 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-06-10 13:44:59 +0200 |
commit | 21a44aa8de944adb84772a3544a5644ef15a945a (patch) | |
tree | c97b037c5ac18c8ef08640487795c1f7c7e4517d | |
parent | c0389c3c7a77187c36ebeffc63bc5e6e43a0d11a (diff) |
ir: Prevent integer overflow when using word-size bitfields.
Fixes #739
-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; +}; |