fix interpreter validity check on Box
This commit is contained in:
parent
b04bfb4aea
commit
7fc77806d4
2 changed files with 29 additions and 6 deletions
|
@ -594,13 +594,35 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
ty::Adt(def, ..) if def.is_box() => {
|
ty::Adt(def, ..) if def.is_box() => {
|
||||||
let unique = self.ecx.operand_field(value, 0)?;
|
// Box is special, very special. We carefully assert all the assumptions we make
|
||||||
let nonnull = self.ecx.operand_field(&unique, 0)?;
|
// here; if this needs to be adjusted, remember to also adjust all the other
|
||||||
let ptr = self.ecx.operand_field(&nonnull, 0)?;
|
// visitors -- in particular the Stacked Borrows retagging visitor in Miri.
|
||||||
self.check_safe_pointer(&ptr, "box")?;
|
// Did I mention that this is a gross hack? Anyway...
|
||||||
|
|
||||||
// Check other fields of Box
|
// `Box` has two fields: the pointer we care about, and the allocator.
|
||||||
self.walk_value(value)?;
|
assert_eq!(value.layout.fields.count(), 2, "`Box` must have exactly 2 fields");
|
||||||
|
let (unique_ptr, alloc) =
|
||||||
|
(self.ecx.operand_field(value, 0)?, self.ecx.operand_field(value, 1)?);
|
||||||
|
// Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`...
|
||||||
|
// (which means another 2 fields, the second of which is a `PhantomData`)
|
||||||
|
assert_eq!(unique_ptr.layout.fields.count(), 2);
|
||||||
|
let (nonnull_ptr, phantom) = (
|
||||||
|
self.ecx.operand_field(&unique_ptr, 0)?,
|
||||||
|
self.ecx.operand_field(&unique_ptr, 1)?,
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
phantom.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()),
|
||||||
|
"2nd field of `Unique` should be PhantomData but is {:?}",
|
||||||
|
phantom.layout.ty,
|
||||||
|
);
|
||||||
|
// ... that contains a `NonNull`... (gladly, only a single field here)
|
||||||
|
assert_eq!(nonnull_ptr.layout.fields.count(), 1);
|
||||||
|
let raw_ptr = self.ecx.operand_field(&nonnull_ptr, 0)?; // the actual raw ptr
|
||||||
|
// ... whose only field finally is a raw ptr we can dereference.
|
||||||
|
self.check_safe_pointer(&raw_ptr, "box")?;
|
||||||
|
// The second `Box` field is the allocator, which we recursively check for validity
|
||||||
|
// like in regular structs.
|
||||||
|
self.walk_value(&alloc)?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
ty::FnPtr(_sig) => {
|
ty::FnPtr(_sig) => {
|
||||||
|
|
|
@ -21,6 +21,7 @@ Rust MIR: a lowered representation of Rust.
|
||||||
#![feature(trusted_step)]
|
#![feature(trusted_step)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(yeet_expr)]
|
#![feature(yeet_expr)]
|
||||||
|
#![feature(is_some_with)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue