@@ -395,6 +395,7 @@ class BaseReport {
395395 access_size(access_size),
396396 untagged_addr(UntagAddr(tagged_addr)),
397397 ptr_tag(GetTagFromPointer(tagged_addr)),
398+ mismatch_offset(FindMismatchOffset()),
398399 heap(CopyHeapChunk()),
399400 allocations(CopyAllocations()),
400401 candidate(FindBufferOverflowCandidate()),
@@ -442,6 +443,7 @@ class BaseReport {
442443 tag_t short_tags[ARRAY_SIZE(tags)] = {};
443444 };
444445
446+ sptr FindMismatchOffset () const ;
445447 Shadow CopyShadow () const ;
446448 tag_t GetTagCopy (uptr addr) const ;
447449 tag_t GetShortTagCopy (uptr addr) const ;
@@ -461,6 +463,7 @@ class BaseReport {
461463 const uptr access_size = 0 ;
462464 const uptr untagged_addr = 0 ;
463465 const tag_t ptr_tag = 0 ;
466+ const sptr mismatch_offset = 0 ;
464467
465468 const HeapChunk heap;
466469 const Allocations allocations;
@@ -469,6 +472,37 @@ class BaseReport {
469472 const Shadow shadow;
470473};
471474
475+ sptr BaseReport::FindMismatchOffset () const {
476+ if (!access_size)
477+ return 0 ;
478+ sptr offset =
479+ __hwasan_test_shadow (reinterpret_cast <void *>(tagged_addr), access_size);
480+ CHECK_GE (offset, 0 );
481+ CHECK_LT (offset, static_cast <sptr>(access_size));
482+ tag_t *tag_ptr =
483+ reinterpret_cast <tag_t *>(MemToShadow (untagged_addr + offset));
484+ tag_t mem_tag = *tag_ptr;
485+
486+ if (mem_tag && mem_tag < kShadowAlignment ) {
487+ tag_t *granule_ptr = reinterpret_cast <tag_t *>((untagged_addr + offset) &
488+ ~(kShadowAlignment - 1 ));
489+ // If offset is 0, (untagged_addr + offset) is not aligned to granules.
490+ // This is the offset of the leftmost accessed byte within the bad granule.
491+ u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1 );
492+ tag_t short_tag = granule_ptr[kShadowAlignment - 1 ];
493+ // The first mismatch was a short granule that matched the ptr_tag.
494+ if (short_tag == ptr_tag) {
495+ // If the access starts after the end of the short granule, then the first
496+ // bad byte is the first byte of the access; otherwise it is the first
497+ // byte past the end of the short granule
498+ if (mem_tag > in_granule_offset) {
499+ offset += mem_tag - in_granule_offset;
500+ }
501+ }
502+ }
503+ return offset;
504+ }
505+
472506BaseReport::Shadow BaseReport::CopyShadow () const {
473507 Shadow result;
474508 if (!MemIsApp (untagged_addr))
@@ -917,31 +951,12 @@ TagMismatchReport::~TagMismatchReport() {
917951
918952 Thread *t = GetCurrentThread ();
919953
920- sptr offset =
921- __hwasan_test_shadow (reinterpret_cast <void *>(tagged_addr), access_size);
922- CHECK_GE (offset, 0 );
923- CHECK_LT (offset, static_cast <sptr>(access_size));
924- tag_t *tag_ptr =
925- reinterpret_cast <tag_t *>(MemToShadow (untagged_addr + offset));
926- tag_t mem_tag = *tag_ptr;
954+ tag_t mem_tag = GetTagCopy (MemToShadow (untagged_addr + mismatch_offset));
927955
928956 Printf (" %s" , d.Access ());
929957 if (mem_tag && mem_tag < kShadowAlignment ) {
930- tag_t *granule_ptr = reinterpret_cast <tag_t *>((untagged_addr + offset) &
931- ~(kShadowAlignment - 1 ));
932- // If offset is 0, (untagged_addr + offset) is not aligned to granules.
933- // This is the offset of the leftmost accessed byte within the bad granule.
934- u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1 );
935- tag_t short_tag = granule_ptr[kShadowAlignment - 1 ];
936- // The first mismatch was a short granule that matched the ptr_tag.
937- if (short_tag == ptr_tag) {
938- // If the access starts after the end of the short granule, then the first
939- // bad byte is the first byte of the access; otherwise it is the first
940- // byte past the end of the short granule
941- if (mem_tag > in_granule_offset) {
942- offset += mem_tag - in_granule_offset;
943- }
944- }
958+ tag_t short_tag =
959+ GetShortTagCopy (MemToShadow (untagged_addr + mismatch_offset));
945960 Printf (
946961 " %s of size %zu at %p tags: %02x/%02x(%02x) (ptr/mem) in thread T%zd\n " ,
947962 is_store ? " WRITE" : " READ" , access_size, untagged_addr, ptr_tag,
@@ -951,16 +966,16 @@ TagMismatchReport::~TagMismatchReport() {
951966 is_store ? " WRITE" : " READ" , access_size, untagged_addr, ptr_tag,
952967 mem_tag, t->unique_id ());
953968 }
954- if (offset != 0 )
955- Printf (" Invalid access starting at offset %zu\n " , offset );
969+ if (mismatch_offset )
970+ Printf (" Invalid access starting at offset %zu\n " , mismatch_offset );
956971 Printf (" %s" , d.Default ());
957972
958973 stack->Print ();
959974
960975 PrintAddressDescription ();
961976 t->Announce ();
962977
963- PrintTags (untagged_addr + offset );
978+ PrintTags (untagged_addr + mismatch_offset );
964979
965980 if (registers_frame)
966981 ReportRegisters (registers_frame, pc);
0 commit comments