Skip to content

Commit 58d19c0

Browse files
committed
Fix an UB in layout tests
- Replaced dereferencing of null ptr with zero bit pattern + transmute + std::ptr::addr_of! to avoid UB. It affects only checks of fields offsets - Overwritten expected with BINDGEN_OVERWRITE_EXPECTED=1 - Overwritten test_multiple_header_calls_in_builder and test_mixed_header_and_header_contents manually because rust-lang#2054 - Do not check the layout for repr(C) unions - Do not call the destructor of tmp struct to avoid other UB
1 parent e6684dc commit 58d19c0

File tree

230 files changed

+12585
-3807
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

230 files changed

+12585
-3807
lines changed

src/codegen/mod.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,8 +2084,12 @@ impl CodeGenerator for CompInfo {
20842084
.count() >
20852085
1;
20862086

2087+
2088+
// The offset of #[repr(C)] union is always 0, don't need to recheck it.
2089+
let is_not_packed_union = is_union && !packed;
2090+
20872091
let should_skip_field_offset_checks =
2088-
is_opaque || too_many_base_vtables;
2092+
is_opaque || too_many_base_vtables || is_not_packed_union;
20892093

20902094
let check_field_offset = if should_skip_field_offset_checks
20912095
{
@@ -2105,8 +2109,26 @@ impl CodeGenerator for CompInfo {
21052109

21062110
Some(quote! {
21072111
assert_eq!(
2108-
unsafe {
2109-
&(*(::#prefix::ptr::null::<#canonical_ident>())).#field_name as *const _ as usize
2112+
{
2113+
// Create an instance of #canonical_ident struct from zero bit pattern
2114+
const STRUCT_SIZE: usize = std::mem::size_of::<#canonical_ident>();
2115+
let buffer = [0u8; STRUCT_SIZE];
2116+
let struct_instance = unsafe {
2117+
// It's safe since #canonical_ident struct allows zero bit pattern
2118+
std::mem::transmute::<[u8; STRUCT_SIZE], #canonical_ident>(buffer)
2119+
};
2120+
// Get the pointers to the struct and its field
2121+
let struct_ptr = &struct_instance as *const #canonical_ident;
2122+
let field_ptr = std::ptr::addr_of!(struct_instance.#field_name);
2123+
2124+
// Get the offset of the field
2125+
let struct_address = struct_ptr as usize;
2126+
let field_address = field_ptr as usize;
2127+
2128+
//Do not call the destructor
2129+
std::mem::forget(struct_instance);
2130+
2131+
field_address.checked_sub(struct_address).unwrap()
21102132
},
21112133
#field_offset,
21122134
concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name))

tests/expectations/tests/16-byte-alignment.rs

Lines changed: 120 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,24 @@ fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1() {
4343
)
4444
);
4545
assert_eq!(
46-
unsafe {
47-
&(*(::std::ptr::null::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>(
48-
)))
49-
.dport as *const _ as usize
46+
{
47+
const STRUCT_SIZE: usize = std::mem::size_of::<
48+
rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1,
49+
>();
50+
let buffer = [0u8; STRUCT_SIZE];
51+
let struct_instance = unsafe {
52+
std::mem::transmute::<
53+
[u8; STRUCT_SIZE],
54+
rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1,
55+
>(buffer)
56+
};
57+
let struct_ptr = &struct_instance
58+
as *const rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1;
59+
let field_ptr = std::ptr::addr_of!(struct_instance.dport);
60+
let struct_address = struct_ptr as usize;
61+
let field_address = field_ptr as usize;
62+
std::mem::forget(struct_instance);
63+
field_address.checked_sub(struct_address).unwrap()
5064
},
5165
0usize,
5266
concat!(
@@ -57,10 +71,24 @@ fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1() {
5771
)
5872
);
5973
assert_eq!(
60-
unsafe {
61-
&(*(::std::ptr::null::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>(
62-
)))
63-
.sport as *const _ as usize
74+
{
75+
const STRUCT_SIZE: usize = std::mem::size_of::<
76+
rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1,
77+
>();
78+
let buffer = [0u8; STRUCT_SIZE];
79+
let struct_instance = unsafe {
80+
std::mem::transmute::<
81+
[u8; STRUCT_SIZE],
82+
rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1,
83+
>(buffer)
84+
};
85+
let struct_ptr = &struct_instance
86+
as *const rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1;
87+
let field_ptr = std::ptr::addr_of!(struct_instance.sport);
88+
let struct_address = struct_ptr as usize;
89+
let field_address = field_ptr as usize;
90+
std::mem::forget(struct_instance);
91+
field_address.checked_sub(struct_address).unwrap()
6492
},
6593
2usize,
6694
concat!(
@@ -83,19 +111,6 @@ fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1() {
83111
4usize,
84112
concat!("Alignment of ", stringify!(rte_ipv4_tuple__bindgen_ty_1))
85113
);
86-
assert_eq!(
87-
unsafe {
88-
&(*(::std::ptr::null::<rte_ipv4_tuple__bindgen_ty_1>())).sctp_tag
89-
as *const _ as usize
90-
},
91-
0usize,
92-
concat!(
93-
"Offset of field: ",
94-
stringify!(rte_ipv4_tuple__bindgen_ty_1),
95-
"::",
96-
stringify!(sctp_tag)
97-
)
98-
);
99114
}
100115
impl Default for rte_ipv4_tuple__bindgen_ty_1 {
101116
fn default() -> Self {
@@ -119,9 +134,18 @@ fn bindgen_test_layout_rte_ipv4_tuple() {
119134
concat!("Alignment of ", stringify!(rte_ipv4_tuple))
120135
);
121136
assert_eq!(
122-
unsafe {
123-
&(*(::std::ptr::null::<rte_ipv4_tuple>())).src_addr as *const _
124-
as usize
137+
{
138+
const STRUCT_SIZE: usize = std::mem::size_of::<rte_ipv4_tuple>();
139+
let buffer = [0u8; STRUCT_SIZE];
140+
let struct_instance = unsafe {
141+
std::mem::transmute::<[u8; STRUCT_SIZE], rte_ipv4_tuple>(buffer)
142+
};
143+
let struct_ptr = &struct_instance as *const rte_ipv4_tuple;
144+
let field_ptr = std::ptr::addr_of!(struct_instance.src_addr);
145+
let struct_address = struct_ptr as usize;
146+
let field_address = field_ptr as usize;
147+
std::mem::forget(struct_instance);
148+
field_address.checked_sub(struct_address).unwrap()
125149
},
126150
0usize,
127151
concat!(
@@ -132,9 +156,18 @@ fn bindgen_test_layout_rte_ipv4_tuple() {
132156
)
133157
);
134158
assert_eq!(
135-
unsafe {
136-
&(*(::std::ptr::null::<rte_ipv4_tuple>())).dst_addr as *const _
137-
as usize
159+
{
160+
const STRUCT_SIZE: usize = std::mem::size_of::<rte_ipv4_tuple>();
161+
let buffer = [0u8; STRUCT_SIZE];
162+
let struct_instance = unsafe {
163+
std::mem::transmute::<[u8; STRUCT_SIZE], rte_ipv4_tuple>(buffer)
164+
};
165+
let struct_ptr = &struct_instance as *const rte_ipv4_tuple;
166+
let field_ptr = std::ptr::addr_of!(struct_instance.dst_addr);
167+
let struct_address = struct_ptr as usize;
168+
let field_address = field_ptr as usize;
169+
std::mem::forget(struct_instance);
170+
field_address.checked_sub(struct_address).unwrap()
138171
},
139172
4usize,
140173
concat!(
@@ -192,10 +225,24 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1() {
192225
)
193226
);
194227
assert_eq!(
195-
unsafe {
196-
&(*(::std::ptr::null::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>(
197-
)))
198-
.dport as *const _ as usize
228+
{
229+
const STRUCT_SIZE: usize = std::mem::size_of::<
230+
rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1,
231+
>();
232+
let buffer = [0u8; STRUCT_SIZE];
233+
let struct_instance = unsafe {
234+
std::mem::transmute::<
235+
[u8; STRUCT_SIZE],
236+
rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1,
237+
>(buffer)
238+
};
239+
let struct_ptr = &struct_instance
240+
as *const rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1;
241+
let field_ptr = std::ptr::addr_of!(struct_instance.dport);
242+
let struct_address = struct_ptr as usize;
243+
let field_address = field_ptr as usize;
244+
std::mem::forget(struct_instance);
245+
field_address.checked_sub(struct_address).unwrap()
199246
},
200247
0usize,
201248
concat!(
@@ -206,10 +253,24 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1() {
206253
)
207254
);
208255
assert_eq!(
209-
unsafe {
210-
&(*(::std::ptr::null::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>(
211-
)))
212-
.sport as *const _ as usize
256+
{
257+
const STRUCT_SIZE: usize = std::mem::size_of::<
258+
rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1,
259+
>();
260+
let buffer = [0u8; STRUCT_SIZE];
261+
let struct_instance = unsafe {
262+
std::mem::transmute::<
263+
[u8; STRUCT_SIZE],
264+
rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1,
265+
>(buffer)
266+
};
267+
let struct_ptr = &struct_instance
268+
as *const rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1;
269+
let field_ptr = std::ptr::addr_of!(struct_instance.sport);
270+
let struct_address = struct_ptr as usize;
271+
let field_address = field_ptr as usize;
272+
std::mem::forget(struct_instance);
273+
field_address.checked_sub(struct_address).unwrap()
213274
},
214275
2usize,
215276
concat!(
@@ -232,19 +293,6 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1() {
232293
4usize,
233294
concat!("Alignment of ", stringify!(rte_ipv6_tuple__bindgen_ty_1))
234295
);
235-
assert_eq!(
236-
unsafe {
237-
&(*(::std::ptr::null::<rte_ipv6_tuple__bindgen_ty_1>())).sctp_tag
238-
as *const _ as usize
239-
},
240-
0usize,
241-
concat!(
242-
"Offset of field: ",
243-
stringify!(rte_ipv6_tuple__bindgen_ty_1),
244-
"::",
245-
stringify!(sctp_tag)
246-
)
247-
);
248296
}
249297
impl Default for rte_ipv6_tuple__bindgen_ty_1 {
250298
fn default() -> Self {
@@ -268,9 +316,18 @@ fn bindgen_test_layout_rte_ipv6_tuple() {
268316
concat!("Alignment of ", stringify!(rte_ipv6_tuple))
269317
);
270318
assert_eq!(
271-
unsafe {
272-
&(*(::std::ptr::null::<rte_ipv6_tuple>())).src_addr as *const _
273-
as usize
319+
{
320+
const STRUCT_SIZE: usize = std::mem::size_of::<rte_ipv6_tuple>();
321+
let buffer = [0u8; STRUCT_SIZE];
322+
let struct_instance = unsafe {
323+
std::mem::transmute::<[u8; STRUCT_SIZE], rte_ipv6_tuple>(buffer)
324+
};
325+
let struct_ptr = &struct_instance as *const rte_ipv6_tuple;
326+
let field_ptr = std::ptr::addr_of!(struct_instance.src_addr);
327+
let struct_address = struct_ptr as usize;
328+
let field_address = field_ptr as usize;
329+
std::mem::forget(struct_instance);
330+
field_address.checked_sub(struct_address).unwrap()
274331
},
275332
0usize,
276333
concat!(
@@ -281,9 +338,18 @@ fn bindgen_test_layout_rte_ipv6_tuple() {
281338
)
282339
);
283340
assert_eq!(
284-
unsafe {
285-
&(*(::std::ptr::null::<rte_ipv6_tuple>())).dst_addr as *const _
286-
as usize
341+
{
342+
const STRUCT_SIZE: usize = std::mem::size_of::<rte_ipv6_tuple>();
343+
let buffer = [0u8; STRUCT_SIZE];
344+
let struct_instance = unsafe {
345+
std::mem::transmute::<[u8; STRUCT_SIZE], rte_ipv6_tuple>(buffer)
346+
};
347+
let struct_ptr = &struct_instance as *const rte_ipv6_tuple;
348+
let field_ptr = std::ptr::addr_of!(struct_instance.dst_addr);
349+
let struct_address = struct_ptr as usize;
350+
let field_address = field_ptr as usize;
351+
std::mem::forget(struct_instance);
352+
field_address.checked_sub(struct_address).unwrap()
287353
},
288354
16usize,
289355
concat!(
@@ -322,30 +388,6 @@ fn bindgen_test_layout_rte_thash_tuple() {
322388
16usize,
323389
concat!("Alignment of ", stringify!(rte_thash_tuple))
324390
);
325-
assert_eq!(
326-
unsafe {
327-
&(*(::std::ptr::null::<rte_thash_tuple>())).v4 as *const _ as usize
328-
},
329-
0usize,
330-
concat!(
331-
"Offset of field: ",
332-
stringify!(rte_thash_tuple),
333-
"::",
334-
stringify!(v4)
335-
)
336-
);
337-
assert_eq!(
338-
unsafe {
339-
&(*(::std::ptr::null::<rte_thash_tuple>())).v6 as *const _ as usize
340-
},
341-
0usize,
342-
concat!(
343-
"Offset of field: ",
344-
stringify!(rte_thash_tuple),
345-
"::",
346-
stringify!(v6)
347-
)
348-
);
349391
}
350392
impl Default for rte_thash_tuple {
351393
fn default() -> Self {

0 commit comments

Comments
 (0)