@@ -200,7 +200,7 @@ static bool FindHeapAllocation(HeapAllocationsRingBuffer *rb, uptr tagged_addr,
200
200
return false ;
201
201
}
202
202
203
- static void PrintStackAllocations (StackAllocationsRingBuffer *sa,
203
+ static void PrintStackAllocations (const StackAllocationsRingBuffer *sa,
204
204
tag_t addr_tag, uptr untagged_addr) {
205
205
uptr frames = Min ((uptr)flags ()->stack_history_size , sa->size ());
206
206
bool found_local = false ;
@@ -457,23 +457,31 @@ class BaseReport {
457
457
tagged_addr(tagged_addr),
458
458
access_size(access_size),
459
459
untagged_addr(UntagAddr(tagged_addr)),
460
- ptr_tag(GetTagFromPointer(tagged_addr)) {}
460
+ ptr_tag(GetTagFromPointer(tagged_addr)) {
461
+ hwasanThreadList ().VisitAllLiveThreads ([&](Thread *t) {
462
+ if (stack_allocations_count < ARRAY_SIZE (stack_allocations) &&
463
+ t->AddrIsInStack (untagged_addr)) {
464
+ stack_allocations[stack_allocations_count++].CopyFrom (t);
465
+ }
466
+ });
467
+ }
461
468
462
469
protected:
470
+ void PrintAddressDescription () const ;
471
+
463
472
ScopedReport scoped_report;
464
473
StackTrace *stack = nullptr ;
465
474
uptr tagged_addr = 0 ;
466
475
uptr access_size = 0 ;
467
476
uptr untagged_addr = 0 ;
468
477
tag_t ptr_tag = 0 ;
478
+ uptr stack_allocations_count = 0 ;
479
+ SavedStackAllocations stack_allocations[16 ];
469
480
};
470
481
471
- static void PrintAddressDescription (
472
- uptr tagged_addr, uptr access_size,
473
- StackAllocationsRingBuffer *current_stack_allocations) {
482
+ void BaseReport::PrintAddressDescription () const {
474
483
Decorator d;
475
484
int num_descriptions_printed = 0 ;
476
- uptr untagged_addr = UntagAddr (tagged_addr);
477
485
478
486
if (MemIsShadow (untagged_addr)) {
479
487
Printf (" %s%p is HWAsan shadow memory.\n %s" , d.Location (), untagged_addr,
@@ -495,48 +503,42 @@ static void PrintAddressDescription(
495
503
d.Default ());
496
504
}
497
505
498
- tag_t addr_tag = GetTagFromPointer (tagged_addr);
499
-
500
- bool on_stack = false ;
501
506
// Check stack first. If the address is on the stack of a live thread, we
502
507
// know it cannot be a heap / global overflow.
503
- hwasanThreadList ().VisitAllLiveThreads ([&](Thread *t) {
504
- if (t->AddrIsInStack (untagged_addr)) {
505
- on_stack = true ;
506
- // TODO(fmayer): figure out how to distinguish use-after-return and
507
- // stack-buffer-overflow.
508
- Printf (" %s" , d.Error ());
509
- Printf (" \n Cause: stack tag-mismatch\n " );
510
- Printf (" %s" , d.Location ());
511
- Printf (" Address %p is located in stack of thread T%zd\n " , untagged_addr,
512
- t->unique_id ());
513
- Printf (" %s" , d.Default ());
514
- t->Announce ();
508
+ for (uptr i = 0 ; i < stack_allocations_count; ++i) {
509
+ auto &allocations = stack_allocations[i];
510
+ // TODO(fmayer): figure out how to distinguish use-after-return and
511
+ // stack-buffer-overflow.
512
+ Printf (" %s" , d.Error ());
513
+ Printf (" \n Cause: stack tag-mismatch\n " );
514
+ Printf (" %s" , d.Location ());
515
+ Printf (" Address %p is located in stack of thread T%zd\n " , untagged_addr,
516
+ allocations.thread_id ());
517
+ Printf (" %s" , d.Default ());
518
+ hwasanThreadList ().VisitAllLiveThreads ([&](Thread *t) {
519
+ if (allocations.thread_id () == t->unique_id ())
520
+ t->Announce ();
521
+ });
515
522
516
- auto *sa = (t == GetCurrentThread () && current_stack_allocations)
517
- ? current_stack_allocations
518
- : t->stack_allocations ();
519
- PrintStackAllocations (sa, addr_tag, untagged_addr);
520
- num_descriptions_printed++;
521
- }
522
- });
523
+ PrintStackAllocations (allocations.get (), ptr_tag, untagged_addr);
524
+ num_descriptions_printed++;
525
+ }
523
526
524
527
// Check if this looks like a heap buffer overflow by scanning
525
528
// the shadow left and right and looking for the first adjacent
526
- // object with a different memory tag. If that tag matches addr_tag ,
529
+ // object with a different memory tag. If that tag matches ptr_tag ,
527
530
// check the allocator if it has a live chunk there.
528
531
tag_t *tag_ptr = reinterpret_cast <tag_t *>(MemToShadow (untagged_addr));
529
532
tag_t *candidate = nullptr , *left = tag_ptr, *right = tag_ptr;
530
533
uptr candidate_distance = 0 ;
531
534
for (; candidate_distance < 1000 ; candidate_distance++) {
532
- if (MemIsShadow (reinterpret_cast <uptr>(left)) &&
533
- TagsEqual (addr_tag, left)) {
535
+ if (MemIsShadow (reinterpret_cast <uptr>(left)) && TagsEqual (ptr_tag, left)) {
534
536
candidate = left;
535
537
break ;
536
538
}
537
539
--left;
538
540
if (MemIsShadow (reinterpret_cast <uptr>(right)) &&
539
- TagsEqual (addr_tag , right)) {
541
+ TagsEqual (ptr_tag , right)) {
540
542
candidate = right;
541
543
break ;
542
544
}
@@ -545,7 +547,8 @@ static void PrintAddressDescription(
545
547
546
548
constexpr auto kCloseCandidateDistance = 1 ;
547
549
548
- if (!on_stack && candidate && candidate_distance <= kCloseCandidateDistance ) {
550
+ if (!stack_allocations_count && candidate &&
551
+ candidate_distance <= kCloseCandidateDistance ) {
549
552
ShowHeapOrGlobalCandidate (untagged_addr, candidate, left, right);
550
553
num_descriptions_printed++;
551
554
}
@@ -645,7 +648,7 @@ InvalidFreeReport::~InvalidFreeReport() {
645
648
646
649
stack->Print ();
647
650
648
- PrintAddressDescription (tagged_addr, 0 , nullptr );
651
+ PrintAddressDescription ();
649
652
650
653
if (tag_ptr)
651
654
PrintTagsAroundAddr (tag_ptr);
@@ -754,8 +757,6 @@ class TagMismatchReport : public BaseReport {
754
757
};
755
758
756
759
TagMismatchReport::~TagMismatchReport () {
757
- SavedStackAllocations current_stack_allocations (GetCurrentThread ());
758
-
759
760
Decorator d;
760
761
// TODO: when possible, try to print heap-use-after-free, etc.
761
762
const char *bug_type = " tag-mismatch" ;
@@ -806,8 +807,7 @@ TagMismatchReport::~TagMismatchReport() {
806
807
807
808
stack->Print ();
808
809
809
- PrintAddressDescription (tagged_addr, access_size,
810
- current_stack_allocations.get ());
810
+ PrintAddressDescription ();
811
811
t->Announce ();
812
812
813
813
PrintTagsAroundAddr (tag_ptr);
0 commit comments