diff options
| author | Ralf Jung <post@ralfj.de> | 2024-04-21 11:35:02 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-04-21 13:04:51 +0200 |
| commit | 875f0c2da05da9a7620afd6e2be04fbcb9a4b395 (patch) | |
| tree | 77bad47cfd027e795fbff76b8f8fff4f882f53c8 /compiler/rustc_const_eval/src/interpret/place.rs | |
| parent | b9be3c47e52d9dec0009662c6ce3708c5396f6d4 (diff) | |
| download | rust-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.rs | 17 |
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)) } |
