@@ -178,7 +178,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
178178 & mut self ,
179179 place : & MPlaceTy < ' tcx , Provenance > , // parent tag extracted from here
180180 ptr_size : Size ,
181- new_perm : Option < NewPermission > ,
181+ new_perm : NewPermission ,
182182 new_tag : BorTag ,
183183 ) -> InterpResult < ' tcx , Option < ( AllocId , BorTag ) > > {
184184 let this = self . eval_context_mut ( ) ;
@@ -256,10 +256,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
256256 ptr_size. bytes( )
257257 ) ;
258258
259- let Some ( new_perm) = new_perm else {
260- return Ok ( Some ( ( alloc_id, orig_tag) ) ) ;
261- } ;
262-
263259 if let Some ( protect) = new_perm. protector {
264260 // We register the protection in two different places.
265261 // This makes creating a protector slower, but checking whether a tag
@@ -305,7 +301,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
305301 fn tb_retag_reference (
306302 & mut self ,
307303 val : & ImmTy < ' tcx , Provenance > ,
308- new_perm : Option < NewPermission > ,
304+ new_perm : NewPermission ,
309305 ) -> InterpResult < ' tcx , ImmTy < ' tcx , Provenance > > {
310306 let this = self . eval_context_mut ( ) ;
311307 // 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<'
317313 // - if the pointer is not reborrowed (raw pointer) or if `zero_size` is set
318314 // then we override the size to do a zero-length reborrow.
319315 let reborrow_size = match new_perm {
320- Some ( NewPermission { zero_size : false , .. } ) =>
316+ NewPermission { zero_size : false , .. } =>
321317 this. size_and_align_of_mplace ( & place) ?
322318 . map ( |( size, _) | size)
323319 . unwrap_or ( place. layout . size ) ,
@@ -374,7 +370,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
374370 NewPermission :: from_ref_ty ( pointee, mutability, kind, this) ,
375371 _ => None ,
376372 } ;
377- this. tb_retag_reference ( val, new_perm)
373+ if let Some ( new_perm) = new_perm {
374+ this. tb_retag_reference ( val, new_perm)
375+ } else {
376+ Ok ( val. clone ( ) )
377+ }
378378 }
379379
380380 /// Retag all pointers that are stored in this place.
@@ -405,9 +405,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
405405 place : & PlaceTy < ' tcx , Provenance > ,
406406 new_perm : Option < NewPermission > ,
407407 ) -> InterpResult < ' tcx > {
408- let val = self . ecx . read_immediate ( & self . ecx . place_to_op ( place) ?) ?;
409- let val = self . ecx . tb_retag_reference ( & val, new_perm) ?;
410- self . ecx . write_immediate ( * val, place) ?;
408+ if let Some ( new_perm) = new_perm {
409+ let val = self . ecx . read_immediate ( & self . ecx . place_to_op ( place) ?) ?;
410+ let val = self . ecx . tb_retag_reference ( & val, new_perm) ?;
411+ self . ecx . write_immediate ( * val, place) ?;
412+ }
411413 Ok ( ( ) )
412414 }
413415 }
@@ -493,36 +495,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
493495 }
494496 }
495497
496- /// After a stack frame got pushed, retag the return place so that we are sure
497- /// it does not alias with anything .
498+ /// Protect a place so that it cannot be used any more for the duration of the current function
499+ /// call .
498500 ///
499- /// This is a HACK because there is nothing in MIR that would make the retag
500- /// explicit. Also see <https://github.com/rust-lang/rust/issues/71117>.
501- fn tb_retag_return_place ( & mut self ) -> InterpResult < ' tcx > {
501+ /// This is used to ensure soundness of in-place function argument/return passing.
502+ fn tb_protect_place ( & mut self , place : & MPlaceTy < ' tcx , Provenance > ) -> InterpResult < ' tcx > {
502503 let this = self . eval_context_mut ( ) ;
503- //this.debug_hint_location();
504- let return_place = & this. frame ( ) . return_place ;
505- if return_place. layout . is_zst ( ) {
506- // There may not be any memory here, nothing to do.
507- return Ok ( ( ) ) ;
508- }
509- // We need this to be in-memory to use tagged pointers.
510- let return_place = this. force_allocation ( & return_place. clone ( ) ) ?;
511504
512- // We have to turn the place into a pointer to use the existing code .
505+ // We have to turn the place into a pointer to use the usual retagging logic .
513506 // (The pointer type does not matter, so we use a raw pointer.)
514- let ptr_layout = this. layout_of ( Ty :: new_mut_ptr ( this. tcx . tcx , return_place . layout . ty ) ) ?;
515- let val = ImmTy :: from_immediate ( return_place . to_ref ( this) , ptr_layout) ;
516- // Reborrow it. With protection! That is part of the point.
517- let new_perm = Some ( NewPermission {
507+ let ptr_layout = this. layout_of ( Ty :: new_mut_ptr ( this. tcx . tcx , place . layout . ty ) ) ?;
508+ let ptr = ImmTy :: from_immediate ( place . to_ref ( this) , ptr_layout) ;
509+ // Reborrow it. With protection! That is the entire point.
510+ let new_perm = NewPermission {
518511 initial_state : Permission :: new_active ( ) ,
519512 zero_size : false ,
520513 protector : Some ( ProtectorKind :: StrongProtector ) ,
521- } ) ;
522- let val = this. tb_retag_reference ( & val, new_perm) ?;
523- // And use reborrowed pointer for return place.
524- let return_place = this. ref_to_mplace ( & val) ?;
525- this. frame_mut ( ) . return_place = return_place. into ( ) ;
514+ } ;
515+ let _new_ptr = this. tb_retag_reference ( & ptr, new_perm) ?;
516+ // We just throw away `new_ptr`, so nobody can access this memory while it is protected.
526517
527518 Ok ( ( ) )
528519 }
0 commit comments