Force padding to be zero, not uninit

I have two values of a particular union. I know they will be the same variant, but not which variant they will be. I want to compare them for byte equality.

I know that normally padding can contain uninit or unspecified bytes. is there some repr or magic wrapper type i can use to force all padding to be zero? I control the construction of those values, is there a way i can zero out all the padding?

You're trying to program C in Rust!!

There is no repr to zero the padding but you can manually add padding fields.

Safe comparison is possible if you define all variants as repr(C) structs of the same size and alignment, containing only plain data (integers, etc), and manually add any fields needed for padding. You can then use the bytemuck crate to derive the Pod and Zeroable traits for the structs, safely cast them to byte arrays and compare the bytes.

The same thing should be possible with the zerocopy crate although I haven't tried it.

3 Likes

I am trying to write an interpreter that does interesting things with static typing.

I know the idiomatic thing to do is to use an enum. but if i do that, i'm just using dynamic typing. I need to circumvent rust's safety measures in order to meaningfully implement my own.

You'd need to either manually zero all the padding yourself, probably using a [MaybeUninit<u8>]. Or start with a zeroed landing pad and manually copy the non-padding. If you circumvent it some other way, you'll be committing UB, or working outside of the Rust abstract machine at best, AFAIK.

I don't know if there's technically any guarantee that zeroed padding bytes "stay" zeroed in the absence of writes. There is no guarantee when copied or moved to a new place. If you need to work with pure bytes, you might be better off just working with pure bytes and never doing a typed copy/move of the union into a place where you want to read the padding.

(Assuming the better, idiomatic option of replacing the padding is unavailable to you.)

3 Likes

There is not and never will be a "padding is zero instead of uninit" repr because it's bad for things like macros. Today code can initialize all the fields and know that's enough to have the struct be initialized (or one field on a union -- maybe zero fields on a union, depending on UCG conversations) enough for MaybeUninit::assume_init, and I don't think that will ever change.

There may be "require this doesn't have padding" attributes or checks or something, but it certainly won't be a repr.

If you want to do this, maybe just only support types implementing FromBytes in zerocopy - Rust ?

3 Likes

Combine zerobytes::IntoBytes with #[repr(u8)] enum Pad { ZERO = 0; } to fill out a struct.

2 Likes

If you start with MaybeUninit::zeroed(), then initializing just the fields would be compatible with "padding is zero" or "padding is just uninitialized bytes". I don't think that's sufficient reason to discard the possibility of such repr, though I don't know whether it's worth the trouble in practice. Point in favour: bindgen translates all C structs into Rust structs with manually defined padding. A special repr would simplify the code and avoid questions "why does bindgen add extra fields to structs".

What kind of macros could fall afoul of this change? I can only think of derive macros, and those are either safe or usually need to special-case all reprs anyway.

3 Likes

No, they usually only need to special-case things like repr(packed) which -- as evidenced by a multi-year-long trail of issues -- was a bad idea in the first place.

derive(Debug) has no need to special-case repr(u32) on an enum, to special case repr(transparent) on a struct, to special-case repr(C), etc. It's only repr(packed) that it has to special-case, which means it's a repr(packed) problem, not a repr problem.

Right, but I don't see a reason why safe macros would have to special-case #[repr(defined_padding)]. The compiler would need to create variables of that type in zeroed rather than uninitialized state and preserve the padding on moves, but what else could be the issues for safe code?

2 Likes