about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src/interpret/place.rs
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-04-21 11:35:02 +0200
committerRalf Jung <post@ralfj.de>2024-04-21 13:04:51 +0200
commit875f0c2da05da9a7620afd6e2be04fbcb9a4b395 (patch)
tree77bad47cfd027e795fbff76b8f8fff4f882f53c8 /compiler/rustc_const_eval/src/interpret/place.rs
parentb9be3c47e52d9dec0009662c6ce3708c5396f6d4 (diff)
downloadrust-875f0c2da05da9a7620afd6e2be04fbcb9a4b395.tar.gz
rust-875f0c2da05da9a7620afd6e2be04fbcb9a4b395.zip
Miri: detect wrong vtables in wide pointers
Diffstat (limited to 'compiler/rustc_const_eval/src/interpret/place.rs')
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs17
1 files changed, 12 insertions, 5 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 8364a5a8d18..e5241f1ba19 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -1020,16 +1020,20 @@ where
     pub(super) fn unpack_dyn_trait(
         &self,
         mplace: &MPlaceTy<'tcx, M::Provenance>,
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
     ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, Pointer<Option<M::Provenance>>)> {
         assert!(
             matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)),
             "`unpack_dyn_trait` only makes sense on `dyn*` types"
         );
         let vtable = mplace.meta().unwrap_meta().to_pointer(self)?;
-        let (ty, _) = self.get_ptr_vtable(vtable)?;
-        let layout = self.layout_of(ty)?;
+        let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
+        if expected_trait.principal() != vtable_trait {
+            throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
+        }
         // This is a kind of transmute, from a place with unsized type and metadata to
         // a place with sized type and no metadata.
+        let layout = self.layout_of(ty)?;
         let mplace =
             MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..mplace.mplace }, layout };
         Ok((mplace, vtable))
@@ -1040,6 +1044,7 @@ where
     pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
         &self,
         val: &P,
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
     ) -> InterpResult<'tcx, (P, Pointer<Option<M::Provenance>>)> {
         assert!(
             matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
@@ -1048,10 +1053,12 @@ where
         let data = self.project_field(val, 0)?;
         let vtable = self.project_field(val, 1)?;
         let vtable = self.read_pointer(&vtable.to_op(self)?)?;
-        let (ty, _) = self.get_ptr_vtable(vtable)?;
+        let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
+        if expected_trait.principal() != vtable_trait {
+            throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
+        }
+        // `data` is already the right thing but has the wrong type. So we transmute it.
         let layout = self.layout_of(ty)?;
-        // `data` is already the right thing but has the wrong type. So we transmute it, by
-        // projecting with offset 0.
         let data = data.transmute(layout, self)?;
         Ok((data, vtable))
     }