Randomize the ordering of struct fields when compiling in debug mode
Now that it looks like https://github.com/rust-lang/rust/issues/28951 will be addressed via https://github.com/rust-lang/rust/issues/37429 , we may have a further obligation to ensure to do what we can to ensure that this doesn't bite people. One way that we could help out would be to randomize the order of struct fields by default when compiling in debug mode. This would only apply to structs that are not tagged with a #repr, and would effectively act as the #[repr(random)] proposed by @petrochenkov at https://github.com/rust-lang/rust/pull/37429#issuecomment-260080723 (actually adding explicit #[repr(random)] would probably require an RFC, and so is not a prereq for this issue).
I know there's code out there in the wild that will be broken by this, especially if it affects the stdlib. Perhaps a Crater run and an early warning for the affected crates is in order.
Austin Bonander at 2016-12-22 22:38:28
@abonander We ran Crater for #37249 and saw no instances of legitimate breakage, though of course what I'm proposing here is more radical and also Crater only catches a subset of errors. This is definitely a conversation that we need to have with the broader community so that people are aware of what Rust actually guarantees (i.e. "less than you think if you're not using repr(C)"), which is part of the reason why I've proposed this. It's true that maybe we could just have this as a dev option for the moment solely for the purpose of teasing out how much would break on Crater.
bstrie at 2016-12-23 00:27:36
Unanswered question: if a user does reveal a bug thanks to Rust reordering struct fields randomly (which, in correct code, should never trigger bugs), how do we help the user reproduce that bug deterministically?
bstrie at 2016-12-23 00:29:16
Unanswered question: if a user does reveal a bug thanks to Rust reordering struct fields randomly (which, in correct code, should never trigger bugs), how do we help the user reproduce that bug deterministically?
Probably some compiler flag that prints the seed for randomization for each struct, and/or prints the final ordering of the fields for a given struct given the seed.
Austin Bonander at 2016-12-23 00:33:53
This will probably end up being a flag that does it both in debug and release. Se this thread.
I wish the three related discussions were centralized.
Austin Hicks at 2016-12-23 16:49:46
Just thought of something else. The seed for the reordering can be a hash of the path to the struct, thus producing a stable ordering until such time as the struct is moved or renamed. This should be really easy to implement.
Austin Hicks at 2016-12-26 21:39:24
@camlorn Read your article and came to think of something. For this one:
struct RcBox<T: ?Sized> { strong: Cell<usize>, refcount: Cell<usize>, value: T, }Could this optimisation change the order of
strong,refcountandvalueso that it is different forRcBox<MyStruct>andRcBox<MyTrait>, so that a currently safe operationrc_mystruct as Rc<MyTrait>becomes a very bad thing?diwic at 2017-04-21 18:04:21
Nope. I didn't go into it because the article was already pretty lengthy, but @eddyb provided magic code that I am not going to even pretend to understand which can tell us whether or not we can move the last field.
Austin Hicks at 2017-04-23 20:28:14
It's not just the last field but you can't reorder the prefix differenly between those types, the cast is safe.
Eduard-Mihai Burtescu at 2017-04-24 03:21:04
We could at least randomize the order of the fields that share an alignment, using the "def path hash" of the
ty::Adt. That way we could release this into the wild and see what breaks.Similarly, I just realized we could do something similar for function calls, though it's harder to know what to key on, there.
Eduard-Mihai Burtescu at 2020-09-23 03:41:38