diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 02811b2491c..727c0ba63cb 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -347,10 +347,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); - // `ReprOptions.layout_seed` is a deterministic seed that we can use to - // randomize field ordering with - let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); - let optimize = !repr.inhibit_struct_field_reordering_opt(); if optimize { let end = @@ -364,6 +360,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // the field ordering to try and catch some code making assumptions about layouts // we don't guarantee if repr.can_randomize_type_layout() { + // `ReprOptions.layout_seed` is a deterministic seed that we can use to + // randomize field ordering with + let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); + // Shuffle the ordering of the fields optimizing.shuffle(&mut rng); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d0d2a46fc4c..10232dc9cb6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1608,9 +1608,9 @@ bitflags! { // the seed stored in `ReprOptions.layout_seed` const RANDOMIZE_LAYOUT = 1 << 5; // Any of these flags being set prevent field reordering optimisation. - const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | - ReprFlags::IS_SIMD.bits | - ReprFlags::IS_LINEAR.bits; + const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits + | ReprFlags::IS_SIMD.bits + | ReprFlags::IS_LINEAR.bits; } } @@ -1640,7 +1640,14 @@ impl ReprOptions { // Generate a deterministically-derived seed from the item's path hash // to allow for cross-crate compilation to actually work - let field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); + let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); + + // If the user defined a custom seed for layout randomization, xor the item's + // path hash with the user defined seed, this will allowing determinism while + // still allowing users to further randomize layout generation for e.g. fuzzing + if let Some(user_seed) = tcx.sess.opts.debugging_opts.layout_seed { + field_shuffle_seed ^= user_seed; + } for attr in tcx.get_attrs(did).iter() { for r in attr::find_repr_attrs(&tcx.sess, attr) { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index dc5f4ee0ece..9090524c933 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1321,6 +1321,8 @@ options! { "print some statistics about the query system (default: no)"), randomize_layout: bool = (false, parse_bool, [TRACKED], "randomize the layout of types (default: no)"), + layout_seed: Option = (None, parse_opt_number, [TRACKED], + "seed layout randomization"), relax_elf_relocations: Option = (None, parse_opt_bool, [TRACKED], "whether ELF relocations can be relaxed"), relro_level: Option = (None, parse_relro_level, [TRACKED],