about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRémy Rakic <remy.rakic+github@gmail.com>2021-06-08 23:47:04 +0200
committerRémy Rakic <remy.rakic+github@gmail.com>2021-06-09 23:04:52 +0200
commitd44990367d57e40a6ec157174a463818665ac6de (patch)
tree0f1e8e54d9f7ba0c9df9b242f6c2f1b8449d3609
parent47d38752c65359e1f4558d7a06935982fb8b486f (diff)
downloadrust-d44990367d57e40a6ec157174a463818665ac6de.tar.gz
rust-d44990367d57e40a6ec157174a463818665ac6de.zip
detect incorrect vtable alignment during const eval instead of ICE-ing
also add tests for these 2 kinds of errors for size and alignment,
as the existing size check wasn't apparently tested
-rw-r--r--compiler/rustc_mir/src/interpret/traits.rs4
-rw-r--r--src/test/ui/consts/const-eval/ub-incorrect-vtable.rs21
-rw-r--r--src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr27
3 files changed, 51 insertions, 1 deletions
diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_mir/src/interpret/traits.rs
index 11f8d388820..d0c04b5b414 100644
--- a/compiler/rustc_mir/src/interpret/traits.rs
+++ b/compiler/rustc_mir/src/interpret/traits.rs
@@ -158,6 +158,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap();
         let align = vtable.read_ptr_sized(pointer_size * 2)?.check_init()?;
         let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
+        let align = Align::from_bytes(align)
+            .map_err(|e| err_ub_format!("invalid vtable: alignment {}", e))?;
 
         if size >= self.tcx.data_layout.obj_size_bound() {
             throw_ub_format!(
@@ -165,6 +167,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 size is bigger than largest supported object"
             );
         }
-        Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap()))
+        Ok((Size::from_bytes(size), align))
     }
 }
diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs b/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs
new file mode 100644
index 00000000000..0c0e3682de4
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs
@@ -0,0 +1,21 @@
+// This test contains code with incorrect vtables in a const context:
+// - from issue 86132: a trait object with invalid alignment caused an ICE in const eval, and now
+//   triggers an error
+// - a similar test that triggers a previously-untested const UB error: emitted close to the above
+//   error, it checks the correctness of the size
+
+trait Trait {}
+
+const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
+    unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+//~^ ERROR any use of this value will cause an error
+//~| WARNING this was previously accepted by the compiler
+//~| invalid vtable: alignment `1000` is not a power of 2
+
+const INVALID_VTABLE_SIZE: &dyn Trait =
+    unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+//~^ ERROR any use of this value will cause an error
+//~| WARNING this was previously accepted by the compiler
+//~| invalid vtable: size is bigger than largest supported object
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr
new file mode 100644
index 00000000000..c937d039d38
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr
@@ -0,0 +1,27 @@
+error: any use of this value will cause an error
+  --> $DIR/ub-incorrect-vtable.rs:10:14
+   |
+LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
+LL | |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
+   |                |
+   |                invalid vtable: alignment `1000` is not a power of 2
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/ub-incorrect-vtable.rs:16:14
+   |
+LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
+LL | |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
+   |                |
+   |                invalid vtable: size is bigger than largest supported object
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 2 previous errors
+