@@ -387,14 +387,10 @@ class BaseReport {
387
387
tagged_addr(tagged_addr),
388
388
access_size(access_size),
389
389
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()) {}
398
394
399
395
protected:
400
396
struct OverflowCandidate {
@@ -411,66 +407,80 @@ class BaseReport {
411
407
} heap;
412
408
};
413
409
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 ();
416
432
OverflowCandidate FindBufferOverflowCandidate () const ;
417
433
void PrintAddressDescription () const ;
418
434
void PrintHeapOrGlobalCandidate () const ;
419
435
436
+ SavedStackAllocations stack_allocations_storage[16 ];
437
+ HeapAllocation heap_allocations_storage[256 ];
438
+
420
439
const ScopedReport scoped_report;
421
440
const StackTrace *stack = nullptr ;
422
441
const uptr tagged_addr = 0 ;
423
442
const uptr access_size = 0 ;
424
443
const uptr untagged_addr = 0 ;
425
444
const tag_t ptr_tag = 0 ;
426
445
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;
447
449
};
448
450
449
- void BaseReport::CopyHeapChunk () {
451
+ BaseReport::HeapChunk BaseReport::CopyHeapChunk () const {
452
+ HeapChunk result = {};
453
+ if (MemIsShadow (untagged_addr))
454
+ return result;
450
455
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 ();
456
461
}
462
+ return result;
457
463
}
458
464
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 ;
460
470
hwasanThreadList ().VisitAllLiveThreads ([&](Thread *t) {
461
- if (stack_allocations_count < ARRAY_SIZE (stack_allocations ) &&
471
+ if (stack_allocations_count < ARRAY_SIZE (stack_allocations_storage ) &&
462
472
t->AddrIsInStack (untagged_addr)) {
463
- stack_allocations [stack_allocations_count++].CopyFrom (t);
473
+ stack_allocations_storage [stack_allocations_count++].CopyFrom (t);
464
474
}
465
475
466
- if (heap_allocations_count < ARRAY_SIZE (heap_allocations )) {
476
+ if (heap_allocations_count < ARRAY_SIZE (heap_allocations_storage )) {
467
477
// Scan all threads' ring buffers to find if it's a heap-use-after-free.
468
478
HeapAllocationRecord har;
469
479
uptr ring_index, num_matching_addrs, num_matching_addrs_4b;
470
480
if (FindHeapAllocation (t->heap_allocations (), tagged_addr, &har,
471
481
&ring_index, &num_matching_addrs,
472
482
&num_matching_addrs_4b)) {
473
- auto &ha = heap_allocations [heap_allocations_count++];
483
+ auto &ha = heap_allocations_storage [heap_allocations_count++];
474
484
ha.har = har;
475
485
ha.ring_index = ring_index;
476
486
ha.num_matching_addrs = num_matching_addrs;
@@ -479,9 +489,15 @@ void BaseReport::CopyAllocations() {
479
489
}
480
490
}
481
491
});
492
+
493
+ return {{stack_allocations_storage, stack_allocations_count},
494
+ {heap_allocations_storage, heap_allocations_count}};
482
495
}
483
496
484
497
BaseReport::OverflowCandidate BaseReport::FindBufferOverflowCandidate () const {
498
+ OverflowCandidate result = {};
499
+ if (MemIsShadow (untagged_addr))
500
+ return result;
485
501
// Check if this looks like a heap buffer overflow by scanning
486
502
// the shadow left and right and looking for the first adjacent
487
503
// object with a different memory tag. If that tag matches ptr_tag,
@@ -503,7 +519,6 @@ BaseReport::OverflowCandidate BaseReport::FindBufferOverflowCandidate() const {
503
519
++right;
504
520
}
505
521
506
- OverflowCandidate result = {};
507
522
constexpr auto kCloseCandidateDistance = 1 ;
508
523
result.is_close = candidate_distance <= kCloseCandidateDistance ;
509
524
@@ -621,29 +636,27 @@ void BaseReport::PrintAddressDescription() const {
621
636
622
637
// Check stack first. If the address is on the stack of a live thread, we
623
638
// 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 ) {
626
640
// TODO(fmayer): figure out how to distinguish use-after-return and
627
641
// stack-buffer-overflow.
628
642
Printf (" %s" , d.Error ());
629
643
Printf (" \n Cause: stack tag-mismatch\n " );
630
644
Printf (" %s" , d.Location ());
631
645
Printf (" Address %p is located in stack of thread T%zd\n " , untagged_addr,
632
- allocations .thread_id ());
646
+ sa .thread_id ());
633
647
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);
636
650
num_descriptions_printed++;
637
651
}
638
652
639
- if (!stack_allocations_count && candidate.untagged_addr &&
653
+ if (allocations. stack . empty () && candidate.untagged_addr &&
640
654
candidate.is_close ) {
641
655
PrintHeapOrGlobalCandidate ();
642
656
num_descriptions_printed++;
643
657
}
644
658
645
- for (uptr i = 0 ; i < heap_allocations_count; ++i) {
646
- const auto &ha = heap_allocations[i];
659
+ for (const auto &ha : allocations.heap ) {
647
660
const HeapAllocationRecord har = ha.har ;
648
661
649
662
Printf (" %s" , d.Error ());
0 commit comments