Normalize struct tail properly in disalignment check

This commit is contained in:
Michael Goulet 2024-08-05 16:30:00 -04:00
parent d9dd5509dc
commit f81549c9ca
4 changed files with 172 additions and 15 deletions

View File

@ -22,7 +22,7 @@ pub fn is_disaligned<'tcx, L>(
}; };
let ty = place.ty(local_decls, tcx).ty; let ty = place.ty(local_decls, tcx).ty;
let unsized_tail = || tcx.struct_tail_with_normalize(ty, |ty| ty, || {}); let unsized_tail = || tcx.struct_tail_erasing_lifetimes(ty, param_env);
match tcx.layout_of(param_env.and(ty)) { match tcx.layout_of(param_env.and(ty)) {
Ok(layout) Ok(layout)
if layout.align.abi <= pack if layout.align.abi <= pack

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:28:13 --> $DIR/unaligned_references.rs:32:13
| |
LL | &self.x; LL | &self.x;
| ^^^^^^^ | ^^^^^^^
@ -9,7 +9,7 @@ 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:40:24 --> $DIR/unaligned_references.rs:44:24
| |
LL | println!("{:?}", &*foo.0); LL | println!("{:?}", &*foo.0);
| ^^^^^ | ^^^^^
@ -19,7 +19,7 @@ LL | println!("{:?}", &*foo.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:42:24 --> $DIR/unaligned_references.rs:46:24
| |
LL | println!("{:?}", &*foo.0); LL | println!("{:?}", &*foo.0);
| ^^^^^ | ^^^^^
@ -29,7 +29,7 @@ LL | println!("{:?}", &*foo.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:47:24 --> $DIR/unaligned_references.rs:51:24
| |
LL | println!("{:?}", &*foo.0); LL | println!("{:?}", &*foo.0);
| ^^^^^ | ^^^^^
@ -39,7 +39,7 @@ LL | println!("{:?}", &*foo.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:57:17 --> $DIR/unaligned_references.rs:81:17
| |
LL | let _ = &good.ptr; LL | let _ = &good.ptr;
| ^^^^^^^^^ | ^^^^^^^^^
@ -49,7 +49,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:58:17 --> $DIR/unaligned_references.rs:82:17
| |
LL | let _ = &good.data; LL | let _ = &good.data;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -59,7 +59,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:60:17 --> $DIR/unaligned_references.rs:84:17
| |
LL | let _ = &good.data as *const _; LL | let _ = &good.data as *const _;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -69,7 +69,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:61:27 --> $DIR/unaligned_references.rs:85:27
| |
LL | let _: *const _ = &good.data; LL | let _: *const _ = &good.data;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -79,7 +79,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:63:17 --> $DIR/unaligned_references.rs:87:17
| |
LL | let _ = good.data.clone(); LL | let _ = good.data.clone();
| ^^^^^^^^^ | ^^^^^^^^^
@ -89,7 +89,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:65:17 --> $DIR/unaligned_references.rs:89:17
| |
LL | let _ = &good.data2[0]; LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -99,7 +99,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:74:17 --> $DIR/unaligned_references.rs:98:17
| |
LL | let _ = &packed2.x; LL | let _ = &packed2.x;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -109,7 +109,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:113:20 --> $DIR/unaligned_references.rs:137:20
| |
LL | let _ref = &m1.1.a; LL | let _ref = &m1.1.a;
| ^^^^^^^ | ^^^^^^^
@ -119,7 +119,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:116:20 --> $DIR/unaligned_references.rs:140:20
| |
LL | let _ref = &m2.1.a; LL | let _ref = &m2.1.a;
| ^^^^^^^ | ^^^^^^^

View File

@ -0,0 +1,133 @@
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:32:13
|
LL | &self.x;
| ^^^^^^^
|
= 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:44: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:46: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:51: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:81:17
|
LL | let _ = &good.ptr;
| ^^^^^^^^^
|
= 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:82:17
|
LL | let _ = &good.data;
| ^^^^^^^^^^
|
= 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:84:17
|
LL | let _ = &good.data as *const _;
| ^^^^^^^^^^
|
= 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:85:27
|
LL | let _: *const _ = &good.data;
| ^^^^^^^^^^
|
= 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:87:17
|
LL | let _ = good.data.clone();
| ^^^^^^^^^
|
= 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:89:17
|
LL | let _ = &good.data2[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:98:17
|
LL | let _ = &packed2.x;
| ^^^^^^^^^^
|
= 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:137:20
|
LL | let _ref = &m1.1.a;
| ^^^^^^^
|
= 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:140:20
|
LL | let _ref = &m2.1.a;
| ^^^^^^^
|
= 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: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0793`.

View File

@ -1,5 +1,9 @@
use std::mem::ManuallyDrop; //@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
use std::fmt::Debug; use std::fmt::Debug;
use std::mem::ManuallyDrop;
#[repr(packed)] #[repr(packed)]
pub struct Good { pub struct Good {
@ -50,6 +54,26 @@ fn packed_dyn() {
println!("{:?}", &*foo.0); // no error! println!("{:?}", &*foo.0); // no error!
} }
// Test for #115396
fn packed_slice_behind_alias() {
trait Mirror {
type Assoc: ?Sized;
}
impl<T: ?Sized> Mirror for T {
type Assoc = T;
}
struct W<T: ?Sized>(<T as Mirror>::Assoc);
#[repr(packed)]
struct Unaligned<T: ?Sized>(ManuallyDrop<W<T>>);
// Even if the actual alignment is 1, we cannot know that when looking at `dyn Debug.`
let ref local: Unaligned<[_; 3]> = Unaligned(ManuallyDrop::new(W([3, 5, 8u8])));
let foo: &Unaligned<[u8]> = local;
let x = &foo.0; // Fine, since the tail of `foo` is `[_]`
}
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] };