@@ -126,11 +126,20 @@ struct AllocHistory {
126
126
current_time : usize ,
127
127
creations : Vec < Event > ,
128
128
invalidations : Vec < Event > ,
129
+ protectors : Vec < Protection > ,
130
+ }
131
+
132
+ #[ derive( Debug ) ]
133
+ struct Protection {
134
+ orig_tag : SbTag ,
135
+ tag : SbTag ,
136
+ span : Span ,
129
137
}
130
138
131
139
#[ derive( Debug ) ]
132
140
struct Event {
133
141
time : usize ,
142
+ parent : Option < SbTag > ,
134
143
tag : SbTag ,
135
144
range : AllocRange ,
136
145
span : Span ,
@@ -141,11 +150,13 @@ pub enum TagHistory {
141
150
tag : SbTag ,
142
151
created : ( AllocRange , SpanData ) ,
143
152
invalidated : Option < ( AllocRange , SpanData ) > ,
153
+ protected : Option < ( SbTag , SpanData , SpanData ) > ,
144
154
} ,
145
155
Untagged {
146
156
recently_created : Option < ( AllocRange , SpanData ) > ,
147
157
recently_invalidated : Option < ( AllocRange , SpanData ) > ,
148
158
matching_created : Option < ( AllocRange , SpanData ) > ,
159
+ protected : Option < ( SbTag , SpanData , SpanData ) > ,
149
160
} ,
150
161
}
151
162
@@ -258,9 +269,16 @@ impl GlobalState {
258
269
tag
259
270
}
260
271
261
- fn add_creation ( & mut self , tag : SbTag , alloc : AllocId , range : AllocRange ) {
272
+ fn add_creation (
273
+ & mut self ,
274
+ parent : Option < SbTag > ,
275
+ tag : SbTag ,
276
+ alloc : AllocId ,
277
+ range : AllocRange ,
278
+ ) {
262
279
let mut extras = self . extras . entry ( alloc) . or_default ( ) ;
263
280
extras. creations . push ( Event {
281
+ parent,
264
282
tag,
265
283
range,
266
284
span : self . current_span ,
@@ -272,6 +290,7 @@ impl GlobalState {
272
290
fn add_invalidation ( & mut self , tag : SbTag , alloc : AllocId , range : AllocRange ) {
273
291
let mut extras = self . extras . entry ( alloc) . or_default ( ) ;
274
292
extras. invalidations . push ( Event {
293
+ parent : None ,
275
294
tag,
276
295
range,
277
296
span : self . current_span ,
@@ -280,14 +299,40 @@ impl GlobalState {
280
299
extras. current_time += 1 ;
281
300
}
282
301
302
+ fn add_protector ( & mut self , orig_tag : SbTag , tag : SbTag , alloc : AllocId ) {
303
+ let mut extras = self . extras . entry ( alloc) . or_default ( ) ;
304
+ extras. protectors . push ( Protection { orig_tag, tag, span : self . current_span } ) ;
305
+ extras. current_time += 1 ;
306
+ }
307
+
283
308
fn get_stack_history (
284
309
& self ,
285
310
tag : SbTag ,
286
311
alloc : AllocId ,
287
312
alloc_range : AllocRange ,
288
313
offset : Size ,
314
+ protector_tag : Option < SbTag > ,
289
315
) -> Option < TagHistory > {
290
316
let extras = self . extras . get ( & alloc) ?;
317
+ let protected = protector_tag
318
+ . and_then ( |protector| {
319
+ extras. protectors . iter ( ) . find_map ( |protection| {
320
+ if protection. tag == protector {
321
+ Some ( ( protection. orig_tag , protection. span . data ( ) ) )
322
+ } else {
323
+ None
324
+ }
325
+ } )
326
+ } )
327
+ . and_then ( |( tag, call_span) | {
328
+ extras. creations . iter ( ) . rev ( ) . find_map ( |event| {
329
+ if event. tag == tag {
330
+ Some ( ( event. parent ?, event. span . data ( ) , call_span) )
331
+ } else {
332
+ None
333
+ }
334
+ } )
335
+ } ) ;
291
336
if let SbTag :: Tagged ( _) = tag {
292
337
let get_matching = |events : & [ Event ] | {
293
338
events. iter ( ) . rev ( ) . find_map ( |event| {
@@ -296,8 +341,9 @@ impl GlobalState {
296
341
} ;
297
342
Some ( TagHistory :: Tagged {
298
343
tag,
299
- created : get_matching ( & extras. creations ) . unwrap ( ) ,
344
+ created : get_matching ( & extras. creations ) ? ,
300
345
invalidated : get_matching ( & extras. invalidations ) ,
346
+ protected,
301
347
} )
302
348
} else {
303
349
let mut created_time = 0 ;
@@ -348,7 +394,12 @@ impl GlobalState {
348
394
} else {
349
395
None
350
396
} ;
351
- Some ( TagHistory :: Untagged { recently_created, matching_created, recently_invalidated } )
397
+ Some ( TagHistory :: Untagged {
398
+ recently_created,
399
+ matching_created,
400
+ recently_invalidated,
401
+ protected,
402
+ } )
352
403
}
353
404
}
354
405
}
@@ -446,27 +497,33 @@ impl<'tcx> Stack {
446
497
/// `None` during a deallocation.
447
498
fn check_protector (
448
499
item : & Item ,
449
- provoking_access : Option < ( SbTag , AccessKind ) > ,
500
+ provoking_access : Option < ( SbTag , AllocId , AllocRange , Size ) > , // just for debug printing amd error messages
450
501
global : & GlobalState ,
451
502
) -> InterpResult < ' tcx > {
452
503
if let SbTag :: Tagged ( id) = item. tag {
453
504
if Some ( id) == global. tracked_pointer_tag {
454
505
register_diagnostic ( NonHaltingDiagnostic :: PoppedPointerTag (
455
506
item. clone ( ) ,
456
- provoking_access ,
507
+ None , // FIXME
457
508
) ) ;
458
509
}
459
510
}
460
511
if let Some ( call) = item. protector {
461
512
if global. is_active ( call) {
462
- if let Some ( ( tag, _ ) ) = provoking_access {
513
+ if let Some ( ( tag, alloc_id , alloc_range , offset ) ) = provoking_access {
463
514
Err ( err_sb_ub (
464
515
format ! (
465
516
"not granting access to tag {:?} because incompatible item is protected: {:?}" ,
466
517
tag, item
467
518
) ,
468
519
None ,
469
- None ,
520
+ global. get_stack_history (
521
+ tag,
522
+ alloc_id,
523
+ alloc_range,
524
+ offset,
525
+ Some ( item. tag ) ,
526
+ ) ,
470
527
) ) ?
471
528
} else {
472
529
Err ( err_sb_ub (
@@ -506,7 +563,7 @@ impl<'tcx> Stack {
506
563
let first_incompatible_idx = self . find_first_write_incompatible ( granting_idx) ;
507
564
for item in self . borrows . drain ( first_incompatible_idx..) . rev ( ) {
508
565
trace ! ( "access: popping item {:?}" , item) ;
509
- Stack :: check_protector ( & item, Some ( ( tag, access ) ) , global) ?;
566
+ Stack :: check_protector ( & item, Some ( ( tag, alloc_id , alloc_range , offset ) ) , global) ?;
510
567
global. add_invalidation ( item. tag , alloc_id, alloc_range) ;
511
568
}
512
569
} else {
@@ -522,7 +579,11 @@ impl<'tcx> Stack {
522
579
let item = & mut self . borrows [ idx] ;
523
580
if item. perm == Permission :: Unique {
524
581
trace ! ( "access: disabling item {:?}" , item) ;
525
- Stack :: check_protector ( item, Some ( ( tag, access) ) , global) ?;
582
+ Stack :: check_protector (
583
+ item,
584
+ Some ( ( tag, alloc_id, alloc_range, offset) ) ,
585
+ global,
586
+ ) ?;
526
587
item. perm = Permission :: Disabled ;
527
588
global. add_invalidation ( item. tag , alloc_id, alloc_range) ;
528
589
}
@@ -548,7 +609,7 @@ impl<'tcx> Stack {
548
609
tag, alloc_id,
549
610
) ,
550
611
None ,
551
- global. get_stack_history ( tag, alloc_id, alloc_range, offset) ,
612
+ global. get_stack_history ( tag, alloc_id, alloc_range, offset, None ) ,
552
613
)
553
614
} ) ?;
554
615
@@ -640,7 +701,7 @@ impl<'tcx> Stack {
640
701
err_sb_ub (
641
702
format ! ( "{}{}" , action, self . error_cause( derived_from) ) ,
642
703
Some ( Self :: operation_summary ( "a reborrow" , alloc_id, alloc_range) ) ,
643
- global. get_stack_history ( derived_from, alloc_id, alloc_range, error_offset) ,
704
+ global. get_stack_history ( derived_from, alloc_id, alloc_range, error_offset, None ) ,
644
705
)
645
706
}
646
707
@@ -664,7 +725,7 @@ impl<'tcx> Stack {
664
725
err_sb_ub (
665
726
format ! ( "{}{}" , action, self . error_cause( tag) ) ,
666
727
Some ( Self :: operation_summary ( "an access" , alloc_id, alloc_range) ) ,
667
- global. get_stack_history ( tag, alloc_id, alloc_range, error_offset) ,
728
+ global. get_stack_history ( tag, alloc_id, alloc_range, error_offset, None ) ,
668
729
)
669
730
}
670
731
@@ -768,7 +829,7 @@ impl Stacks {
768
829
( tag, Permission :: SharedReadWrite )
769
830
}
770
831
} ;
771
- extra. add_creation ( base_tag, id, alloc_range ( Size :: ZERO , size) ) ;
832
+ extra. add_creation ( None , base_tag, id, alloc_range ( Size :: ZERO , size) ) ;
772
833
Stacks :: new ( size, perm, base_tag)
773
834
}
774
835
@@ -857,6 +918,17 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
857
918
let ( alloc_id, base_offset, ptr) = this. memory . ptr_get_alloc ( place. ptr ) ?;
858
919
let orig_tag = ptr. provenance . sb ;
859
920
921
+ let mem_extra = this. memory . extra . stacked_borrows . as_mut ( ) . unwrap ( ) . get_mut ( ) ;
922
+ mem_extra. add_creation (
923
+ Some ( orig_tag) ,
924
+ new_tag,
925
+ alloc_id,
926
+ alloc_range ( base_offset, base_offset + size) ,
927
+ ) ;
928
+ if protect {
929
+ mem_extra. add_protector ( orig_tag, new_tag, alloc_id) ;
930
+ }
931
+
860
932
// Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
861
933
let ( alloc_size, _) =
862
934
this. memory . get_size_and_align ( alloc_id, AllocCheck :: Dereferenceable ) ?;
@@ -959,9 +1031,6 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
959
1031
None => return Ok ( * val) ,
960
1032
} ;
961
1033
962
- // May return Err for retags of size 0
963
- let alloc = this. memory . ptr_get_alloc ( place. ptr ) ;
964
-
965
1034
// Compute new borrow.
966
1035
let mem_extra = this. memory . extra . stacked_borrows . as_mut ( ) . unwrap ( ) . get_mut ( ) ;
967
1036
let new_tag = match kind {
@@ -971,10 +1040,6 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
971
1040
_ => SbTag :: Tagged ( mem_extra. new_ptr ( ) ) ,
972
1041
} ;
973
1042
974
- if let Ok ( ( alloc_id, base_offset, _ptr) ) = alloc {
975
- mem_extra. add_creation ( new_tag, alloc_id, alloc_range ( base_offset, base_offset + size) ) ;
976
- }
977
-
978
1043
// Reborrow.
979
1044
this. reborrow ( & place, size, kind, new_tag, protect) ?;
980
1045
0 commit comments