-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Closed
Labels
-Zrandomize-layoutUnstable option: Randomize the layout of types.Unstable option: Randomize the layout of types.A-layoutArea: Memory layout of typesArea: Memory layout of typesC-feature-acceptedCategory: A feature request that has been accepted pending implementation.Category: A feature request that has been accepted pending implementation.C-feature-requestCategory: A feature request, i.e: not implemented / a PR.Category: A feature request, i.e: not implemented / a PR.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
In order to better detect code that rely on unspecified behavior related to memory layout, it could be useful to have a -Zrandomize-layout
flag that add some padding bytes at the start of all #[repr(rust)]
structs and unions. It should also add different amounts of padding to different fields.
This should help detecting invalid transmutes, or invalid unions.
Zulip thread: https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/Transmute.20safety.20question
the8472, Aaron1011, jyn514 and Kobzol
Metadata
Metadata
Assignees
Labels
-Zrandomize-layoutUnstable option: Randomize the layout of types.Unstable option: Randomize the layout of types.A-layoutArea: Memory layout of typesArea: Memory layout of typesC-feature-acceptedCategory: A feature request that has been accepted pending implementation.Category: A feature request that has been accepted pending implementation.C-feature-requestCategory: A feature request, i.e: not implemented / a PR.Category: A feature request, i.e: not implemented / a PR.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
[-]Add `-Zrandomize-layout` flag to better detect code that rely on unspecified behavior related memory layout[/-][+]Add `-Zrandomize-layout` flag to better detect code that rely on unspecified behavior related to memory layout[/+]RalfJung commentedon Sep 29, 2020
I think this could be very useful indeed... maybe @eddyb has some ideas for how to best implement this.
eddyb commentedon Sep 29, 2020
You can make this deterministic by using the
def_path_hash
for a given definition (it's an equivalent ofDefId
that's stable across incremental recompilation) - you might not even need to seed a PRNG with it if all you need is one value!We can also do a limited version of this by default, but since it won't change the size, it would only fail at runtime #38550 (comment)
eddyb commentedon Sep 30, 2020
On Zulip @RalfJung pointed out that I didn't explain why you would want to make this deterministic (or why that's the main difficulty), so here's 3 reasons why this has to be deterministic:
There's two ways to get deterministic per-type-definition "seeds":
def_path_hash
(which I mentioned in the previous comment), which is effectively theTypeId
hash corresponding to aDefId
, and rely on its hash properties be pseudo-random (it should change with compiler releases and crate versions specified in theCargo.toml
, so at least we should get some variety - though maybe not as much on nightly sadly)You might probably also want a CLI flag to e.g. XOR in a fixed seed as well, even with the latter method, but it would have to be embedded in the type definition (so that it's correct cross-crate without requiring the same flag to passed in order to avoid miscompilation), so it's as much effort as both.
petrochenkov commentedon Sep 30, 2020
Randomizing the layout for testing purposes was being suggested starting from the original struct layout RFC (https://github.com/rust-lang/rfcs/blob/master/text/0079-undefined-struct-layout.md#alternatives), it's unfortunate that it's still not implemented.
I've found one similar existing issue for this - #38550.
elichai commentedon Oct 5, 2020
I think the "easiest" thing that should also give the highest reward is adding uninit bytes at the front of every repr(Rust) struct (obviously under some
-Zpad-layout
)because this will:
we can then extend to:
A. Randomize the fields order.
B. Mess with alignment (can probably only be increased and not decreased).
C. Add uninit bytes at the middle/end? (not sure if this achieves anything)
marmeladema commentedon Oct 5, 2020
I would be glad to help implementing a first iteration of those ideas namely padding bytes at the start of repr(rust) struct. But I am not knowledgeable enough about those parts of the compiler.
Would someone be available to mentor me?
eddyb commentedon Oct 8, 2020
@marmeladema It's pretty much all in
rustc_middle::ty::layout
. Wherever field offsets are computed (univariant_uninterned
), you can, for example, add the final alignment to all of the field offsets - this will increase the size of the whole type but keep all fields correctly aligned (and it's slightly simpler than changing field order, which has to be done similarly to how we sort fields by alignment).You should be able to PM me if you have more questions.
If you rely on the same flag to be passed across all the crates, or if you record what the choices were when a certain crate was contained (you could look at how
-Z symbol-mangling-version
is handled), you should be able to avoid problems with cross-crate consistency, which as per #77316 (comment) was my main worry.Rollup merge of rust-lang#87868 - Kixiron:packing-on-the-pounds, r=eddyb
Rollup merge of rust-lang#87868 - Kixiron:packing-on-the-pounds, r=eddyb
-Z randomize-layout
rust-marker/marker#287 remaining items