@@ -391,7 +391,7 @@ class BaseReport {
391391 return ;
392392
393393 CopyHeapChunk ();
394- CopyStackAllocations ();
394+ CopyAllocations ();
395395 candidate = FindBufferOverflowCandidate ();
396396 }
397397
@@ -411,7 +411,7 @@ class BaseReport {
411411 };
412412
413413 void CopyHeapChunk ();
414- void CopyStackAllocations ();
414+ void CopyAllocations ();
415415 OverflowCandidate FindBufferOverflowCandidate () const ;
416416 void PrintAddressDescription () const ;
417417 void PrintHeapOrGlobalCandidate () const ;
@@ -434,6 +434,15 @@ class BaseReport {
434434 } heap;
435435
436436 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 ];
437446};
438447
439448void BaseReport::CopyHeapChunk () {
@@ -446,12 +455,28 @@ void BaseReport::CopyHeapChunk() {
446455 }
447456}
448457
449- void BaseReport::CopyStackAllocations () {
458+ void BaseReport::CopyAllocations () {
450459 hwasanThreadList ().VisitAllLiveThreads ([&](Thread *t) {
451460 if (stack_allocations_count < ARRAY_SIZE (stack_allocations) &&
452461 t->AddrIsInStack (untagged_addr)) {
453462 stack_allocations[stack_allocations_count++].CopyFrom (t);
454463 }
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+ }
455480 });
456481}
457482
@@ -616,42 +641,39 @@ void BaseReport::PrintAddressDescription() const {
616641 num_descriptions_printed++;
617642 }
618643
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+ }
655677
656678 if (candidate.untagged_addr && num_descriptions_printed == 0 ) {
657679 PrintHeapOrGlobalCandidate ();
0 commit comments