fix detecting references to packed unsized fields

This commit is contained in:
Ralf Jung 2023-09-05 22:29:51 +02:00
parent ab45885dec
commit 8b3435c10f
3 changed files with 37 additions and 12 deletions

View File

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

View File

@ -1,3 +1,6 @@
use std::mem::ManuallyDrop;
use std::fmt::Debug;
#[repr(packed)] #[repr(packed)]
pub struct Good { pub struct Good {
data: u64, data: u64,
@ -27,6 +30,16 @@ impl Foo for Packed2 {
} }
} }
// Test for #115396
fn packed_dyn() {
#[repr(packed)]
struct Unaligned<T: ? Sized>(ManuallyDrop<T>);
let ref local = Unaligned(ManuallyDrop::new([3, 5, 8u64]));
let foo: &Unaligned<dyn Debug> = &*local;
println!("{:?}", &*foo.0); //~ ERROR reference to packed field
}
fn main() { fn main() {
unsafe { unsafe {
let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] }; let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };

View File

@ -1,5 +1,5 @@
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:25:13 --> $DIR/unaligned_references.rs:28:13
| |
LL | &self.x; LL | &self.x;
| ^^^^^^^ | ^^^^^^^
@ -9,7 +9,17 @@ LL | &self.x;
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:34:17 --> $DIR/unaligned_references.rs:40:24
|
LL | println!("{:?}", &*foo.0);
| ^^^^^
|
= note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
= note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:47:17
| |
LL | let _ = &good.ptr; LL | let _ = &good.ptr;
| ^^^^^^^^^ | ^^^^^^^^^
@ -19,7 +29,7 @@ LL | let _ = &good.ptr;
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:35:17 --> $DIR/unaligned_references.rs:48:17
| |
LL | let _ = &good.data; LL | let _ = &good.data;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -29,7 +39,7 @@ LL | let _ = &good.data;
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:37:17 --> $DIR/unaligned_references.rs:50:17
| |
LL | let _ = &good.data as *const _; LL | let _ = &good.data as *const _;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -39,7 +49,7 @@ LL | let _ = &good.data as *const _;
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:38:27 --> $DIR/unaligned_references.rs:51:27
| |
LL | let _: *const _ = &good.data; LL | let _: *const _ = &good.data;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -49,7 +59,7 @@ LL | let _: *const _ = &good.data;
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:40:17 --> $DIR/unaligned_references.rs:53:17
| |
LL | let _ = good.data.clone(); LL | let _ = good.data.clone();
| ^^^^^^^^^ | ^^^^^^^^^
@ -59,7 +69,7 @@ LL | let _ = good.data.clone();
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:42:17 --> $DIR/unaligned_references.rs:55:17
| |
LL | let _ = &good.data2[0]; LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -69,7 +79,7 @@ LL | let _ = &good.data2[0];
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:51:17 --> $DIR/unaligned_references.rs:64:17
| |
LL | let _ = &packed2.x; LL | let _ = &packed2.x;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -79,7 +89,7 @@ LL | let _ = &packed2.x;
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:90:20 --> $DIR/unaligned_references.rs:103:20
| |
LL | let _ref = &m1.1.a; LL | let _ref = &m1.1.a;
| ^^^^^^^ | ^^^^^^^
@ -89,7 +99,7 @@ LL | let _ref = &m1.1.a;
= 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) = 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)
error[E0793]: reference to packed field is unaligned error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:93:20 --> $DIR/unaligned_references.rs:106:20
| |
LL | let _ref = &m2.1.a; LL | let _ref = &m2.1.a;
| ^^^^^^^ | ^^^^^^^
@ -98,6 +108,6 @@ LL | let _ref = &m2.1.a;
= note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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) = 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)
error: aborting due to 10 previous errors error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0793`. For more information about this error, try `rustc --explain E0793`.