Skip to content

Improve the UB situation in layout tests. #2064

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2116,8 +2116,13 @@ impl CodeGenerator for CompInfo {
.count() >
1;

let prefix = ctx.trait_prefix();

// The offset of #[repr(C)] union is always 0, don't need to recheck it.
let is_not_packed_union = is_union && !packed;

let should_skip_field_offset_checks =
is_opaque || too_many_base_vtables;
is_opaque || too_many_base_vtables || is_not_packed_union;

let check_field_offset = if should_skip_field_offset_checks
{
Expand All @@ -2137,8 +2142,24 @@ impl CodeGenerator for CompInfo {

quote! {
assert_eq!(
unsafe {
&(*(::#prefix::ptr::null::<#canonical_ident>())).#field_name as *const _ as usize
{
// Create an instance of #canonical_ident struct from zero bit pattern
let struct_instance = unsafe {
#prefix::mem::zeroed::<#canonical_ident>()
};

// Get the pointers to the struct and its field
let struct_ptr = &struct_instance as *const #canonical_ident;
let field_ptr = #prefix::ptr::addr_of!(struct_instance.#field_name);

// Get the offset of the field
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;

//Do not call the destructor
#prefix::mem::forget(struct_instance);

field_address.checked_sub(struct_address).unwrap()
},
#field_offset,
concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name))
Expand Down
158 changes: 80 additions & 78 deletions tests/expectations/tests/16-byte-alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,17 @@ fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1() {
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>(
)))
.dport as *const _ as usize
{
let struct_instance = unsafe {
std::mem::zeroed::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>()
};
let struct_ptr = &struct_instance
as *const rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1;
let field_ptr = std::ptr::addr_of!(struct_instance.dport);
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;
std::mem::forget(struct_instance);
field_address.checked_sub(struct_address).unwrap()
},
0usize,
concat!(
Expand All @@ -57,10 +64,17 @@ fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1() {
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>(
)))
.sport as *const _ as usize
{
let struct_instance = unsafe {
std::mem::zeroed::<rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1>()
};
let struct_ptr = &struct_instance
as *const rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1;
let field_ptr = std::ptr::addr_of!(struct_instance.sport);
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;
std::mem::forget(struct_instance);
field_address.checked_sub(struct_address).unwrap()
},
2usize,
concat!(
Expand All @@ -83,19 +97,6 @@ fn bindgen_test_layout_rte_ipv4_tuple__bindgen_ty_1() {
4usize,
concat!("Alignment of ", stringify!(rte_ipv4_tuple__bindgen_ty_1))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv4_tuple__bindgen_ty_1>())).sctp_tag
as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(rte_ipv4_tuple__bindgen_ty_1),
"::",
stringify!(sctp_tag)
)
);
}
impl Default for rte_ipv4_tuple__bindgen_ty_1 {
fn default() -> Self {
Expand All @@ -119,9 +120,15 @@ fn bindgen_test_layout_rte_ipv4_tuple() {
concat!("Alignment of ", stringify!(rte_ipv4_tuple))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv4_tuple>())).src_addr as *const _
as usize
{
let struct_instance =
unsafe { std::mem::zeroed::<rte_ipv4_tuple>() };
let struct_ptr = &struct_instance as *const rte_ipv4_tuple;
let field_ptr = std::ptr::addr_of!(struct_instance.src_addr);
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;
std::mem::forget(struct_instance);
field_address.checked_sub(struct_address).unwrap()
},
0usize,
concat!(
Expand All @@ -132,9 +139,15 @@ fn bindgen_test_layout_rte_ipv4_tuple() {
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv4_tuple>())).dst_addr as *const _
as usize
{
let struct_instance =
unsafe { std::mem::zeroed::<rte_ipv4_tuple>() };
let struct_ptr = &struct_instance as *const rte_ipv4_tuple;
let field_ptr = std::ptr::addr_of!(struct_instance.dst_addr);
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;
std::mem::forget(struct_instance);
field_address.checked_sub(struct_address).unwrap()
},
4usize,
concat!(
Expand Down Expand Up @@ -192,10 +205,17 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1() {
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>(
)))
.dport as *const _ as usize
{
let struct_instance = unsafe {
std::mem::zeroed::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>()
};
let struct_ptr = &struct_instance
as *const rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1;
let field_ptr = std::ptr::addr_of!(struct_instance.dport);
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;
std::mem::forget(struct_instance);
field_address.checked_sub(struct_address).unwrap()
},
0usize,
concat!(
Expand All @@ -206,10 +226,17 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1() {
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>(
)))
.sport as *const _ as usize
{
let struct_instance = unsafe {
std::mem::zeroed::<rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1>()
};
let struct_ptr = &struct_instance
as *const rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1;
let field_ptr = std::ptr::addr_of!(struct_instance.sport);
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;
std::mem::forget(struct_instance);
field_address.checked_sub(struct_address).unwrap()
},
2usize,
concat!(
Expand All @@ -232,19 +259,6 @@ fn bindgen_test_layout_rte_ipv6_tuple__bindgen_ty_1() {
4usize,
concat!("Alignment of ", stringify!(rte_ipv6_tuple__bindgen_ty_1))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv6_tuple__bindgen_ty_1>())).sctp_tag
as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(rte_ipv6_tuple__bindgen_ty_1),
"::",
stringify!(sctp_tag)
)
);
}
impl Default for rte_ipv6_tuple__bindgen_ty_1 {
fn default() -> Self {
Expand All @@ -268,9 +282,15 @@ fn bindgen_test_layout_rte_ipv6_tuple() {
concat!("Alignment of ", stringify!(rte_ipv6_tuple))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv6_tuple>())).src_addr as *const _
as usize
{
let struct_instance =
unsafe { std::mem::zeroed::<rte_ipv6_tuple>() };
let struct_ptr = &struct_instance as *const rte_ipv6_tuple;
let field_ptr = std::ptr::addr_of!(struct_instance.src_addr);
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;
std::mem::forget(struct_instance);
field_address.checked_sub(struct_address).unwrap()
},
0usize,
concat!(
Expand All @@ -281,9 +301,15 @@ fn bindgen_test_layout_rte_ipv6_tuple() {
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_ipv6_tuple>())).dst_addr as *const _
as usize
{
let struct_instance =
unsafe { std::mem::zeroed::<rte_ipv6_tuple>() };
let struct_ptr = &struct_instance as *const rte_ipv6_tuple;
let field_ptr = std::ptr::addr_of!(struct_instance.dst_addr);
let struct_address = struct_ptr as usize;
let field_address = field_ptr as usize;
std::mem::forget(struct_instance);
field_address.checked_sub(struct_address).unwrap()
},
16usize,
concat!(
Expand Down Expand Up @@ -322,30 +348,6 @@ fn bindgen_test_layout_rte_thash_tuple() {
16usize,
concat!("Alignment of ", stringify!(rte_thash_tuple))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_thash_tuple>())).v4 as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(rte_thash_tuple),
"::",
stringify!(v4)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<rte_thash_tuple>())).v6 as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(rte_thash_tuple),
"::",
stringify!(v6)
)
);
}
impl Default for rte_thash_tuple {
fn default() -> Self {
Expand Down
Loading