-
Notifications
You must be signed in to change notification settings - Fork 745
Fix an UB in layout tests #2055
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
Fix an UB in layout tests #2055
Conversation
- 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
r? @emilio |
r? @fitzgen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still not guaranteed to be ub-free, think of a rust enum field like:
enum Foo { Bar = 1, Baz, }
Using a zeroed buffer for that seems like itd still be UB.
But anyhow this is better than what we're doing so it seems ok to me with the suggestion below.
src/codegen/mod.rs
Outdated
{ | ||
// Create an instance of #canonical_ident struct from zero bit pattern | ||
const STRUCT_SIZE: usize = std::mem::size_of::<#canonical_ident>(); | ||
let buffer = [0u8; STRUCT_SIZE]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not guaranteed to be aligned right? I think using std::mem::zeroed should be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, fixed
Though, I don't catch why there is a wrong alignment. AFAIU, In case of mem::zeroed the padding bytes are not zeroed but the total behavior is the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, let's say you have a struct with an u32
member. The compiler would make sure that that is aligned appropriately, but if you use a flat array of u8
s then it's not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emilio
Ok, thank you. Replaced it with mem::zeroed
It seems there are still some tests to update, but I'll try to get to this myself if you can't. |
Yeah, I've missed errors on CI, locally it was OK. I'm going to fix it but a bit later. |
let struct_instance = unsafe { | ||
std::mem::zeroed::<#canonical_ident>() | ||
}; | ||
|
||
// Get the pointers to the struct and its field | ||
let struct_ptr = &struct_instance as *const #canonical_ident; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This potential UB can be avoided:
let struct_instance = unsafe { | |
std::mem::zeroed::<#canonical_ident>() | |
}; | |
// Get the pointers to the struct and its field | |
let struct_ptr = &struct_instance as *const #canonical_ident; | |
let struct_instance = core::mem::MaybeUninit::<#canonical_ident>::uninit(); | |
// Get the pointers to the struct and its field | |
let struct_ptr = struct_instance.as_ptr(); |
☔ The latest upstream changes (presumably 310f7f8) made this pull request unmergeable. Please resolve the merge conflicts. |
This might be obsoleted since #2203 was completed. |
It appears that this (like #2064) has a little more in it than #2203 did, but since #1651 is now closed, I am inferring that this PR is no longer needed, so I am closing it. If I missed something, let me know. |
zero bit pattern + transmute + std::ptr::addr_of!
to avoid UB. It affects only checks of fields offsets
manually because Some expected are not overwritten with BINDGEN_OVERWRITE_EXPECTED=1 #2054
Close #1651
Note: This way is not ideal (see the latest comments in related issue). Zero bit pattern can be replaces with manual initialization of the fields, but I have no time to investigate how to do it when
However, I think this way is good enough, because there no UB anymore. The only one unsafe block with transmute will not cause an UB, because all C types allows zero bit pattern. Anyway, it's better than current implementation with UB and warnings.
Any feedback or commits are appreciated. Thanks.