25
25
#include " sanitizer_common/sanitizer_array_ref.h"
26
26
#include " sanitizer_common/sanitizer_common.h"
27
27
#include " sanitizer_common/sanitizer_flags.h"
28
+ #include " sanitizer_common/sanitizer_internal_defs.h"
28
29
#include " sanitizer_common/sanitizer_mutex.h"
29
30
#include " sanitizer_common/sanitizer_report_decorator.h"
30
31
#include " sanitizer_common/sanitizer_stackdepot.h"
@@ -321,56 +322,61 @@ static uptr GetGlobalSizeFromDescriptor(uptr ptr) {
321
322
322
323
void ReportStats () {}
323
324
324
- static void PrintTagInfoAroundAddr (tag_t *tag_ptr, uptr num_rows,
325
- void (*print_tag)(InternalScopedString &s,
326
- tag_t *tag)) {
325
+ template <typename PrintTag>
326
+ static void PrintTagInfoAroundAddr (uptr addr, uptr num_rows,
327
+ InternalScopedString &s,
328
+ PrintTag print_tag) {
327
329
const uptr row_len = 16 ; // better be power of two.
328
- tag_t *center_row_beg = reinterpret_cast <tag_t *>(
329
- RoundDownTo (reinterpret_cast <uptr>(tag_ptr), row_len));
330
- tag_t *beg_row = center_row_beg - row_len * (num_rows / 2 );
331
- tag_t *end_row = center_row_beg + row_len * ((num_rows + 1 ) / 2 );
332
- InternalScopedString s;
333
- for (tag_t *row = beg_row; row < end_row; row += row_len) {
330
+ uptr center_row_beg = RoundDownTo (addr, row_len);
331
+ uptr beg_row = center_row_beg - row_len * (num_rows / 2 );
332
+ uptr end_row = center_row_beg + row_len * ((num_rows + 1 ) / 2 );
333
+ for (uptr row = beg_row; row < end_row; row += row_len) {
334
334
s.Append (row == center_row_beg ? " =>" : " " );
335
- s.AppendF (" %p:" , (void *)ShadowToMem (reinterpret_cast <uptr>( row) ));
335
+ s.AppendF (" %p:" , (void *)ShadowToMem (row));
336
336
for (uptr i = 0 ; i < row_len; i++) {
337
- s.Append (row + i == tag_ptr ? " [" : " " );
338
- print_tag (s, & row[i] );
339
- s.Append (row + i == tag_ptr ? " ]" : " " );
337
+ s.Append (row + i == addr ? " [" : " " );
338
+ print_tag (s, row + i );
339
+ s.Append (row + i == addr ? " ]" : " " );
340
340
}
341
341
s.AppendF (" \n " );
342
342
}
343
- Printf (" %s" , s.data ());
344
343
}
345
344
346
- static void PrintTagsAroundAddr (tag_t *tag_ptr) {
347
- Printf (
345
+ template <typename GetTag, typename GetShortTag>
346
+ static void PrintTagsAroundAddr (uptr addr, GetTag get_tag,
347
+ GetShortTag get_short_tag) {
348
+ InternalScopedString s;
349
+ addr = MemToShadow (addr);
350
+ s.AppendF (
348
351
" Memory tags around the buggy address (one tag corresponds to %zd "
349
352
" bytes):\n " ,
350
353
kShadowAlignment );
351
- PrintTagInfoAroundAddr (tag_ptr, 17 , [](InternalScopedString &s, tag_t *tag) {
352
- s.AppendF (" %02x" , *tag);
353
- });
354
+ PrintTagInfoAroundAddr (addr, 17 , s,
355
+ [&](InternalScopedString &s, uptr tag_addr) {
356
+ tag_t tag = get_tag (tag_addr);
357
+ s.AppendF (" %02x" , tag);
358
+ });
354
359
355
- Printf (
360
+ s. AppendF (
356
361
" Tags for short granules around the buggy address (one tag corresponds "
357
362
" to %zd bytes):\n " ,
358
363
kShadowAlignment );
359
- PrintTagInfoAroundAddr (tag_ptr , 3 , [](InternalScopedString &s, tag_t *tag) {
360
- uptr granule_addr = ShadowToMem ( reinterpret_cast < uptr>(tag));
361
- if (*tag >= 1 && * tag <= kShadowAlignment &&
362
- IsAccessibleMemoryRange (granule_addr, kShadowAlignment ) ) {
363
- s. AppendF ( " %02x " ,
364
- * reinterpret_cast <u8 *>(granule_addr + kShadowAlignment - 1 ) );
365
- } else {
366
- s.AppendF (" .." );
367
- }
368
- });
369
- Printf (
364
+ PrintTagInfoAroundAddr (addr , 3 , s,
365
+ [&](InternalScopedString &s, uptr tag_addr) {
366
+ tag_t tag = get_tag (tag_addr);
367
+ if (tag >= 1 && tag <= kShadowAlignment ) {
368
+ tag_t short_tag = get_short_tag (tag_addr);
369
+ s. AppendF ( " %02x " , short_tag );
370
+ } else {
371
+ s.AppendF (" .." );
372
+ }
373
+ });
374
+ s. AppendF (
370
375
" See "
371
376
" https://clang.llvm.org/docs/"
372
377
" HardwareAssistedAddressSanitizerDesign.html#short-granules for a "
373
378
" description of short granule tags\n " );
379
+ Printf (" %s" , s.data ());
374
380
}
375
381
376
382
static uptr GetTopPc (const StackTrace *stack) {
@@ -390,7 +396,8 @@ class BaseReport {
390
396
ptr_tag(GetTagFromPointer(tagged_addr)),
391
397
heap(CopyHeapChunk()),
392
398
allocations(CopyAllocations()),
393
- candidate(FindBufferOverflowCandidate()) {}
399
+ candidate(FindBufferOverflowCandidate()),
400
+ shadow(CopyShadow()) {}
394
401
395
402
protected:
396
403
struct OverflowCandidate {
@@ -428,6 +435,15 @@ class BaseReport {
428
435
bool is_allocated = false ;
429
436
};
430
437
438
+ struct Shadow {
439
+ uptr addr = 0 ;
440
+ tag_t tags[512 ] = {};
441
+ tag_t short_tags[ARRAY_SIZE(tags)] = {};
442
+ };
443
+
444
+ Shadow CopyShadow () const ;
445
+ tag_t GetTagCopy (uptr addr) const ;
446
+ tag_t GetShortTagCopy (uptr addr) const ;
431
447
HeapChunk CopyHeapChunk () const ;
432
448
Allocations CopyAllocations ();
433
449
OverflowCandidate FindBufferOverflowCandidate () const ;
@@ -447,8 +463,49 @@ class BaseReport {
447
463
const HeapChunk heap;
448
464
const Allocations allocations;
449
465
const OverflowCandidate candidate;
466
+
467
+ const Shadow shadow ;
450
468
};
451
469
470
+ BaseReport::Shadow BaseReport::CopyShadow () const {
471
+ Shadow result;
472
+ if (!MemIsApp (untagged_addr))
473
+ return result;
474
+
475
+ result.addr = MemToShadow (untagged_addr) - ARRAY_SIZE (result.tags ) / 2 ;
476
+ for (uptr i = 0 ; i < ARRAY_SIZE (result.tags ); ++i) {
477
+ uptr tag_addr = result.addr + i;
478
+ if (!MemIsShadow (tag_addr))
479
+ continue ;
480
+ result.tags [i] = *reinterpret_cast <tag_t *>(tag_addr);
481
+ uptr granule_addr = ShadowToMem (tag_addr);
482
+ if (1 <= result.tags [i] && result.tags [i] <= kShadowAlignment &&
483
+ IsAccessibleMemoryRange (granule_addr, kShadowAlignment )) {
484
+ result.short_tags [i] =
485
+ *reinterpret_cast <tag_t *>(granule_addr + kShadowAlignment - 1 );
486
+ }
487
+ }
488
+ return result;
489
+ }
490
+
491
+ tag_t BaseReport::GetTagCopy (uptr addr) const {
492
+ if (addr < shadow .addr )
493
+ return 0 ;
494
+ uptr idx = addr - shadow .addr ;
495
+ if (idx >= ARRAY_SIZE (shadow .tags ))
496
+ return 0 ;
497
+ return shadow .tags [idx];
498
+ }
499
+
500
+ tag_t BaseReport::GetShortTagCopy (uptr addr) const {
501
+ if (addr < shadow .addr )
502
+ return 0 ;
503
+ uptr idx = addr - shadow .addr ;
504
+ if (idx >= ARRAY_SIZE (shadow .short_tags ))
505
+ return 0 ;
506
+ return shadow .short_tags [idx];
507
+ }
508
+
452
509
BaseReport::HeapChunk BaseReport::CopyHeapChunk () const {
453
510
HeapChunk result = {};
454
511
if (MemIsShadow (untagged_addr))
@@ -721,15 +778,6 @@ class InvalidFreeReport : public BaseReport {
721
778
};
722
779
723
780
InvalidFreeReport::~InvalidFreeReport () {
724
- tag_t *tag_ptr = nullptr ;
725
- tag_t mem_tag = 0 ;
726
- if (MemIsApp (untagged_addr)) {
727
- tag_ptr = reinterpret_cast <tag_t *>(MemToShadow (untagged_addr));
728
- if (MemIsShadow (reinterpret_cast <uptr>(tag_ptr)))
729
- mem_tag = *tag_ptr;
730
- else
731
- tag_ptr = nullptr ;
732
- }
733
781
Decorator d;
734
782
Printf (" %s" , d.Error ());
735
783
uptr pc = GetTopPc (stack);
@@ -743,16 +791,19 @@ InvalidFreeReport::~InvalidFreeReport() {
743
791
SanitizerToolName, bug_type, untagged_addr, pc);
744
792
}
745
793
Printf (" %s" , d.Access ());
746
- if (tag_ptr )
747
- Printf (" tags: %02x/%02x (ptr/mem)\n " , ptr_tag, mem_tag );
794
+ if (shadow . addr )
795
+ Printf (" tags: %02x/%02x (ptr/mem)\n " , ptr_tag, GetTagCopy (untagged_addr) );
748
796
Printf (" %s" , d.Default ());
749
797
750
798
stack->Print ();
751
799
752
800
PrintAddressDescription ();
753
801
754
- if (tag_ptr)
755
- PrintTagsAroundAddr (tag_ptr);
802
+ if (shadow .addr ) {
803
+ PrintTagsAroundAddr (
804
+ untagged_addr, [&](uptr addr) { return GetTagCopy (addr); },
805
+ [&](uptr addr) { return GetShortTagCopy (addr); });
806
+ }
756
807
757
808
MaybePrintAndroidHelpUrl ();
758
809
ReportErrorSummary (bug_type, stack);
@@ -834,8 +885,9 @@ TailOverwrittenReport::~TailOverwrittenReport() {
834
885
Printf (" %s" , s.data ());
835
886
GetCurrentThread ()->Announce ();
836
887
837
- tag_t *tag_ptr = reinterpret_cast <tag_t *>(MemToShadow (untagged_addr));
838
- PrintTagsAroundAddr (tag_ptr);
888
+ PrintTagsAroundAddr (
889
+ untagged_addr, [&](uptr addr) { return GetTagCopy (addr); },
890
+ [&](uptr addr) { return GetShortTagCopy (addr); });
839
891
840
892
MaybePrintAndroidHelpUrl ();
841
893
ReportErrorSummary (bug_type, stack);
@@ -912,7 +964,9 @@ TagMismatchReport::~TagMismatchReport() {
912
964
PrintAddressDescription ();
913
965
t->Announce ();
914
966
915
- PrintTagsAroundAddr (tag_ptr);
967
+ PrintTagsAroundAddr (
968
+ untagged_addr + offset, [&](uptr addr) { return GetTagCopy (addr); },
969
+ [&](uptr addr) { return GetShortTagCopy (addr); });
916
970
917
971
if (registers_frame)
918
972
ReportRegisters (registers_frame, pc);
0 commit comments