about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-10-02 19:17:30 +0200
committerRalf Jung <post@ralfj.de>2018-10-09 13:08:00 +0200
commit0a2fae6cb72a19e690b74bd57a67b9b36deef81c (patch)
treedd6c095341092816aa5e0608b997eb13da91f71f
parentf65d3b5491a8f675c3c5bb892c3e97ce4d4f9798 (diff)
downloadrust-0a2fae6cb72a19e690b74bd57a67b9b36deef81c.tar.gz
rust-0a2fae6cb72a19e690b74bd57a67b9b36deef81c.zip
fix validating arrays of ZSTs
Fixes #54751
-rw-r--r--src/librustc_mir/interpret/place.rs12
-rw-r--r--src/librustc_mir/interpret/validity.rs13
-rw-r--r--src/test/ui/consts/const-eval/ub-uninhabit.rs15
-rw-r--r--src/test/ui/consts/const-eval/ub-uninhabit.stderr22
4 files changed, 43 insertions, 19 deletions
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 8878e5ca83f..f8e1e9e55d5 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -131,6 +131,18 @@ impl MemPlace {
 }
 
 impl<'tcx> MPlaceTy<'tcx> {
+    /// Produces a MemPlace that works for ZST but nothing else
+    #[inline]
+    pub fn dangling(layout: TyLayout<'tcx>, cx: impl HasDataLayout) -> Self {
+        MPlaceTy {
+            mplace: MemPlace::from_scalar_ptr(
+                Scalar::from_uint(layout.align.abi(), cx.pointer_size()),
+                layout.align
+            ),
+            layout
+        }
+    }
+
     #[inline]
     fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self {
         MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align), layout }
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index a5e4231e7ab..23f09cf108e 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -365,8 +365,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                 // The fields don't need to correspond to any bit pattern of the union's fields.
                 // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
             },
-            layout::FieldPlacement::Array { stride, .. } if !dest.layout.is_zst() => {
-                let dest = dest.to_mem_place(); // non-ZST array/slice/str cannot be immediate
+            layout::FieldPlacement::Array { stride, .. } => {
+                let dest = if dest.layout.is_zst() {
+                    // it's a ZST, the memory content cannot matter
+                    MPlaceTy::dangling(dest.layout, self)
+                } else {
+                    // non-ZST array/slice/str cannot be immediate
+                    dest.to_mem_place()
+                };
                 match dest.layout.ty.sty {
                     // Special handling for strings to verify UTF-8
                     ty::Str => {
@@ -429,9 +435,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     }
                 }
             },
-            layout::FieldPlacement::Array { .. } => {
-                // An empty array.  Nothing to do.
-            }
             layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                 for i in 0..offsets.len() {
                     let field = self.operand_field(dest, i as u64)?;
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs
index 0f58c84c10b..99305beee52 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.rs
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs
@@ -8,19 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-union Foo {
-    a: usize,
-    b: Bar,
-    c: &'static Bar,
-}
+#![feature(const_transmute)]
+
+use std::mem;
 
 #[derive(Copy, Clone)]
 enum Bar {}
 
-const BAD_BAD_BAD: Bar = unsafe { Foo { a: 1 }.b };
+const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
 //~^ ERROR this constant likely exhibits undefined behavior
 
-const BAD_BAD_REF: &Bar = unsafe { Foo { a: 1 }.c };
+const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) };
 //~^ ERROR this constant likely exhibits undefined behavior
 
 fn main() {
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr
index 95cf8865c8d..136d5f29199 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr
@@ -1,19 +1,27 @@
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/ub-uninhabit.rs:20:1
+  --> $DIR/ub-uninhabit.rs:18:1
    |
-LL | const BAD_BAD_BAD: Bar = unsafe { Foo { a: 1 }.b };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+LL | const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/ub-uninhabit.rs:23:1
+  --> $DIR/ub-uninhabit.rs:21:1
    |
-LL | const BAD_BAD_REF: &Bar = unsafe { Foo { a: 1 }.c };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
+LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
-error: aborting due to 2 previous errors
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-uninhabit.rs:24:1
+   |
+LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at [0]
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.