about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/interpret/operand.rs18
-rw-r--r--src/librustc_mir/interpret/place.rs11
2 files changed, 25 insertions, 4 deletions
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 48e7193ec39..93ab7b9aab7 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -444,13 +444,27 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Field(field, _) => self.operand_field(base, field.index() as u64)?,
             Downcast(_, variant) => self.operand_downcast(base, variant)?,
             Deref => self.deref_operand(base)?.into(),
-            Subslice { .. } | ConstantIndex { .. } | Index(_) => if base.layout.is_zst() {
+            ConstantIndex { .. } | Index(_) if base.layout.is_zst() => {
                 OpTy {
                     op: Operand::Immediate(Scalar::zst().into()),
                     // the actual index doesn't matter, so we just pick a convenient one like 0
                     layout: base.layout.field(self, 0)?,
                 }
-            } else {
+            }
+            Subslice { from, to, from_end } if base.layout.is_zst() => {
+                let elem_ty = if let ty::Array(elem_ty, _) = base.layout.ty.kind {
+                    elem_ty
+                } else {
+                    bug!("slices shouldn't be zero-sized");
+                };
+                assert!(!from_end, "arrays shouldn't be subsliced from the end");
+
+                OpTy {
+                    op: Operand::Immediate(Scalar::zst().into()),
+                    layout: self.layout_of(self.tcx.mk_array(elem_ty, (to - from) as u64))?,
+                }
+            }
+            Subslice { .. } | ConstantIndex { .. }  | Index(_) => {
                 // The rest should only occur as mplace, we do not use Immediates for types
                 // allowing such operations.  This matches place_projection forcing an allocation.
                 let mplace = base.assert_mem_place();
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 42fbfeca3f0..8923b167fde 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -455,7 +455,10 @@ where
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         let actual_to = if from_end {
-            assert!(from <= len - to);
+            if from + to > len {
+                // This can only be reached in ConstProp and non-rustc-MIR.
+                throw_ub!(BoundsCheckFailed { len: len as u64, index: from as u64 + to as u64 });
+            }
             len - to
         } else {
             to
@@ -523,7 +526,11 @@ where
                 from_end,
             } => {
                 let n = base.len(self)?;
-                assert!(n >= min_length as u64);
+                if n < min_length as u64 {
+                    // This can only be reached in ConstProp and non-rustc-MIR.
+                    throw_ub!(BoundsCheckFailed { len: min_length as u64, index: n as u64 });
+                }
+                assert!(offset < min_length);
 
                 let index = if from_end {
                     n - u64::from(offset)