]> git.lizzy.rs Git - rust.git/commitdiff
only count deref_operand as actual deref, but not all ref-to-place conversions
authorRalf Jung <post@ralfj.de>
Wed, 7 Nov 2018 09:07:50 +0000 (10:07 +0100)
committerRalf Jung <post@ralfj.de>
Wed, 7 Nov 2018 15:54:31 +0000 (16:54 +0100)
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/validity.rs

index cb2a750f4e3b6cc4a987a5fe88ee6ac31ff9833c..7c704e97911407e047dc752b14e67d824fdba8fa 100644 (file)
@@ -183,8 +183,7 @@ pub fn hook_fn(
         } else if Some(def_id) == self.tcx.lang_items().panic_fn() {
             assert!(args.len() == 1);
             // &(&'static str, &'static str, u32, u32)
-            let ptr = self.read_immediate(args[0])?;
-            let place = self.ref_to_mplace(ptr)?;
+            let place = self.deref_operand(args[0])?;
             let (msg, file, line, col) = (
                 self.mplace_field(place, 0)?,
                 self.mplace_field(place, 1)?,
@@ -192,9 +191,9 @@ pub fn hook_fn(
                 self.mplace_field(place, 3)?,
             );
 
-            let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?;
+            let msg_place = self.deref_operand(msg.into())?;
             let msg = Symbol::intern(self.read_str(msg_place)?);
-            let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?;
+            let file_place = self.deref_operand(file.into())?;
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
             let col = self.read_scalar(col.into())?.to_u32()?;
@@ -203,17 +202,16 @@ pub fn hook_fn(
             assert!(args.len() == 2);
             // &'static str, &(&'static str, u32, u32)
             let msg = args[0];
-            let ptr = self.read_immediate(args[1])?;
-            let place = self.ref_to_mplace(ptr)?;
+            let place = self.deref_operand(args[1])?;
             let (file, line, col) = (
                 self.mplace_field(place, 0)?,
                 self.mplace_field(place, 1)?,
                 self.mplace_field(place, 2)?,
             );
 
-            let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?;
+            let msg_place = self.deref_operand(msg.into())?;
             let msg = Symbol::intern(self.read_str(msg_place)?);
-            let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?;
+            let file_place = self.deref_operand(file.into())?;
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
             let col = self.read_scalar(col.into())?.to_u32()?;
index 83a2d14b7ca4cdf9896d81e46758e697b6b67de0..a97bf95e7345d05e93c8115c45deb98f32f49ad2 100644 (file)
@@ -555,17 +555,6 @@ pub fn operand_downcast(
         })
     }
 
-    // Take an operand, representing a pointer, and dereference it to a place -- that
-    // will always be a MemPlace.
-    pub(super) fn deref_operand(
-        &self,
-        src: OpTy<'tcx, M::PointerTag>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        let val = self.read_immediate(src)?;
-        trace!("deref to {} on {:?}", val.layout.ty, *val);
-        Ok(self.ref_to_mplace(val)?)
-    }
-
     pub fn operand_projection(
         &self,
         base: OpTy<'tcx, M::PointerTag>,
index d52250a43ac9f340c257de3928ef39f69425969d..510b5826e489b4ee2ef7f7ff7ddd613745eab215 100644 (file)
@@ -277,6 +277,8 @@ impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M>
 {
     /// Take a value, which represents a (thin or fat) reference, and make it a place.
     /// Alignment is just based on the type.  This is the inverse of `MemPlace::to_ref()`.
+    /// This does NOT call the "deref" machine hook, so it does NOT count as a
+    /// deref as far as Stacked Borrows is concerned.  Use `deref_operand` for that!
     pub fn ref_to_mplace(
         &self,
         val: ImmTy<'tcx, M::PointerTag>,
@@ -284,11 +286,25 @@ pub fn ref_to_mplace(
         let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty;
         let layout = self.layout_of(pointee_type)?;
 
-        let align = layout.align;
-        let meta = val.to_meta()?;
-        let ptr = val.to_scalar_ptr()?;
-        let mplace = MemPlace { ptr, align, meta };
-        let mut mplace = MPlaceTy { mplace, layout };
+        let mplace = MemPlace {
+            ptr: val.to_scalar_ptr()?,
+            align: layout.align,
+            meta: val.to_meta()?,
+        };
+        Ok(MPlaceTy { mplace, layout })
+    }
+
+    // Take an operand, representing a pointer, and dereference it to a place -- that
+    // will always be a MemPlace.  Lives in `place.rs` because it creates a place.
+    // This calls the "deref" machine hook, and counts as a deref as far as
+    // Stacked Borrows is concerned.
+    pub fn deref_operand(
+        &self,
+        src: OpTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        let val = self.read_immediate(src)?;
+        trace!("deref to {} on {:?}", val.layout.ty, *val);
+        let mut place = self.ref_to_mplace(val)?;
         // Pointer tag tracking might want to adjust the tag.
         let mutbl = match val.layout.ty.sty {
             // `builtin_deref` considers boxes immutable, that's useless for our purposes
@@ -297,9 +313,8 @@ pub fn ref_to_mplace(
             ty::RawPtr(_) => None,
             _ => bug!("Unexpected pointer type {}", val.layout.ty.sty),
         };
-        mplace.mplace.ptr = M::tag_dereference(self, mplace, mutbl)?;
-        // Done
-        Ok(mplace)
+        place.mplace.ptr = M::tag_dereference(self, place, mutbl)?;
+        Ok(place)
     }
 
     /// Offset a pointer to project to a field. Unlike place_field, this is always
index 4cd7ca8182e99bd63b72728cda93412840dc2a4b..6070b31d3e7a3f7d67c6926223acb2e183f8ffeb 100644 (file)
@@ -402,7 +402,7 @@ fn eval_fn_call(
             ty::InstanceDef::Virtual(_, idx) => {
                 let ptr_size = self.pointer_size();
                 let ptr_align = self.tcx.data_layout.pointer_align;
-                let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?;
+                let ptr = self.deref_operand(args[0])?;
                 let vtable = ptr.vtable()?;
                 let fn_ptr = self.memory.read_ptr_sized(
                     vtable.offset(ptr_size * (idx as u64 + 3), self)?,
index 8c8b3e2ca77c49ddea6244d1ce8318a12a25a195..97bce651c05a16fcf2220a56c5dcd69bcf08f6ca 100644 (file)
@@ -322,13 +322,10 @@ fn visit_primitive(&mut self, value: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'
                         }
                     }
                 }
-                // Turn ptr into place.
-                // `ref_to_mplace` also calls the machine hook for (re)activating the tag,
-                // which in turn will (in full miri) check if the pointer is dereferencable.
-                let place = self.ecx.ref_to_mplace(value)?;
                 // Recursive checking
                 if let Some(ref mut ref_tracking) = self.ref_tracking {
                     assert!(self.const_mode, "We should only do recursie checking in const mode");
+                    let place = self.ecx.ref_to_mplace(value)?;
                     if size != Size::ZERO {
                         // Non-ZST also have to be dereferencable
                         let ptr = try_validation!(place.ptr.to_ptr(),