]> git.lizzy.rs Git - rust.git/commitdiff
forcing instead of normalization
authorRalf Jung <post@ralfj.de>
Sat, 6 Jul 2019 12:19:04 +0000 (14:19 +0200)
committerRalf Jung <post@ralfj.de>
Sat, 6 Jul 2019 12:19:04 +0000 (14:19 +0200)
Normalziation does not work well for dyamically sized types

src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/validity.rs

index b43c810b8e626f92da8ce4ae87d68952319e430e..3d97132e53969472ea39c580fe253867067c3bc0 100644 (file)
@@ -217,13 +217,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Normalice `place.ptr` to a `Pointer` if this is a place and not a ZST.
     /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
     #[inline]
-    pub fn normalize_op_ptr(
+    pub fn force_op_ptr(
         &self,
         op: OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         match op.try_as_mplace() {
-            Ok(mplace) => Ok(self.normalize_mplace_ptr(mplace)?.into()),
-            Err(imm) => Ok(imm.into()), // Nothing to normalize
+            Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()),
+            Err(imm) => Ok(imm.into()), // Nothing to cast/force
         }
     }
 
index 6b8eb3fa77353e6fa17fcfc895dcb1ac1bb3b9b5..50e3789ed80701678f1b092d445714151cdb41c0 100644 (file)
@@ -327,15 +327,13 @@ pub fn check_mplace_access(
         self.memory.check_ptr_access(place.ptr, size, place.align)
     }
 
-    /// Normalice `place.ptr` to a `Pointer` if this is not a ZST.
+    /// Force `place.ptr` to a `Pointer`.
     /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
-    pub fn normalize_mplace_ptr(
+    pub fn force_mplace_ptr(
         &self,
         mut place: MPlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        if !place.layout.is_zst() {
-            place.mplace.ptr = self.force_ptr(place.mplace.ptr)?.into();
-        }
+        place.mplace.ptr = self.force_ptr(place.mplace.ptr)?.into();
         Ok(place)
     }
 
index bf062ac68a5c191fc0f647643393f53ab4721f10..00107a536ba26522d1e317b215342d9d069799d3 100644 (file)
@@ -444,7 +444,12 @@ fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<
                     // `!` is a ZST and we want to validate it.
                     // Normalize before handing `place` to tracking because that will
                     // check for duplicates.
-                    let place = self.ecx.normalize_mplace_ptr(place)?;
+                    let place = if size.bytes() > 0 {
+                        self.ecx.force_mplace_ptr(place)
+                            .expect("we already bounds-checked")
+                    } else {
+                        place
+                    };
                     let path = &self.path;
                     ref_tracking.track(place, || {
                         // We need to clone the path anyway, make sure it gets created
@@ -578,8 +583,8 @@ fn visit_aggregate(
                 let ty_size = self.ecx.layout_of(tys)?.size;
                 // This is the size in bytes of the whole array.
                 let size = ty_size * len;
-                // Size is not 0, get a pointer (no cast because we normalized in validate_operand).
-                let ptr = mplace.ptr.assert_ptr();
+                // Size is not 0, get a pointer.
+                let ptr = self.ecx.force_ptr(mplace.ptr)?;
 
                 // NOTE: Keep this in sync with the handling of integer and float
                 // types above, in `visit_primitive`.
@@ -654,8 +659,10 @@ pub fn validate_operand(
             ecx: self,
         };
 
+        // Try to cast to ptr *once* instead of all the time.
+        let op = self.force_op_ptr(op).unwrap_or(op);
+
         // Run it
-        let op = self.normalize_op_ptr(op)?; // avoid doing ptr-to-int all the time
         visitor.visit_value(op)
     }
 }