miri tree borrows: skip retag_reference early if there is no NewPermission

This commit is contained in:
Ralf Jung 2023-07-10 22:14:28 +02:00
parent dd453a6a99
commit 95392ef0c9

View File

@ -178,7 +178,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
&mut self,
place: &MPlaceTy<'tcx, Provenance>, // parent tag extracted from here
ptr_size: Size,
new_perm: Option<NewPermission>,
new_perm: NewPermission,
new_tag: BorTag,
) -> InterpResult<'tcx, Option<(AllocId, BorTag)>> {
let this = self.eval_context_mut();
@ -256,10 +256,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
ptr_size.bytes()
);
let Some(new_perm) = new_perm else {
return Ok(Some((alloc_id, orig_tag)));
};
if let Some(protect) = new_perm.protector {
// We register the protection in two different places.
// This makes creating a protector slower, but checking whether a tag
@ -305,7 +301,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
fn tb_retag_reference(
&mut self,
val: &ImmTy<'tcx, Provenance>,
new_perm: Option<NewPermission>,
new_perm: NewPermission,
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
let this = self.eval_context_mut();
// We want a place for where the ptr *points to*, so we get one.
@ -317,7 +313,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
// - if the pointer is not reborrowed (raw pointer) or if `zero_size` is set
// then we override the size to do a zero-length reborrow.
let reborrow_size = match new_perm {
Some(NewPermission { zero_size: false, .. }) =>
NewPermission { zero_size: false, .. } =>
this.size_and_align_of_mplace(&place)?
.map(|(size, _)| size)
.unwrap_or(place.layout.size),
@ -374,7 +370,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
NewPermission::from_ref_ty(pointee, mutability, kind, this),
_ => None,
};
this.tb_retag_reference(val, new_perm)
if let Some(new_perm) = new_perm {
this.tb_retag_reference(val, new_perm)
} else {
Ok(val.clone())
}
}
/// Retag all pointers that are stored in this place.
@ -405,9 +405,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
place: &PlaceTy<'tcx, Provenance>,
new_perm: Option<NewPermission>,
) -> InterpResult<'tcx> {
let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
let val = self.ecx.tb_retag_reference(&val, new_perm)?;
self.ecx.write_immediate(*val, place)?;
if let Some(new_perm) = new_perm {
let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
let val = self.ecx.tb_retag_reference(&val, new_perm)?;
self.ecx.write_immediate(*val, place)?;
}
Ok(())
}
}
@ -505,11 +507,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, place.layout.ty))?;
let ptr = ImmTy::from_immediate(place.to_ref(this), ptr_layout);
// Reborrow it. With protection! That is the entire point.
let new_perm = Some(NewPermission {
let new_perm = NewPermission {
initial_state: Permission::new_active(),
zero_size: false,
protector: Some(ProtectorKind::StrongProtector),
});
};
let _new_ptr = this.tb_retag_reference(&ptr, new_perm)?;
// We just throw away `new_ptr`, so nobody can access this memory while it is protected.