Skip to content

Commit 04087c2

Browse files
committed
[NFC][hwasan] Find mismatch offset early (#66682)
1 parent 6eaaf09 commit 04087c2

File tree

1 file changed

+40
-25
lines changed

1 file changed

+40
-25
lines changed

compiler-rt/lib/hwasan/hwasan_report.cpp

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
472506
BaseReport::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

Comments
 (0)