@@ -391,7 +391,7 @@ class BaseReport {
391
391
return ;
392
392
393
393
CopyHeapChunk ();
394
- CopyStackAllocations ();
394
+ CopyAllocations ();
395
395
candidate = FindBufferOverflowCandidate ();
396
396
}
397
397
@@ -411,7 +411,7 @@ class BaseReport {
411
411
};
412
412
413
413
void CopyHeapChunk ();
414
- void CopyStackAllocations ();
414
+ void CopyAllocations ();
415
415
OverflowCandidate FindBufferOverflowCandidate () const ;
416
416
void PrintAddressDescription () const ;
417
417
void PrintHeapOrGlobalCandidate () const ;
@@ -434,6 +434,15 @@ class BaseReport {
434
434
} heap;
435
435
436
436
OverflowCandidate candidate;
437
+
438
+ uptr heap_allocations_count = 0 ;
439
+ struct {
440
+ HeapAllocationRecord har = {};
441
+ uptr ring_index = 0 ;
442
+ uptr num_matching_addrs = 0 ;
443
+ uptr num_matching_addrs_4b = 0 ;
444
+ u32 free_thread_id = 0 ;
445
+ } heap_allocations[256 ];
437
446
};
438
447
439
448
void BaseReport::CopyHeapChunk () {
@@ -446,12 +455,28 @@ void BaseReport::CopyHeapChunk() {
446
455
}
447
456
}
448
457
449
- void BaseReport::CopyStackAllocations () {
458
+ void BaseReport::CopyAllocations () {
450
459
hwasanThreadList ().VisitAllLiveThreads ([&](Thread *t) {
451
460
if (stack_allocations_count < ARRAY_SIZE (stack_allocations) &&
452
461
t->AddrIsInStack (untagged_addr)) {
453
462
stack_allocations[stack_allocations_count++].CopyFrom (t);
454
463
}
464
+
465
+ if (heap_allocations_count < ARRAY_SIZE (heap_allocations)) {
466
+ // Scan all threads' ring buffers to find if it's a heap-use-after-free.
467
+ HeapAllocationRecord har;
468
+ uptr ring_index, num_matching_addrs, num_matching_addrs_4b;
469
+ if (FindHeapAllocation (t->heap_allocations (), tagged_addr, &har,
470
+ &ring_index, &num_matching_addrs,
471
+ &num_matching_addrs_4b)) {
472
+ auto &ha = heap_allocations[heap_allocations_count++];
473
+ ha.har = har;
474
+ ha.ring_index = ring_index;
475
+ ha.num_matching_addrs = num_matching_addrs;
476
+ ha.num_matching_addrs_4b = num_matching_addrs_4b;
477
+ ha.free_thread_id = t->unique_id ();
478
+ }
479
+ }
455
480
});
456
481
}
457
482
@@ -616,42 +641,39 @@ void BaseReport::PrintAddressDescription() const {
616
641
num_descriptions_printed++;
617
642
}
618
643
619
- hwasanThreadList ().VisitAllLiveThreads ([&](Thread *t) {
620
- // Scan all threads' ring buffers to find if it's a heap-use-after-free.
621
- HeapAllocationRecord har;
622
- uptr ring_index, num_matching_addrs, num_matching_addrs_4b;
623
- if (FindHeapAllocation (t->heap_allocations (), tagged_addr, &har,
624
- &ring_index, &num_matching_addrs,
625
- &num_matching_addrs_4b)) {
626
- Printf (" %s" , d.Error ());
627
- Printf (" \n Cause: use-after-free\n " );
628
- Printf (" %s" , d.Location ());
629
- Printf (" %p is located %zd bytes inside a %zd-byte region [%p,%p)\n " ,
630
- untagged_addr, untagged_addr - UntagAddr (har.tagged_addr ),
631
- har.requested_size , UntagAddr (har.tagged_addr ),
632
- UntagAddr (har.tagged_addr ) + har.requested_size );
633
- Printf (" %s" , d.Allocation ());
634
- Printf (" freed by thread T%u here:\n " , t->unique_id ());
635
- Printf (" %s" , d.Default ());
636
- GetStackTraceFromId (har.free_context_id ).Print ();
637
-
638
- Printf (" %s" , d.Allocation ());
639
- Printf (" previously allocated by thread T%u here:\n " , har.alloc_thread_id );
640
- Printf (" %s" , d.Default ());
641
- GetStackTraceFromId (har.alloc_context_id ).Print ();
642
-
643
- // Print a developer note: the index of this heap object
644
- // in the thread's deallocation ring buffer.
645
- Printf (" hwasan_dev_note_heap_rb_distance: %zd %zd\n " , ring_index + 1 ,
646
- flags ()->heap_history_size );
647
- Printf (" hwasan_dev_note_num_matching_addrs: %zd\n " , num_matching_addrs);
648
- Printf (" hwasan_dev_note_num_matching_addrs_4b: %zd\n " ,
649
- num_matching_addrs_4b);
650
-
651
- t->Announce ();
652
- num_descriptions_printed++;
653
- }
654
- });
644
+ for (uptr i = 0 ; i < heap_allocations_count; ++i) {
645
+ const auto &ha = heap_allocations[i];
646
+ const HeapAllocationRecord har = ha.har ;
647
+
648
+ Printf (" %s" , d.Error ());
649
+ Printf (" \n Cause: use-after-free\n " );
650
+ Printf (" %s" , d.Location ());
651
+ Printf (" %p is located %zd bytes inside a %zd-byte region [%p,%p)\n " ,
652
+ untagged_addr, untagged_addr - UntagAddr (har.tagged_addr ),
653
+ har.requested_size , UntagAddr (har.tagged_addr ),
654
+ UntagAddr (har.tagged_addr ) + har.requested_size );
655
+ Printf (" %s" , d.Allocation ());
656
+ Printf (" freed by thread T%u here:\n " , ha.free_thread_id );
657
+ Printf (" %s" , d.Default ());
658
+ GetStackTraceFromId (har.free_context_id ).Print ();
659
+
660
+ Printf (" %s" , d.Allocation ());
661
+ Printf (" previously allocated by thread T%u here:\n " , har.alloc_thread_id );
662
+ Printf (" %s" , d.Default ());
663
+ GetStackTraceFromId (har.alloc_context_id ).Print ();
664
+
665
+ // Print a developer note: the index of this heap object
666
+ // in the thread's deallocation ring buffer.
667
+ Printf (" hwasan_dev_note_heap_rb_distance: %zd %zd\n " , ha.ring_index + 1 ,
668
+ flags ()->heap_history_size );
669
+ Printf (" hwasan_dev_note_num_matching_addrs: %zd\n " , ha.num_matching_addrs );
670
+ Printf (" hwasan_dev_note_num_matching_addrs_4b: %zd\n " ,
671
+ ha.num_matching_addrs_4b );
672
+
673
+ announce_by_id (ha.free_thread_id );
674
+ // TODO: announce_by_id(har.alloc_thread_id);
675
+ num_descriptions_printed++;
676
+ }
655
677
656
678
if (candidate.untagged_addr && num_descriptions_printed == 0 ) {
657
679
PrintHeapOrGlobalCandidate ();
0 commit comments