Skip to content

Commit

Permalink
exclude unsizable tail from randomization seed calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
the8472 committed Jan 10, 2025
1 parent d7fb729 commit 56889dd
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 16 deletions.
22 changes: 9 additions & 13 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,15 +1051,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
let mut max_repr_align = repr.align;
let mut inverse_memory_index: IndexVec<u32, FieldIdx> = fields.indices().collect();
let field_seed =
fields.raw.iter().fold(0u64, |acc, f| acc.wrapping_add(f.randomization_seed));
let optimize_field_order = !repr.inhibit_struct_field_reordering();
if optimize_field_order && fields.len() > 1 {
let end =
if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
let optimizing = &mut inverse_memory_index.raw[..end];
let fields_excluding_tail = &fields.raw[..end];
let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
let optimizing = &mut inverse_memory_index.raw[..end];
let fields_excluding_tail = &fields.raw[..end];
// unsizable tail fields are excluded so that we use the same seed for the sized and unsized layouts.
let field_seed = fields_excluding_tail
.iter()
.fold(0u64, |acc, f| acc.wrapping_add(f.randomization_seed));

if optimize_field_order && fields.len() > 1 {
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
// the field ordering to try and catch some code making assumptions about layouts
// we don't guarantee.
Expand Down Expand Up @@ -1369,12 +1370,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
unadjusted_abi_align
};

// a transparent struct only has a single field, so its seed should be the same as the one we pass forward
let seed = if repr.transparent() {
field_seed
} else {
field_seed.wrapping_add(repr.field_shuffle_seed)
};
let seed = field_seed.wrapping_add(repr.field_shuffle_seed);

Ok(LayoutData {
variants: Variants::Single { index: VariantIdx::new(0) },
Expand Down
7 changes: 4 additions & 3 deletions tests/ui/layout/randomize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ const _: () = {
#[cfg(randomize_layout)]
assert!(std::mem::offset_of!(Foo::<u16>, 1) != std::mem::offset_of!(Foo::<Wrapper<u16>>, 1));

// but repr(transparent) should make them the same again.
// maybe not strictly guaranteed? but UCG has been leaning in that direction at least
// Even transparent wrapper inner types get a different layout since associated type
// pecialization could result in the outer type behaving differently depending on the exact
// inner type.
#[cfg(randomize_layout)]
assert!(
std::mem::offset_of!(Foo::<u16>, 1) == std::mem::offset_of!(Foo::<TransparentWrapper>, 1)
std::mem::offset_of!(Foo::<u16>, 1) != std::mem::offset_of!(Foo::<TransparentWrapper>, 1)
);
};

0 comments on commit 56889dd

Please sign in to comment.