@@ -296,7 +296,6 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
296296
297297 type AllocExtra = stacked_borrows:: Stacks ;
298298 type PointerTag = Borrow ;
299- const ENABLE_PTR_TRACKING_HOOKS : bool = true ;
300299
301300 type MemoryMap = MonoHashMap < AllocId , ( MemoryKind < MiriMemoryKind > , Allocation < Borrow , Self :: AllocExtra > ) > ;
302301
@@ -309,16 +308,18 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
309308
310309 // Some functions are whitelisted until we figure out how to fix them.
311310 // We walk up the stack a few frames to also cover their callees.
312- const WHITELIST : & [ & str ] = & [
311+ const WHITELIST : & [ ( & str , & str ) ] = & [
313312 // Uses mem::uninitialized
314- "std::ptr::read" ,
315- "std::sys::windows::mutex::Mutex::" ,
313+ ( "std::ptr::read" , "" ) ,
314+ ( "std::sys::windows::mutex::Mutex::" , "" ) ,
315+ // Should directly take a raw reference
316+ ( "<std::cell::UnsafeCell<T>>" , "::get" ) ,
316317 ] ;
317318 for frame in ecx. stack ( ) . iter ( )
318319 . rev ( ) . take ( 3 )
319320 {
320321 let name = frame. instance . to_string ( ) ;
321- if WHITELIST . iter ( ) . any ( |white | name. starts_with ( white ) ) {
322+ if WHITELIST . iter ( ) . any ( |( prefix , suffix ) | name. starts_with ( prefix ) && name . ends_with ( suffix ) ) {
322323 return false ;
323324 }
324325 }
@@ -446,26 +447,6 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
446447 Cow :: Owned ( alloc)
447448 }
448449
449- #[ inline( always) ]
450- fn tag_reference (
451- ecx : & mut EvalContext < ' a , ' mir , ' tcx , Self > ,
452- place : MPlaceTy < ' tcx , Borrow > ,
453- mutability : Option < hir:: Mutability > ,
454- ) -> EvalResult < ' tcx , Scalar < Borrow > > {
455- let ( size, _) = ecx. size_and_align_of_mplace ( place) ?
456- // for extern types, just cover what we can
457- . unwrap_or_else ( || place. layout . size_and_align ( ) ) ;
458- if !ecx. machine . validate || size == Size :: ZERO {
459- // No tracking
460- Ok ( place. ptr )
461- } else {
462- let ptr = place. ptr . to_ptr ( ) ?;
463- let tag = ecx. tag_reference ( place, size, mutability. into ( ) ) ?;
464- Ok ( Scalar :: Ptr ( Pointer :: new_with_tag ( ptr. alloc_id , ptr. offset , tag) ) )
465- }
466- }
467-
468- #[ inline( always) ]
469450 fn tag_dereference (
470451 ecx : & EvalContext < ' a , ' mir , ' tcx , Self > ,
471452 place : MPlaceTy < ' tcx , Borrow > ,
@@ -474,11 +455,13 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
474455 let ( size, _) = ecx. size_and_align_of_mplace ( place) ?
475456 // for extern types, just cover what we can
476457 . unwrap_or_else ( || place. layout . size_and_align ( ) ) ;
477- if !ecx. machine . validate || size == Size :: ZERO {
458+ if !ecx. tcx . sess . opts . debugging_opts . mir_emit_retag ||
459+ !Self :: enforce_validity ( ecx) || size == Size :: ZERO
460+ {
478461 // No tracking
479462 Ok ( place. ptr )
480463 } else {
481- let ptr = place. ptr . to_ptr ( ) ?;
464+ let ptr = place. ptr . to_ptr ( ) ?; // assert this is not a scalar
482465 let tag = ecx. tag_dereference ( place, size, mutability. into ( ) ) ?;
483466 Ok ( Scalar :: Ptr ( Pointer :: new_with_tag ( ptr. alloc_id , ptr. offset , tag) ) )
484467 }
@@ -499,19 +482,46 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
499482 }
500483 }
501484
485+ #[ inline]
486+ fn escape_to_raw (
487+ ecx : & mut EvalContext < ' a , ' mir , ' tcx , Self > ,
488+ ptr : OpTy < ' tcx , Self :: PointerTag > ,
489+ ) -> EvalResult < ' tcx > {
490+ // It is tempting to check the type here, but drop glue does EscapeToRaw
491+ // on a raw pointer.
492+ // This is deliberately NOT `deref_operand` as we do not want `tag_dereference`
493+ // to be called! That would kill the original tag if we got a raw ptr.
494+ let place = ecx. ref_to_mplace ( ecx. read_immediate ( ptr) ?) ?;
495+ let ( size, _) = ecx. size_and_align_of_mplace ( place) ?
496+ // for extern types, just cover what we can
497+ . unwrap_or_else ( || place. layout . size_and_align ( ) ) ;
498+ if !ecx. tcx . sess . opts . debugging_opts . mir_emit_retag ||
499+ !ecx. machine . validate || size == Size :: ZERO
500+ {
501+ // No tracking, or no retagging. The latter is possible because a dependency of ours
502+ // might be called with different flags than we are, so there are `Retag`
503+ // statements but we do not want to execute them.
504+ Ok ( ( ) )
505+ } else {
506+ ecx. escape_to_raw ( place, size)
507+ }
508+ }
509+
502510 #[ inline( always) ]
503511 fn retag (
504512 ecx : & mut EvalContext < ' a , ' mir , ' tcx , Self > ,
505513 fn_entry : bool ,
506514 place : PlaceTy < ' tcx , Borrow > ,
507515 ) -> EvalResult < ' tcx > {
508516 if !ecx. tcx . sess . opts . debugging_opts . mir_emit_retag || !Self :: enforce_validity ( ecx) {
509- // No tracking, or no retagging. This is possible because a dependency of ours might be
510- // called with different flags than we are,
517+ // No tracking, or no retagging. The latter is possible because a dependency of ours
518+ // might be called with different flags than we are, so there are `Retag`
519+ // statements but we do not want to execute them.
511520 // Also, honor the whitelist in `enforce_validity` because otherwise we might retag
512521 // uninitialized data.
513- return Ok ( ( ) )
522+ Ok ( ( ) )
523+ } else {
524+ ecx. retag ( fn_entry, place)
514525 }
515- ecx. retag ( fn_entry, place)
516526 }
517527}
0 commit comments