Skip to content

Commit 96aff94

Browse files
authored
Rollup merge of #118540 - RalfJung:unsized-packed-offset, r=TaKO8Ki
codegen, miri: fix computing the offset of an unsized field in a packed struct `#[repr(packed)]` strikes again. Fixes rust-lang/rust#118537 Fixes #3200 `@bjorn3` I assume cranelift needs the same fix.
2 parents 05de086 + 06dc9f2 commit 96aff94

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#![feature(layout_for_ptr)]
2+
use std::mem;
3+
4+
#[repr(packed, C)]
5+
struct PackedSized {
6+
f: u8,
7+
d: [u32; 4],
8+
}
9+
10+
#[repr(packed, C)]
11+
struct PackedUnsized {
12+
f: u8,
13+
d: [u32],
14+
}
15+
16+
impl PackedSized {
17+
fn unsize(&self) -> &PackedUnsized {
18+
// We can't unsize via a generic type since then we get the error
19+
// that packed structs with unsized tail don't work if the tail
20+
// might need dropping.
21+
let len = 4usize;
22+
unsafe { mem::transmute((self, len)) }
23+
}
24+
}
25+
26+
fn main() { unsafe {
27+
let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
28+
let p = p.unsize() as *const PackedUnsized;
29+
// Make sure the size computation does *not* think there is
30+
// any padding in front of the `d` field.
31+
assert_eq!(mem::size_of_val_raw(p), 1 + 4*4);
32+
// And likewise for the offset computation.
33+
let d = std::ptr::addr_of!((*p).d);
34+
assert_eq!(d.cast::<u32>().read_unaligned(), 1);
35+
} }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#![feature(layout_for_ptr)]
2+
use std::mem;
3+
4+
#[repr(packed(4))]
5+
struct Slice([u32]);
6+
7+
#[repr(packed(2), C)]
8+
struct PackedSized {
9+
f: u8,
10+
d: [u32; 4],
11+
}
12+
13+
#[repr(packed(2), C)]
14+
struct PackedUnsized {
15+
f: u8,
16+
d: Slice,
17+
}
18+
19+
impl PackedSized {
20+
fn unsize(&self) -> &PackedUnsized {
21+
// We can't unsize via a generic type since then we get the error
22+
// that packed structs with unsized tail don't work if the tail
23+
// might need dropping.
24+
let len = 4usize;
25+
unsafe { mem::transmute((self, len)) }
26+
}
27+
}
28+
29+
fn main() { unsafe {
30+
let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
31+
let p = p.unsize() as *const PackedUnsized;
32+
// Make sure the size computation correctly adds exact 1 byte of padding
33+
// in front of the `d` field.
34+
assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4);
35+
// And likewise for the offset computation.
36+
let d = std::ptr::addr_of!((*p).d);
37+
assert_eq!(d.cast::<u32>().read_unaligned(), 1);
38+
} }

0 commit comments

Comments
 (0)