Skip to content

Commit 05dea3a

Browse files
committed
ir: Prevent integer overflow when using word-size bitfields.
1 parent c0389c3 commit 05dea3a

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

src/ir/comp.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,21 @@ impl Bitfield {
293293

294294
/// Get the mask value that when &'ed with this bitfield's allocation unit
295295
/// produces this bitfield's value.
296+
///
297+
/// TODO(emilio): This should probably use the target's word size, and what
298+
/// about bitfields that are bigger than that?
296299
pub fn mask(&self) -> usize {
297-
((1usize << self.width()) - 1usize) << self.offset_into_unit()
300+
use std::mem;
301+
use std::usize;
302+
303+
let unoffseted_mask =
304+
if self.width() as usize == mem::size_of::<usize>() * 8 {
305+
usize::MAX
306+
} else {
307+
((1usize << self.width()) - 1usize)
308+
};
309+
310+
unoffseted_mask << self.offset_into_unit()
298311
}
299312

300313
/// Get the bit width of this bitfield.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Default, Copy)]
9+
pub struct Foo {
10+
pub _bitfield_1: [u64; 4usize],
11+
pub __bindgen_align: [u64; 0usize],
12+
}
13+
#[test]
14+
fn bindgen_test_layout_Foo() {
15+
assert_eq!(::std::mem::size_of::<Foo>() , 32usize , concat ! (
16+
"Size of: " , stringify ! ( Foo ) ));
17+
assert_eq! (::std::mem::align_of::<Foo>() , 8usize , concat ! (
18+
"Alignment of " , stringify ! ( Foo ) ));
19+
}
20+
impl Clone for Foo {
21+
fn clone(&self) -> Self { *self }
22+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#define POINTER_WIDTH (sizeof(void*) * 8)
2+
3+
struct Foo {
4+
unsigned long m_bitfield: POINTER_WIDTH;
5+
unsigned long m_bar: POINTER_WIDTH;
6+
unsigned long foo: 1;
7+
unsigned long bar: POINTER_WIDTH;
8+
};

0 commit comments

Comments
 (0)