Skip to content

Commit 8b3435c

Browse files
committed
fix detecting references to packed unsized fields
1 parent ab45885 commit 8b3435c

File tree

3 files changed

+37
-12
lines changed

3 files changed

+37
-12
lines changed

Diff for: compiler/rustc_const_eval/src/util/alignment.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ where
2222

2323
let ty = place.ty(local_decls, tcx).ty;
2424
match tcx.layout_of(param_env.and(ty)) {
25-
Ok(layout) if layout.align.abi <= pack => {
25+
Ok(layout) if layout.align.abi <= pack && layout.is_sized() => {
2626
// If the packed alignment is greater or equal to the field alignment, the type won't be
2727
// further disaligned.
28+
// However we need to ensure the field is sized; for unsized fields, `layout.align` is
29+
// just an approximation.
2830
debug!(
2931
"is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
3032
place,

Diff for: tests/ui/lint/unaligned_references.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use std::mem::ManuallyDrop;
2+
use std::fmt::Debug;
3+
14
#[repr(packed)]
25
pub struct Good {
36
data: u64,
@@ -27,6 +30,16 @@ impl Foo for Packed2 {
2730
}
2831
}
2932

33+
// Test for #115396
34+
fn packed_dyn() {
35+
#[repr(packed)]
36+
struct Unaligned<T: ? Sized>(ManuallyDrop<T>);
37+
38+
let ref local = Unaligned(ManuallyDrop::new([3, 5, 8u64]));
39+
let foo: &Unaligned<dyn Debug> = &*local;
40+
println!("{:?}", &*foo.0); //~ ERROR reference to packed field
41+
}
42+
3043
fn main() {
3144
unsafe {
3245
let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };

Diff for: tests/ui/lint/unaligned_references.stderr

+21-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0793]: reference to packed field is unaligned
2-
--> $DIR/unaligned_references.rs:25:13
2+
--> $DIR/unaligned_references.rs:28:13
33
|
44
LL | &self.x;
55
| ^^^^^^^
@@ -9,7 +9,17 @@ LL | &self.x;
99
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
1010

1111
error[E0793]: reference to packed field is unaligned
12-
--> $DIR/unaligned_references.rs:34:17
12+
--> $DIR/unaligned_references.rs:40:24
13+
|
14+
LL | println!("{:?}", &*foo.0);
15+
| ^^^^^
16+
|
17+
= note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
18+
= note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
19+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
20+
21+
error[E0793]: reference to packed field is unaligned
22+
--> $DIR/unaligned_references.rs:47:17
1323
|
1424
LL | let _ = &good.ptr;
1525
| ^^^^^^^^^
@@ -19,7 +29,7 @@ LL | let _ = &good.ptr;
1929
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
2030

2131
error[E0793]: reference to packed field is unaligned
22-
--> $DIR/unaligned_references.rs:35:17
32+
--> $DIR/unaligned_references.rs:48:17
2333
|
2434
LL | let _ = &good.data;
2535
| ^^^^^^^^^^
@@ -29,7 +39,7 @@ LL | let _ = &good.data;
2939
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
3040

3141
error[E0793]: reference to packed field is unaligned
32-
--> $DIR/unaligned_references.rs:37:17
42+
--> $DIR/unaligned_references.rs:50:17
3343
|
3444
LL | let _ = &good.data as *const _;
3545
| ^^^^^^^^^^
@@ -39,7 +49,7 @@ LL | let _ = &good.data as *const _;
3949
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
4050

4151
error[E0793]: reference to packed field is unaligned
42-
--> $DIR/unaligned_references.rs:38:27
52+
--> $DIR/unaligned_references.rs:51:27
4353
|
4454
LL | let _: *const _ = &good.data;
4555
| ^^^^^^^^^^
@@ -49,7 +59,7 @@ LL | let _: *const _ = &good.data;
4959
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
5060

5161
error[E0793]: reference to packed field is unaligned
52-
--> $DIR/unaligned_references.rs:40:17
62+
--> $DIR/unaligned_references.rs:53:17
5363
|
5464
LL | let _ = good.data.clone();
5565
| ^^^^^^^^^
@@ -59,7 +69,7 @@ LL | let _ = good.data.clone();
5969
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
6070

6171
error[E0793]: reference to packed field is unaligned
62-
--> $DIR/unaligned_references.rs:42:17
72+
--> $DIR/unaligned_references.rs:55:17
6373
|
6474
LL | let _ = &good.data2[0];
6575
| ^^^^^^^^^^^^^^
@@ -69,7 +79,7 @@ LL | let _ = &good.data2[0];
6979
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
7080

7181
error[E0793]: reference to packed field is unaligned
72-
--> $DIR/unaligned_references.rs:51:17
82+
--> $DIR/unaligned_references.rs:64:17
7383
|
7484
LL | let _ = &packed2.x;
7585
| ^^^^^^^^^^
@@ -79,7 +89,7 @@ LL | let _ = &packed2.x;
7989
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
8090

8191
error[E0793]: reference to packed field is unaligned
82-
--> $DIR/unaligned_references.rs:90:20
92+
--> $DIR/unaligned_references.rs:103:20
8393
|
8494
LL | let _ref = &m1.1.a;
8595
| ^^^^^^^
@@ -89,7 +99,7 @@ LL | let _ref = &m1.1.a;
8999
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
90100

91101
error[E0793]: reference to packed field is unaligned
92-
--> $DIR/unaligned_references.rs:93:20
102+
--> $DIR/unaligned_references.rs:106:20
93103
|
94104
LL | let _ref = &m2.1.a;
95105
| ^^^^^^^
@@ -98,6 +108,6 @@ LL | let _ref = &m2.1.a;
98108
= note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
99109
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
100110

101-
error: aborting due to 10 previous errors
111+
error: aborting due to 11 previous errors
102112

103113
For more information about this error, try `rustc --explain E0793`.

0 commit comments

Comments
 (0)