[libc-commits] [mlir] [openmp] [libcxx] [compiler-rt] [llvm] [lldb] [libc] [clang] [flang] [hwasan] Classify stack overflow, and use after scope (PR #76133)

Vitaly Buka via libc-commits libc-commits at lists.llvm.org
Thu Dec 21 17:35:41 PST 2023


https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/76133

>From 89636904337efe75ef6e0743e4f098f0d5b5ab56 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Wed, 20 Dec 2023 23:58:05 -0800
Subject: [PATCH 1/4] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
 =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.4

[skip ci]
---
 compiler-rt/lib/hwasan/hwasan_report.cpp      | 26 ++++++++++++++-----
 .../test/hwasan/TestCases/Linux/syscalls.cpp  |  2 +-
 .../hwasan/TestCases/heap-buffer-overflow.c   |  7 ++---
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index 5e8aa315801bcd..dc34cded48e12c 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -205,6 +205,7 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
                                   tag_t addr_tag, uptr untagged_addr) {
   uptr frames = Min((uptr)flags()->stack_history_size, sa->size());
   bool found_local = false;
+  InternalScopedString location;
   for (uptr i = 0; i < frames; i++) {
     const uptr *record_addr = &(*sa)[i];
     uptr record = *record_addr;
@@ -233,11 +234,16 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
         if (obj_offset >= local.size)
           continue;
         if (!found_local) {
-          Printf("Potentially referenced stack objects:\n");
+          Printf("\nPotentially referenced stack objects:\n");
           found_local = true;
         }
-        Printf("  %s in %s %s:%d\n", local.name, local.function_name,
-               local.decl_file, local.decl_line);
+        StackTracePrinter::GetOrInit()->RenderSourceLocation(
+            &location, local.decl_file, local.decl_line, 0,
+            common_flags()->symbolize_vs_style,
+            common_flags()->strip_path_prefix);
+        Printf("  %s in %s %s\n", local.name, local.function_name,
+               location.data());
+        location.clear();
       }
       frame.Clear();
     }
