Skip to content
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

as_bytes is unsound #6

Open
andrewhickman opened this issue May 30, 2020 · 6 comments
Open

as_bytes is unsound #6

andrewhickman opened this issue May 30, 2020 · 6 comments

Comments

@andrewhickman
Copy link

It is unsafe to view an arbitrary type as bytes because it might contain uninitialized padding bytes.

zerocopy solves this with a derive macro but it is a bit limited (it doesn't work with generics, and implementing it manually is discouraged)

Unfortunately many types in this crate have padding, so there isn't really a great alternative 😕

@zakarumych
Copy link
Collaborator

Could you please provide a quote supporting that reading bytes from padding is invalid?

@andrewhickman
Copy link
Author

This seems to be the best official definition for padding at present https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/glossary.md#padding

Copying Pad ignores the source byte, and writes any value to the target byte. Or, equivalently (in terms of Abstract Machine behavior), copying Pad marks the target byte as uninitialized.

So I think if you do

let padding_byte: u8 = as_bytes(my_struct)[padding_index);
println!("{}", padding_byte);

padding_byte would be considered uninitialized.

@zakarumych
Copy link
Collaborator

I guess you're right. It can only return *const [u8] in this case.
Other alternative is to fill padding with fields and initialize them.

@zakarumych
Copy link
Collaborator

Oh, another option would be returning &[MaybeUninit<u8>]

@LPGhatguy
Copy link

I think I found a clever solution to this problem involving generating const functions that compute alignment padding between each member. Imagine creating a derive macro that generates code like this: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b309095885a8d96c60f4681727063a04

It's made a lot simpler by the expanded const fn support in Rust 1.46.0, which I think makes things like this a lot more plausible.

@LPGhatguy
Copy link

I took a stab at implementing this as part of a new crate. It might serve as good inspiration. Instead of using ZSTs aligned with #[repr(align(N))], it uses the const fn trick I demoed above: https://github.com/LPGhatguy/crevice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants