Skip to content

Commit 7641c22

Browse files
committed
[NFC][hwasan] Store shadow bytes early (#66682)
1 parent ac750e2 commit 7641c22

File tree

1 file changed

+102
-48
lines changed

1 file changed

+102
-48
lines changed

compiler-rt/lib/hwasan/hwasan_report.cpp

Lines changed: 102 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "sanitizer_common/sanitizer_array_ref.h"
2626
#include "sanitizer_common/sanitizer_common.h"
2727
#include "sanitizer_common/sanitizer_flags.h"
28+
#include "sanitizer_common/sanitizer_internal_defs.h"
2829
#include "sanitizer_common/sanitizer_mutex.h"
2930
#include "sanitizer_common/sanitizer_report_decorator.h"
3031
#include "sanitizer_common/sanitizer_stackdepot.h"
@@ -321,56 +322,61 @@ static uptr GetGlobalSizeFromDescriptor(uptr ptr) {
321322

322323
void ReportStats() {}
323324

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) {
327329
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) {
334334
s.Append(row == center_row_beg ? "=>" : " ");
335-
s.AppendF("%p:", (void *)ShadowToMem(reinterpret_cast<uptr>(row)));
335+
s.AppendF("%p:", (void *)ShadowToMem(row));
336336
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 ? "]" : " ");
340340
}
341341
s.AppendF("\n");
342342
}
343-
Printf("%s", s.data());
344343
}
345344

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(
348351
"Memory tags around the buggy address (one tag corresponds to %zd "
349352
"bytes):\n",
350353
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+
});
354359

355-
Printf(
360+
s.AppendF(
356361
"Tags for short granules around the buggy address (one tag corresponds "
357362
"to %zd bytes):\n",
358363
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(
370375
"See "
371376
"https://clang.llvm.org/docs/"
372377
"HardwareAssistedAddressSanitizerDesign.html#short-granules for a "
373378
"description of short granule tags\n");
379+
Printf("%s", s.data());
374380
}
375381

376382
static uptr GetTopPc(const StackTrace *stack) {
@@ -390,7 +396,8 @@ class BaseReport {
390396
ptr_tag(GetTagFromPointer(tagged_addr)),
391397
heap(CopyHeapChunk()),
392398
allocations(CopyAllocations()),
393-
candidate(FindBufferOverflowCandidate()) {}
399+
candidate(FindBufferOverflowCandidate()),
400+
shadow(CopyShadow()) {}
394401

395402
protected:
396403
struct OverflowCandidate {
@@ -428,6 +435,15 @@ class BaseReport {
428435
bool is_allocated = false;
429436
};
430437

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;
431447
HeapChunk CopyHeapChunk() const;
432448
Allocations CopyAllocations();
433449
OverflowCandidate FindBufferOverflowCandidate() const;
@@ -447,8 +463,49 @@ class BaseReport {
447463
const HeapChunk heap;
448464
const Allocations allocations;
449465
const OverflowCandidate candidate;
466+
467+
const Shadow shadow;
450468
};
451469

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+
452509
BaseReport::HeapChunk BaseReport::CopyHeapChunk() const {
453510
HeapChunk result = {};
454511
if (MemIsShadow(untagged_addr))
@@ -721,15 +778,6 @@ class InvalidFreeReport : public BaseReport {
721778
};
722779

723780
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-
}
733781
Decorator d;
734782
Printf("%s", d.Error());
735783
uptr pc = GetTopPc(stack);
@@ -743,16 +791,19 @@ InvalidFreeReport::~InvalidFreeReport() {
743791
SanitizerToolName, bug_type, untagged_addr, pc);
744792
}
745793
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));
748796
Printf("%s", d.Default());
749797

750798
stack->Print();
751799

752800
PrintAddressDescription();
753801

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+
}
756807

757808
MaybePrintAndroidHelpUrl();
758809
ReportErrorSummary(bug_type, stack);
@@ -834,8 +885,9 @@ TailOverwrittenReport::~TailOverwrittenReport() {
834885
Printf("%s", s.data());
835886
GetCurrentThread()->Announce();
836887

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); });
839891

840892
MaybePrintAndroidHelpUrl();
841893
ReportErrorSummary(bug_type, stack);
@@ -912,7 +964,9 @@ TagMismatchReport::~TagMismatchReport() {
912964
PrintAddressDescription();
913965
t->Announce();
914966

915-
PrintTagsAroundAddr(tag_ptr);
967+
PrintTagsAroundAddr(
968+
untagged_addr + offset, [&](uptr addr) { return GetTagCopy(addr); },
969+
[&](uptr addr) { return GetShortTagCopy(addr); });
916970

917971
if (registers_frame)
918972
ReportRegisters(registers_frame, pc);

0 commit comments

Comments
 (0)