@@ -363,7 +369,7 @@ static void PrintTagsAroundAddr(uptr addr, GetTag get_tag,
   InternalScopedString s;
   addr = MemToShadow(addr);
   s.AppendF(
-      "Memory tags around the buggy address (one tag corresponds to %zd "
+      "\nMemory tags around the buggy address (one tag corresponds to %zd "
       "bytes):\n",
       kShadowAlignment);
   PrintTagInfoAroundAddr(addr, kShadowLines, s,
@@ -648,19 +654,23 @@ void BaseReport::PrintHeapOrGlobalCandidate() const {
   if (candidate.heap.is_allocated) {
     uptr offset;
     const char *whence;
+    const char *cause;
     if (candidate.heap.begin <= untagged_addr &&
         untagged_addr < candidate.heap.end) {
       offset = untagged_addr - candidate.heap.begin;
       whence = "inside";
+      cause = "heap-use-after-free";
     } else if (candidate.after) {
       offset = untagged_addr - candidate.heap.end;
       whence = "after";
+      cause = "heap-buffer-overflow";
     } else {
       offset = candidate.heap.begin - untagged_addr;
       whence = "before";
+      cause = "heap-buffer-underflow";
     }
     Printf("%s", d.Error());
-    Printf("\nCause: heap-buffer-overflow\n");
+    Printf("\nCause: %s\n", cause);
     Printf("%s", d.Default());
     Printf("%s", d.Location());
     Printf("%p is located %zd bytes %s a %zd-byte region [%p,%p)\n",
@@ -803,8 +813,10 @@ void BaseReport::PrintAddressDescription() const {
   }
 
   // Print the remaining threads, as an extra information, 1 line per thread.
-  if (flags()->print_live_threads_info)
+  if (flags()->print_live_threads_info) {
+    Printf("\n");
     hwasanThreadList().VisitAllLiveThreads([&](Thread *t) { t->Announce(); });
+  }
 
   if (!num_descriptions_printed)
     // We exhausted our possibilities. Bail out.
@@ -1020,7 +1032,7 @@ void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size,
 // See the frame breakdown defined in __hwasan_tag_mismatch (from
 // hwasan_tag_mismatch_{aarch64,riscv64}.S).
 void ReportRegisters(const uptr *frame, uptr pc) {
-  Printf("Registers where the failure occurred (pc %p):\n", pc);
+  Printf("\nRegisters where the failure occurred (pc %p):\n", pc);
 
   // We explicitly print a single line (4 registers/line) each iteration to
   // reduce the amount of logcat error messages printed. Each Printf() will
diff --git a/compiler-rt/test/hwasan/TestCases/Linux/syscalls.cpp b/compiler-rt/test/hwasan/TestCases/Linux/syscalls.cpp
index 154b6989899352..eee43f458fac10 100644
--- a/compiler-rt/test/hwasan/TestCases/Linux/syscalls.cpp
+++ b/compiler-rt/test/hwasan/TestCases/Linux/syscalls.cpp
@@ -26,7 +26,7 @@ int main(int argc, char *argv[]) {
 
   __sanitizer_syscall_pre_recvmsg(0, buf - 1, 0);
   // CHECK: HWAddressSanitizer: tag-mismatch on address [[PTR:0x[a-f0-9]+]]
-  // CHECK: Cause: heap-buffer-overflow
+  // CHECK: Cause: heap-buffer-underflow
   // CHECK: [[PTR]] is located 1 bytes before a 1000-byte region
 
   free(buf);
diff --git a/compiler-rt/test/hwasan/TestCases/heap-buffer-overflow.c b/compiler-rt/test/hwasan/TestCases/heap-buffer-overflow.c
index 4e6638be584b0d..c1c7d458b9424f 100644
--- a/compiler-rt/test/hwasan/TestCases/heap-buffer-overflow.c
+++ b/compiler-rt/test/hwasan/TestCases/heap-buffer-overflow.c
@@ -29,7 +29,8 @@ int main(int argc, char **argv) {
   if (size == 1000000) {
     fprintf(stderr, "is a large allocated heap chunk; size: 1003520 offset: %d\n",
             offset);
-    fprintf(stderr, "Cause: heap-buffer-overflow\n");
+    fprintf(stderr, "Cause: heap-buffer-%s\n",
+            offset == -30 ? "underflow" : "overflow");
     fprintf(stderr, "is located %s a 1000000-byte region\n",
             offset == -30 ? "30 bytes before" : "0 bytes after");
     return -1;
@@ -44,11 +45,11 @@ int main(int argc, char **argv) {
 // CHECK80: Cause: heap-buffer-overflow
 // CHECK80: is located 50 bytes after a 30-byte region
 //
-// CHECKm30: Cause: heap-buffer-overflow
+// CHECKm30: Cause: heap-buffer-underflow
 // CHECKm30: is located 30 bytes before a 30-byte region
 //
 // CHECKMm30: is a large allocated heap chunk; size: 1003520 offset: -30
-// CHECKMm30: Cause: heap-buffer-overflow
+// CHECKMm30: Cause: heap-buffer-underflow
 // CHECKMm30: is located 30 bytes before a 1000000-byte region
 //
 // CHECKM: is a large allocated heap chunk; size: 1003520 offset: 1000000

>From bd2a5987e9c6e3e48dd091cbe08601b26ba4d303 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 21 Dec 2023 00:06:16 -0800
Subject: [PATCH 2/4] update tests

Created using spr 1.3.4
---
 compiler-rt/lib/hwasan/hwasan_report.cpp            | 2 +-
 compiler-rt/test/hwasan/TestCases/stack-underflow.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index 253b64773fe384..ae8884390ac796 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -251,7 +251,7 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
         } else {
           offset = local_beg - untagged_addr;
           whence = "before";
-          cause = "stack-buffer-overflow";
+          cause = "stack-buffer-underflow";
         }
         Decorator d;
         Printf("%s", d.Error());
diff --git a/compiler-rt/test/hwasan/TestCases/stack-underflow.c b/compiler-rt/test/hwasan/TestCases/stack-underflow.c
index 131140ce35e616..7f790afc553fd1 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-underflow.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-underflow.c
@@ -17,7 +17,7 @@ int main() {
   // CHECK: Cause: stack tag-mismatch
   // CHECK: is located in stack of thread
   // CHECK: Potentially referenced stack objects:
-  // CHECK: Cause: stack-buffer-overflow
+  // CHECK: Cause: stack-buffer-underflow
   // CHECK-NEXT: 0x{{.*}} is located 2 bytes before a 64-byte region
   // CHECK-NEXT: declared as c in buggy {{.*}}stack-underflow.c:
   // CHECK: Memory tags around the buggy address

>From 995ecd32254a051661d7cda466c6c7cc7714ef94 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 21 Dec 2023 17:34:09 -0800
Subject: [PATCH 3/4] Update hwasan_report.cpp

---
 compiler-rt/lib/hwasan/hwasan_report.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index 3d192d14975319..b35c731ea1e3ad 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -228,6 +228,8 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
         tag_t obj_tag = base_tag ^ local.tag_offset;
         if (obj_tag != addr_tag)
           continue;
+        // Guess top bits of local variable from the faulting address, because
+        // we only store bits 4-19 of FP (bits 0-3 are guaranteed to be zero).
         uptr local_beg = (fp + local.frame_offset) |
                          (untagged_addr & ~(uptr(kRecordFPModulus) - 1));
         uptr local_end = local_beg + local.size;

>From ee7914a221cca48a369c09fa29f9b354c56e466d Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 21 Dec 2023 17:35:31 -0800
Subject: [PATCH 4/4] Update hwasan_report.cpp

---
 compiler-rt/lib/hwasan/hwasan_report.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index b35c731ea1e3ad..5b3a99adfea7c5 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -779,8 +779,6 @@ void BaseReport::PrintAddressDescription() const {
   // Check stack first. If the address is on the stack of a live thread, we
   // know it cannot be a heap / global overflow.
   for (const auto &sa : allocations.stack) {
-    // TODO(fmayer): figure out how to distinguish use-after-return and
-    // stack-buffer-overflow.
     Printf("%s", d.Error());
     Printf("\nCause: stack tag-mismatch\n");
     Printf("%s", d.Location());



More information about the libc-commits mailing list