Skip to content

Commit

Permalink
Don't generate 2^64 byte padding fields on unions
Browse files Browse the repository at this point in the history
The --explicit-padding flag would make bindgen try to add tail padding
to rust unions, by adding up the size of all the union fields and
subtracting from the size of the union as given by clang. The total size
of a union's fields is always larger than the union, so the subtraction
underflowed and bindgen produced padding fields larger than addressable
RAM.
  • Loading branch information
tbodt authored and emilio committed Oct 27, 2021
1 parent 9738fb9 commit 5785340
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/codegen/struct_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ impl<'a> StructLayoutTracker<'a> {
return None;
}

// Padding doesn't make sense for rust unions.
if self.is_rust_union {
return None;
}

if self.latest_offset == comp_layout.size {
// This struct does not contain tail padding.
return None;
Expand Down
65 changes: 65 additions & 0 deletions tests/expectations/tests/explicit-padding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,68 @@ fn bindgen_test_layout_pad_me() {
)
);
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union dont_pad_me {
pub first: u8,
pub second: u32,
pub third: u16,
}
#[test]
fn bindgen_test_layout_dont_pad_me() {
assert_eq!(
::std::mem::size_of::<dont_pad_me>(),
4usize,
concat!("Size of: ", stringify!(dont_pad_me))
);
assert_eq!(
::std::mem::align_of::<dont_pad_me>(),
4usize,
concat!("Alignment of ", stringify!(dont_pad_me))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<dont_pad_me>())).first as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(dont_pad_me),
"::",
stringify!(first)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<dont_pad_me>())).second as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(dont_pad_me),
"::",
stringify!(second)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<dont_pad_me>())).third as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(dont_pad_me),
"::",
stringify!(third)
)
);
}
impl Default for dont_pad_me {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
6 changes: 6 additions & 0 deletions tests/headers/explicit-padding.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ struct pad_me {
uint32_t second;
uint16_t third;
};

union dont_pad_me {
uint8_t first;
uint32_t second;
uint16_t third;
};

0 comments on commit 5785340

Please sign in to comment.