about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-06-13 12:08:59 +0000
committerbors <bors@rust-lang.org>2021-06-13 12:08:59 +0000
commitfb3ea63d9b4c3e9bb90d4250b870faaffb9c8fd2 (patch)
tree94675917e0edd783192d018e3d0250e537f47d8a /compiler
parent6cc5d5432aaed21630ead1fa59418245ee2e1047 (diff)
parente29f3e837fb6262040d42d4cde8e2f775dee0fe7 (diff)
downloadrust-fb3ea63d9b4c3e9bb90d4250b870faaffb9c8fd2.tar.gz
rust-fb3ea63d9b4c3e9bb90d4250b870faaffb9c8fd2.zip
Auto merge of #86245 - lqd:const-ub-align, r=RalfJung
Fix ICEs on invalid vtable size/alignment const UB errors

The invalid vtable size/alignment errors from `InterpCx::read_size_and_align_from_vtable` were "freeform const UB errors", causing ICEs when reaching validation. This PR turns them into const UB hard errors to catch them during validation and avoid that.

Fixes #86193

r? `@RalfJung`

(It seemed cleaner to have 2 variants but they can be merged into one variant with a message payload if you prefer that ?)
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs12
-rw-r--r--compiler/rustc_mir/src/interpret/traits.rs13
-rw-r--r--compiler/rustc_mir/src/interpret/validity.rs6
3 files changed, 20 insertions, 11 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 65d9c1dd90e..aca39d438c1 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -227,7 +227,11 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     /// Invalid metadata in a wide pointer (using `str` to avoid allocations).
     InvalidMeta(&'static str),
     /// Invalid drop function in vtable.
-    InvalidDropFn(FnSig<'tcx>),
+    InvalidVtableDropFn(FnSig<'tcx>),
+    /// Invalid size in a vtable: too large.
+    InvalidVtableSize,
+    /// Invalid alignment in a vtable: too large, or not a power of 2.
+    InvalidVtableAlignment(String),
     /// Reading a C string that does not end within its allocation.
     UnterminatedCString(Pointer),
     /// Dereferencing a dangling pointer after it got freed.
@@ -287,11 +291,15 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
             RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
             PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
             InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
-            InvalidDropFn(sig) => write!(
+            InvalidVtableDropFn(sig) => write!(
                 f,
                 "invalid drop function signature: got {}, expected exactly one argument which must be a pointer type",
                 sig
             ),
+            InvalidVtableSize => {
+                write!(f, "invalid vtable: size is bigger than largest supported object")
+            }
+            InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {}", msg),
             UnterminatedCString(p) => write!(
                 f,
                 "reading a null-terminated string starting at {} with no null found before end of allocation",
diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_mir/src/interpret/traits.rs
index d0c04b5b414..9a59161f08f 100644
--- a/compiler/rustc_mir/src/interpret/traits.rs
+++ b/compiler/rustc_mir/src/interpret/traits.rs
@@ -137,9 +137,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // The drop function takes `*mut T` where `T` is the type being dropped, so get that.
         let args = fn_sig.inputs();
         if args.len() != 1 {
-            throw_ub!(InvalidDropFn(fn_sig));
+            throw_ub!(InvalidVtableDropFn(fn_sig));
         }
-        let ty = args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidDropFn(fn_sig)))?.ty;
+        let ty =
+            args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidVtableDropFn(fn_sig)))?.ty;
         Ok((drop_instance, ty))
     }
 
@@ -158,14 +159,10 @@ 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))?;
+        let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?;
 
         if size >= self.tcx.data_layout.obj_size_bound() {
-            throw_ub_format!(
-                "invalid vtable: \
-                size is bigger than largest supported object"
-            );
+            throw_ub!(InvalidVtableSize);
         }
         Ok((Size::from_bytes(size), align))
     }
diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs
index fb165a991bc..c9ebffe8d1c 100644
--- a/compiler/rustc_mir/src/interpret/validity.rs
+++ b/compiler/rustc_mir/src/interpret/validity.rs
@@ -349,12 +349,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                     err_ub!(InvalidFunctionPointer(..)) |
                     err_unsup!(ReadBytesAsPointer) =>
                         { "invalid drop function pointer in vtable (not pointing to a function)" },
-                    err_ub!(InvalidDropFn(..)) =>
+                    err_ub!(InvalidVtableDropFn(..)) =>
                         { "invalid drop function pointer in vtable (function has incompatible signature)" },
                 );
                 try_validation!(
                     self.ecx.read_size_and_align_from_vtable(vtable),
                     self.path,
+                    err_ub!(InvalidVtableSize) =>
+                        { "invalid vtable: size is bigger than largest supported object" },
+                    err_ub!(InvalidVtableAlignment(msg)) =>
+                        { "invalid vtable: alignment {}", msg },
                     err_unsup!(ReadPointerAsBytes) => { "invalid size or align in vtable" },
                 );
                 // FIXME: More checks for the vtable.