@@ -178,7 +178,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
178
178
& mut self ,
179
179
place : & MPlaceTy < ' tcx , Provenance > , // parent tag extracted from here
180
180
ptr_size : Size ,
181
- new_perm : Option < NewPermission > ,
181
+ new_perm : NewPermission ,
182
182
new_tag : BorTag ,
183
183
) -> InterpResult < ' tcx , Option < ( AllocId , BorTag ) > > {
184
184
let this = self . eval_context_mut ( ) ;
@@ -256,10 +256,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
256
256
ptr_size. bytes( )
257
257
) ;
258
258
259
- let Some ( new_perm) = new_perm else {
260
- return Ok ( Some ( ( alloc_id, orig_tag) ) ) ;
261
- } ;
262
-
263
259
if let Some ( protect) = new_perm. protector {
264
260
// We register the protection in two different places.
265
261
// This makes creating a protector slower, but checking whether a tag
@@ -305,7 +301,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
305
301
fn tb_retag_reference (
306
302
& mut self ,
307
303
val : & ImmTy < ' tcx , Provenance > ,
308
- new_perm : Option < NewPermission > ,
304
+ new_perm : NewPermission ,
309
305
) -> InterpResult < ' tcx , ImmTy < ' tcx , Provenance > > {
310
306
let this = self . eval_context_mut ( ) ;
311
307
// 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<'
317
313
// - if the pointer is not reborrowed (raw pointer) or if `zero_size` is set
318
314
// then we override the size to do a zero-length reborrow.
319
315
let reborrow_size = match new_perm {
320
- Some ( NewPermission { zero_size : false , .. } ) =>
316
+ NewPermission { zero_size : false , .. } =>
321
317
this. size_and_align_of_mplace ( & place) ?
322
318
. map ( |( size, _) | size)
323
319
. unwrap_or ( place. layout . size ) ,
@@ -374,7 +370,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
374
370
NewPermission :: from_ref_ty ( pointee, mutability, kind, this) ,
375
371
_ => None ,
376
372
} ;
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
+ }
378
378
}
379
379
380
380
/// Retag all pointers that are stored in this place.
@@ -405,9 +405,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
405
405
place : & PlaceTy < ' tcx , Provenance > ,
406
406
new_perm : Option < NewPermission > ,
407
407
) -> 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
+ }
411
413
Ok ( ( ) )
412
414
}
413
415
}
@@ -493,37 +495,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
493
495
}
494
496
}
495
497
496
- /// After a stack frame got pushed, retag the return place so that we are sure
497
- /// it does not alias with anything.
498
- ///
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 > {
498
+ /// Protect a place so that it cannot be used any more for the duration of the current function
499
+ /// call.
500
+ ///
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 > {
502
503
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 ( ) ) ?;
511
504
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 .
513
506
// (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
- // FIXME: do we truly want a 2phase borrow here?
518
- let new_perm = Some ( NewPermission {
519
- initial_state : Permission :: new_unique_2phase ( /*freeze*/ false ) ,
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 {
511
+ initial_state : Permission :: new_active ( ) ,
520
512
zero_size : false ,
521
513
protector : Some ( ProtectorKind :: StrongProtector ) ,
522
- } ) ;
523
- let val = this. tb_retag_reference ( & val, new_perm) ?;
524
- // And use reborrowed pointer for return place.
525
- let return_place = this. ref_to_mplace ( & val) ?;
526
- 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.
527
517
528
518
Ok ( ( ) )
529
519
}
0 commit comments