diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 48e7193ec39d4..93ab7b9aab7fb 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 42fbfeca3f05d..8923b167fdee8 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)