diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp --- a/compiler-rt/lib/hwasan/hwasan_report.cpp +++ b/compiler-rt/lib/hwasan/hwasan_report.cpp @@ -589,6 +589,15 @@ void ReportTailOverwritten(StackTrace *stack, uptr tagged_addr, uptr orig_size, const u8 *expected) { uptr tail_size = kShadowAlignment - (orig_size % kShadowAlignment); + u8 actual_expected[kShadowAlignment]; + internal_memcpy(actual_expected, expected, tail_size); + tag_t ptr_tag = GetTagFromPointer(tagged_addr); + // Short granule is stashed in the last byte of the magic string. To avoid + // confusion, make the expected magic string contain the short granule tag. + if (orig_size % kShadowAlignment != 0) { + actual_expected[tail_size - 1] = ptr_tag; + } + ScopedReport R(flags()->halt_on_error); Decorator d; uptr untagged_addr = UntagAddr(tagged_addr); @@ -625,14 +634,13 @@ s.append("Expected: "); for (uptr i = 0; i < kShadowAlignment - tail_size; i++) s.append(".. "); - for (uptr i = 0; i < tail_size; i++) - s.append("%02x ", expected[i]); + for (uptr i = 0; i < tail_size; i++) s.append("%02x ", actual_expected[i]); s.append("\n"); s.append(" "); for (uptr i = 0; i < kShadowAlignment - tail_size; i++) s.append(" "); for (uptr i = 0; i < tail_size; i++) - s.append("%s ", expected[i] != tail[i] ? "^^" : " "); + s.append("%s ", actual_expected[i] != tail[i] ? "^^" : " "); s.append("\nThis error occurs when a buffer overflow overwrites memory\n" "to the right of a heap object, but within the %zd-byte granule, e.g.\n" diff --git a/compiler-rt/test/hwasan/TestCases/tail-magic.c b/compiler-rt/test/hwasan/TestCases/tail-magic.c --- a/compiler-rt/test/hwasan/TestCases/tail-magic.c +++ b/compiler-rt/test/hwasan/TestCases/tail-magic.c @@ -1,8 +1,13 @@ // Tests free_checks_tail_magic=1. -// RUN: %clang_hwasan %s -o %t +// RUN: %clang_hwasan %s -o %t // RUN: %env_hwasan_opts=free_checks_tail_magic=0 %run %t -// RUN: %env_hwasan_opts=free_checks_tail_magic=1 not %run %t 2>&1 | FileCheck %s -// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: %env_hwasan_opts=free_checks_tail_magic=1 not %run %t 2>&1 | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-NONLASTGRANULE --strict-whitespace %s +// RUN: not %run %t 2>&1 | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-NONLASTGRANULE --strict-whitespace %s +// RUN: %clang_hwasan -DLAST_GRANULE %s -o %t +// RUN: not %run %t 2>&1 | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-LASTGRANULE --strict-whitespace %s // REQUIRES: stable-runtime @@ -17,20 +22,30 @@ __attribute__((no_sanitize("hwaddress"))) void overwrite_tail() { sink[20] = 0x42; sink[24] = 0x66; +#ifdef LAST_GRANULE + sink[31] = 0x71; +#endif // LAST_GRANULE } int main(int argc, char **argv) { __hwasan_enable_allocator_tagging(); char *p = (char*)malloc(20); + __hwasan_print_shadow(p, 1); sink = p; overwrite_tail(); free(p); +// CHECK: HWASan shadow map for {{.*}} (pointer tag [[TAG:[a-f0-9]+]]) // CHECK: ERROR: HWAddressSanitizer: allocation-tail-overwritten; heap object [{{.*}}) of size 20 // CHECK: Stack of invalid access unknown. Issue detected at deallocation time. // CHECK: deallocated here: -// CHECK: in main {{.*}}tail-magic.c:[[@LINE-4]] +// CHECK: in main {{.*}}tail-magic.c:[[@LINE-5]] // CHECK: allocated here: -// CHECK: in main {{.*}}tail-magic.c:[[@LINE-9]] -// CHECK: Tail contains: .. .. .. .. 42 {{.. .. ..}} 66 +// CHECK: in main {{.*}}tail-magic.c:[[@LINE-11]] +// CHECK-NONLASTGRANULE: Tail contains: .. .. .. .. 42 {{(([a-f0-9]{2} ){3})}}66 +// CHECK-LASTGRANULE: Tail contains: .. .. .. .. 42 {{(([a-f0-9]{2} ){3})}}66 {{(([a-f0-9]{2} ?)+)}}71{{ *$}} +// CHECK-NEXT: Expected: {{ +}} .. .. .. .. {{([a-f0-9]{2} )+0?}}[[TAG]]{{ *$}} +// CHECK-NONLASTGRANULE-NEXT: {{ +}}^^{{ +}}^^{{ *$}} +// CHECK-LASTGRANULE-NEXT: {{ +}}^^{{ +}}^^{{ +}}^^{{ *$}} + return 0; }