From 21a44aa8de944adb84772a3544a5644ef15a945a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 10 Jun 2017 13:44:06 +0200 Subject: [PATCH] ir: Prevent integer overflow when using word-size bitfields. Fixes #739 --- src/ir/comp.rs | 15 ++++++++++++- .../tests/issue-739-pointer-wide-bitfield.rs | 22 +++++++++++++++++++ .../headers/issue-739-pointer-wide-bitfield.h | 8 +++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/expectations/tests/issue-739-pointer-wide-bitfield.rs create mode 100644 tests/headers/issue-739-pointer-wide-bitfield.h diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 5be2041679..171f130c2a 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::() * 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 0000000000..17e6398138 --- /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::() , 32usize , concat ! ( + "Size of: " , stringify ! ( Foo ) )); + assert_eq! (::std::mem::align_of::() , 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 0000000000..611dab1da0 --- /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; +};