Skip to content

Commit 20ef0b6

Browse files
Apostolnemilio
authored andcommitted
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 #2054 - Do not check the layout for repr(C) unions - Do not call the destructor of tmp struct to avoid other UB
1 parent 7bd2329 commit 20ef0b6

File tree

230 files changed

+8432
-3822
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

+8432
-3822
lines changed

src/codegen/mod.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,8 +2116,12 @@ impl CodeGenerator for CompInfo {
21162116
.count() >
21172117
1;
21182118

2119+
2120+
// The offset of #[repr(C)] union is always 0, don't need to recheck it.
2121+
let is_not_packed_union = is_union && !packed;
2122+
21192123
let should_skip_field_offset_checks =
2120-
is_opaque || too_many_base_vtables;
2124+
is_opaque || too_many_base_vtables || is_not_packed_union;
21212125

21222126
let check_field_offset = if should_skip_field_offset_checks
21232127
{
@@ -2137,8 +2141,24 @@ impl CodeGenerator for CompInfo {
21372141

21382142
quote! {
21392143
assert_eq!(
2140-
unsafe {
2141-
&(*(::#prefix::ptr::null::<#canonical_ident>())).#field_name as *const _ as usize
2144+
{
2145+
// Create an instance of #canonical_ident struct from zero bit pattern
2146+
let struct_instance = unsafe {
2147+
std::mem::zeroed::<#canonical_ident>()
2148+
};
2149+
2150+
// Get the pointers to the struct and its field
2151+
let struct_ptr = &struct_instance as *const #canonical_ident;
2152+
let field_ptr = std::ptr::addr_of!(struct_instance.#field_name);
2153+
2154+
// Get the offset of the field
2155+
let struct_address = struct_ptr as usize;
2156+
let field_address = field_ptr as usize;
2157+
2158+
//Do not call the destructor
2159+
std::mem::forget(struct_instance);
2160+
2161+
field_address.checked_sub(struct_address).unwrap()
21422162
},
21432163
#field_offset,
21442164
concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name))

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

Lines changed: 80 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,17 @@ 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+
let struct_instance = unsafe {
48+
std::mem::zeroed::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>()
49+
};
50+
let struct_ptr = &struct_instance
51+
as *const rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1;
52+
let field_ptr = std::ptr::addr_of!(struct_instance.dport);
53+
let struct_address = struct_ptr as usize;
54+
let field_address = field_ptr as usize;
55+
std::mem::forget(struct_instance);
56+
field_address.checked_sub(struct_address).unwrap()
5057
},
5158
0usize,
5259
concat!(
@@ -57,10 +64,17 @@ fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1() {
5764
)
5865
);
5966
assert_eq!(
60-
unsafe {
61-
&(*(::std::ptr::null::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>(
62-
)))
63-
.sport as *const _ as usize
67+
{
68+
let struct_instance = unsafe {
69+
std::mem::zeroed::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>()
70+
};
71+
let struct_ptr = &struct_instance
72+
as *const rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1;
73+
let field_ptr = std::ptr::addr_of!(struct_instance.sport);
74+
let struct_address = struct_ptr as usize;
75+
let field_address = field_ptr as usize;
76+
std::mem::forget(struct_instance);
77+
field_address.checked_sub(struct_address).unwrap()
6478
},
6579
2usize,
6680
concat!(
@@ -83,19 +97,6 @@ fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1() {
8397
4usize,
8498
concat!("Alignment of ", stringify!(rte_ipv4_tuple__bindgen_ty_1))
8599
);
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-
);
99100
}
100101
impl Default for rte_ipv4_tuple__bindgen_ty_1 {
101102
fn default() -> Self {
@@ -119,9 +120,15 @@ fn bindgen_test_layout_rte_ipv4_tuple() {
119120
concat!("Alignment of ", stringify!(rte_ipv4_tuple))
120121
);
121122
assert_eq!(
122-
unsafe {
123-
&(*(::std::ptr::null::<rte_ipv4_tuple>())).src_addr as *const _
124-
as usize
123+
{
124+
let struct_instance =
125+
unsafe { std::mem::zeroed::<rte_ipv4_tuple>() };
126+
let struct_ptr = &struct_instance as *const rte_ipv4_tuple;
127+
let field_ptr = std::ptr::addr_of!(struct_instance.src_addr);
128+
let struct_address = struct_ptr as usize;
129+
let field_address = field_ptr as usize;
130+
std::mem::forget(struct_instance);
131+
field_address.checked_sub(struct_address).unwrap()
125132
},
126133
0usize,
127134
concat!(
@@ -132,9 +139,15 @@ fn bindgen_test_layout_rte_ipv4_tuple() {
132139
)
133140
);
134141
assert_eq!(
135-
unsafe {
136-
&(*(::std::ptr::null::<rte_ipv4_tuple>())).dst_addr as *const _
137-
as usize
142+
{
143+
let struct_instance =
144+
unsafe { std::mem::zeroed::<rte_ipv4_tuple>() };
145+
let struct_ptr = &struct_instance as *const rte_ipv4_tuple;
146+
let field_ptr = std::ptr::addr_of!(struct_instance.dst_addr);
147+
let struct_address = struct_ptr as usize;
148+
let field_address = field_ptr as usize;
149+
std::mem::forget(struct_instance);
150+
field_address.checked_sub(struct_address).unwrap()
138151
},
139152
4usize,
140153
concat!(
@@ -192,10 +205,17 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1() {
192205
)
193206
);
194207
assert_eq!(
195-
unsafe {
196-
&(*(::std::ptr::null::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>(
197-
)))
198-
.dport as *const _ as usize
208+
{
209+
let struct_instance = unsafe {
210+
std::mem::zeroed::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>()
211+
};
212+
let struct_ptr = &struct_instance
213+
as *const rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1;
214+
let field_ptr = std::ptr::addr_of!(struct_instance.dport);
215+
let struct_address = struct_ptr as usize;
216+
let field_address = field_ptr as usize;
217+
std::mem::forget(struct_instance);
218+
field_address.checked_sub(struct_address).unwrap()
199219
},
200220
0usize,
201221
concat!(
@@ -206,10 +226,17 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1() {
206226
)
207227
);
208228
assert_eq!(
209-
unsafe {
210-
&(*(::std::ptr::null::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>(
211-
)))
212-
.sport as *const _ as usize
229+
{
230+
let struct_instance = unsafe {
231+
std::mem::zeroed::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>()
232+
};
233+
let struct_ptr = &struct_instance
234+
as *const rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1;
235+
let field_ptr = std::ptr::addr_of!(struct_instance.sport);
236+
let struct_address = struct_ptr as usize;
237+
let field_address = field_ptr as usize;
238+
std::mem::forget(struct_instance);
239+
field_address.checked_sub(struct_address).unwrap()
213240
},
214241
2usize,
215242
concat!(
@@ -232,19 +259,6 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1() {
232259
4usize,
233260
concat!("Alignment of ", stringify!(rte_ipv6_tuple__bindgen_ty_1))
234261
);
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-
);
248262
}
249263
impl Default for rte_ipv6_tuple__bindgen_ty_1 {
250264
fn default() -> Self {
@@ -268,9 +282,15 @@ fn bindgen_test_layout_rte_ipv6_tuple() {
268282
concat!("Alignment of ", stringify!(rte_ipv6_tuple))
269283
);
270284
assert_eq!(
271-
unsafe {
272-
&(*(::std::ptr::null::<rte_ipv6_tuple>())).src_addr as *const _
273-
as usize
285+
{
286+
let struct_instance =
287+
unsafe { std::mem::zeroed::<rte_ipv6_tuple>() };
288+
let struct_ptr = &struct_instance as *const rte_ipv6_tuple;
289+
let field_ptr = std::ptr::addr_of!(struct_instance.src_addr);
290+
let struct_address = struct_ptr as usize;
291+
let field_address = field_ptr as usize;
292+
std::mem::forget(struct_instance);
293+
field_address.checked_sub(struct_address).unwrap()
274294
},
275295
0usize,
276296
concat!(
@@ -281,9 +301,15 @@ fn bindgen_test_layout_rte_ipv6_tuple() {
281301
)
282302
);
283303
assert_eq!(
284-
unsafe {
285-
&(*(::std::ptr::null::<rte_ipv6_tuple>())).dst_addr as *const _
286-
as usize
304+
{
305+
let struct_instance =
306+
unsafe { std::mem::zeroed::<rte_ipv6_tuple>() };
307+
let struct_ptr = &struct_instance as *const rte_ipv6_tuple;
308+
let field_ptr = std::ptr::addr_of!(struct_instance.dst_addr);
309+
let struct_address = struct_ptr as usize;
310+
let field_address = field_ptr as usize;
311+
std::mem::forget(struct_instance);
312+
field_address.checked_sub(struct_address).unwrap()
287313
},
288314
16usize,
289315
concat!(
@@ -322,30 +348,6 @@ fn bindgen_test_layout_rte_thash_tuple() {
322348
16usize,
323349
concat!("Alignment of ", stringify!(rte_thash_tuple))
324350
);
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-
);
349351
}
350352
impl Default for rte_thash_tuple {
351353
fn default() -> Self {

0 commit comments

Comments
 (0)