@@ -387,14 +387,10 @@ class BaseReport {
387387 tagged_addr(tagged_addr),
388388 access_size(access_size),
389389 untagged_addr(UntagAddr(tagged_addr)),
390- ptr_tag(GetTagFromPointer(tagged_addr)) {
391- if (MemIsShadow (untagged_addr))
392- return ;
393-
394- CopyHeapChunk ();
395- CopyAllocations ();
396- candidate = FindBufferOverflowCandidate ();
397- }
390+ ptr_tag(GetTagFromPointer(tagged_addr)),
391+ heap(CopyHeapChunk()),
392+ allocations(CopyAllocations()),
393+ candidate(FindBufferOverflowCandidate()) {}
398394
399395 protected:
400396 struct OverflowCandidate {
@@ -411,66 +407,80 @@ class BaseReport {
411407 } heap;
412408 };
413409
414- void CopyHeapChunk ();
415- void CopyAllocations ();
410+ struct HeapAllocation {
411+ HeapAllocationRecord har = {};
412+ uptr ring_index = 0 ;
413+ uptr num_matching_addrs = 0 ;
414+ uptr num_matching_addrs_4b = 0 ;
415+ u32 free_thread_id = 0 ;
416+ };
417+
418+ struct Allocations {
419+ ArrayRef<SavedStackAllocations> stack;
420+ ArrayRef<HeapAllocation> heap;
421+ };
422+
423+ struct HeapChunk {
424+ uptr begin = 0 ;
425+ uptr size = 0 ;
426+ bool from_small_heap = false ;
427+ bool is_allocated = false ;
428+ };
429+
430+ HeapChunk CopyHeapChunk () const ;
431+ Allocations CopyAllocations ();
416432 OverflowCandidate FindBufferOverflowCandidate () const ;
417433 void PrintAddressDescription () const ;
418434 void PrintHeapOrGlobalCandidate () const ;
419435
436+ SavedStackAllocations stack_allocations_storage[16 ];
437+ HeapAllocation heap_allocations_storage[256 ];
438+
420439 const ScopedReport scoped_report;
421440 const StackTrace *stack = nullptr ;
422441 const uptr tagged_addr = 0 ;
423442 const uptr access_size = 0 ;
424443 const uptr untagged_addr = 0 ;
425444 const tag_t ptr_tag = 0 ;
426445
427- uptr stack_allocations_count = 0 ;
428- SavedStackAllocations stack_allocations[16 ];
429-
430- struct {
431- uptr begin = 0 ;
432- uptr size = 0 ;
433- bool from_small_heap = false ;
434- bool is_allocated = false ;
435- } heap;
436-
437- OverflowCandidate candidate;
438-
439- uptr heap_allocations_count = 0 ;
440- struct {
441- HeapAllocationRecord har = {};
442- uptr ring_index = 0 ;
443- uptr num_matching_addrs = 0 ;
444- uptr num_matching_addrs_4b = 0 ;
445- u32 free_thread_id = 0 ;
446- } heap_allocations[256 ];
446+ const HeapChunk heap;
447+ const Allocations allocations;
448+ const OverflowCandidate candidate;
447449};
448450
449- void BaseReport::CopyHeapChunk () {
451+ BaseReport::HeapChunk BaseReport::CopyHeapChunk () const {
452+ HeapChunk result = {};
453+ if (MemIsShadow (untagged_addr))
454+ return result;
450455 HwasanChunkView chunk = FindHeapChunkByAddress (untagged_addr);
451- heap .begin = chunk.Beg ();
452- if (heap .begin ) {
453- heap .size = chunk.ActualSize ();
454- heap .from_small_heap = chunk.FromSmallHeap ();
455- heap .is_allocated = chunk.IsAllocated ();
456+ result .begin = chunk.Beg ();
457+ if (result .begin ) {
458+ result .size = chunk.ActualSize ();
459+ result .from_small_heap = chunk.FromSmallHeap ();
460+ result .is_allocated = chunk.IsAllocated ();
456461 }
462+ return result;
457463}
458464
459- void BaseReport::CopyAllocations () {
465+ BaseReport::Allocations BaseReport::CopyAllocations () {
466+ if (MemIsShadow (untagged_addr))
467+ return {};
468+ uptr stack_allocations_count = 0 ;
469+ uptr heap_allocations_count = 0 ;
460470 hwasanThreadList ().VisitAllLiveThreads ([&](Thread *t) {
461- if (stack_allocations_count < ARRAY_SIZE (stack_allocations ) &&
471+ if (stack_allocations_count < ARRAY_SIZE (stack_allocations_storage ) &&
462472 t->AddrIsInStack (untagged_addr)) {
463- stack_allocations [stack_allocations_count++].CopyFrom (t);
473+ stack_allocations_storage [stack_allocations_count++].CopyFrom (t);
464474 }
465475
466- if (heap_allocations_count < ARRAY_SIZE (heap_allocations )) {
476+ if (heap_allocations_count < ARRAY_SIZE (heap_allocations_storage )) {
467477 // Scan all threads' ring buffers to find if it's a heap-use-after-free.
468478 HeapAllocationRecord har;
469479 uptr ring_index, num_matching_addrs, num_matching_addrs_4b;
470480 if (FindHeapAllocation (t->heap_allocations (), tagged_addr, &har,
471481 &ring_index, &num_matching_addrs,
472482 &num_matching_addrs_4b)) {
473- auto &ha = heap_allocations [heap_allocations_count++];
483+ auto &ha = heap_allocations_storage [heap_allocations_count++];
474484 ha.har = har;
475485 ha.ring_index = ring_index;
476486 ha.num_matching_addrs = num_matching_addrs;
@@ -479,9 +489,15 @@ void BaseReport::CopyAllocations() {
479489 }
480490 }
481491 });
492+
493+ return {{stack_allocations_storage, stack_allocations_count},
494+ {heap_allocations_storage, heap_allocations_count}};
482495}
483496
484497BaseReport::OverflowCandidate BaseReport::FindBufferOverflowCandidate () const {
498+ OverflowCandidate result = {};
499+ if (MemIsShadow (untagged_addr))
500+ return result;
485501 // Check if this looks like a heap buffer overflow by scanning
486502 // the shadow left and right and looking for the first adjacent
487503 // object with a different memory tag. If that tag matches ptr_tag,
@@ -503,7 +519,6 @@ BaseReport::OverflowCandidate BaseReport::FindBufferOverflowCandidate() const {
503519 ++right;
504520 }
505521
506- OverflowCandidate result = {};
507522 constexpr auto kCloseCandidateDistance = 1 ;
508523 result.is_close = candidate_distance <= kCloseCandidateDistance ;
509524
@@ -621,29 +636,27 @@ void BaseReport::PrintAddressDescription() const {
621636
622637 // Check stack first. If the address is on the stack of a live thread, we
623638 // know it cannot be a heap / global overflow.
624- for (uptr i = 0 ; i < stack_allocations_count; ++i) {
625- const auto &allocations = stack_allocations[i];
639+ for (const auto &sa : allocations.stack ) {
626640 // TODO(fmayer): figure out how to distinguish use-after-return and
627641 // stack-buffer-overflow.
628642 Printf (" %s" , d.Error ());
629643 Printf (" \n Cause: stack tag-mismatch\n " );
630644 Printf (" %s" , d.Location ());
631645 Printf (" Address %p is located in stack of thread T%zd\n " , untagged_addr,
632- allocations .thread_id ());
646+ sa .thread_id ());
633647 Printf (" %s" , d.Default ());
634- announce_by_id (allocations .thread_id ());
635- PrintStackAllocations (allocations .get (), ptr_tag, untagged_addr);
648+ announce_by_id (sa .thread_id ());
649+ PrintStackAllocations (sa .get (), ptr_tag, untagged_addr);
636650 num_descriptions_printed++;
637651 }
638652
639- if (!stack_allocations_count && candidate.untagged_addr &&
653+ if (allocations. stack . empty () && candidate.untagged_addr &&
640654 candidate.is_close ) {
641655 PrintHeapOrGlobalCandidate ();
642656 num_descriptions_printed++;
643657 }
644658
645- for (uptr i = 0 ; i < heap_allocations_count; ++i) {
646- const auto &ha = heap_allocations[i];
659+ for (const auto &ha : allocations.heap ) {
647660 const HeapAllocationRecord har = ha.har ;
648661
649662 Printf (" %s" , d.Error ());
0 commit comments