fix retagging of vtable ptrs

This commit is contained in:
Ralf Jung 2022-07-03 11:54:47 -04:00
parent cfad9d12f3
commit a4e7e1e6b5
2 changed files with 19 additions and 0 deletions

View File

@ -1039,6 +1039,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let val = self.ecx.read_immediate(&place.into())?;
let val = self.ecx.retag_reference(&val, mutbl, protector)?;
self.ecx.write_immediate(*val, &place.into())?;
} else if matches!(place.layout.ty.kind(), ty::RawPtr(..)) {
// Wide raw pointers *do* have fields and their types are strange.
// vtables have a type like `&[*const (); 3]` or so!
// Do *not* recurse into them.
// (No need to worry about wide references or boxes, those always "qualify".)
} else {
// Maybe we need to go deeper.
self.walk_value(place)?;

View File

@ -1,4 +1,5 @@
// compile-flags: -Zmiri-retag-fields
#![feature(allocator_api)]
use std::ptr;
// Test various stacked-borrows-related things.
@ -17,6 +18,7 @@ fn main() {
raw_ref_to_part();
array_casts();
mut_below_shr();
wide_raw_ptr_in_tuple();
}
// Make sure that reading from an `&mut` does, like reborrowing to `&`,
@ -205,3 +207,15 @@ fn mut_below_shr() {
let r = &**p;
let _val = *r;
}
fn wide_raw_ptr_in_tuple() {
let mut x: Box<dyn std::any::Any> = Box::new("ouch");
let r = &mut *x as *mut dyn std::any::Any;
// This triggers the visitor-based recursive retagging. It is *not* supposed to retag raw
// pointers, but then the visitor might recurse into the "fields" of a wide raw pointer and
// finds a reference (to a vtable) there that it wants to retag... and that would be Wrong.
let pair = (r, &0);
let r = unsafe { &mut *pair.0 };
// Make sure the fn ptr part of the vtable is still fine.
r.type_id();
}