[compiler-rt] [HWASan] symbolize stack overflows (PR #95308)

Florian Mayer via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 13 17:25:04 PDT 2024


https://github.com/fmayer updated https://github.com/llvm/llvm-project/pull/95308

>From b38d6b01364a8052370336712b545e195c1b7443 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 12 Jun 2024 13:48:06 -0700
Subject: [PATCH 1/7] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.4
---
 .../lib/hwasan/scripts/hwasan_symbolize       | 51 +++++++++++++++++--
 .../hwasan_symbolize_stack_overflow.cpp       | 28 ++++++++++
 2 files changed, 76 insertions(+), 3 deletions(-)
 create mode 100644 compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp

diff --git a/compiler-rt/lib/hwasan/scripts/hwasan_symbolize b/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
index 0408e0eb9993d..9a9824d904334 100755
--- a/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
+++ b/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
@@ -109,6 +109,10 @@ class Symbolizer:
     self.__html = False
     self.__last_access_address = None
     self.__last_access_tag = None
+    self.__tag_dump = []
+    self.__tag_dump_match_idx = None
+    self.__matched_stack_uas = False
+    self.__offsets = []
 
   def enable_html(self, enable):
     self.__html = enable
@@ -311,6 +315,36 @@ class Symbolizer:
     if match:
       self.__last_access_tag = int(match.group(2), 16)
 
+  def process_tag_dump_line(self, line, ignore_tags=False):
+    m = re.match(r'.*?(0x[0-9a-f]+):' + '([ ]*[\[ ][0-9a-f][0-9a-f]\]?)' * 16, line)
+    if m is None:
+      return False
+    if self.__matched_stack_uas:
+      return True
+    addr = m.group(1)
+    tags = m.group(*range(2, 18))
+    fault = [i for i, x in enumerate(tags) if '[' in x]
+    if fault:
+      self.__tag_dump_match_idx = len(self.__tag_dump) + fault[0]
+    self.__tag_dump.extend(int(x.strip(' [').rstrip('] '), 16) for x in tags)
+    return True
+
+  def finish_tag_dump(self):
+    if self.__matched_stack_uas or not self.__tag_dump_match_idx:
+      return
+    for offset, size, local in sorted(self.__offsets, key=lambda x: abs(x[0])):
+      idx = self.__tag_dump_match_idx - offset // 16
+      if idx < 0 or idx > len(self.__tag_dump):
+        continue
+      if self.__tag_dump[idx] == self.__last_access_tag:
+        self.print('')
+        self.print('Potentially referenced stack object:')
+        if offset > 0:
+          self.print('  %d bytes after a variable "%s" in stack frame of function "%s"' % (offset - size, local[2], local[0]))
+        if offset < 0:
+          self.print('  %d bytes before a variable "%s" in stack frame of function "%s"' % (-offset, local[2], local[0]))
+        self.print('  at %s' % (local[1],))
+
   def process_stack_history(self, line, ignore_tags=False):
     if self.__last_access_address is None or self.__last_access_tag is None:
       return
@@ -336,16 +370,18 @@ class Symbolizer:
         size = local[4]
         if frame_offset is None or size is None:
           continue
-        obj_offset = (self.__last_access_address - fp - frame_offset) & fp_mask
-        if obj_offset >= size:
-          continue
+        obj_offset = (self.__last_access_address & fp_mask) - ((fp + frame_offset) & fp_mask)
         tag_offset = local[5]
         if not ignore_tags and (tag_offset is None or base_tag ^ tag_offset != self.__last_access_tag):
           continue
+        if obj_offset <= 0 or obj_offset >= size:
+          self.__offsets.append((obj_offset, size, local))
+          continue
         self.print('')
         self.print('Potentially referenced stack object:')
         self.print('  %d bytes inside a variable "%s" in stack frame of function "%s"' % (obj_offset, local[2], local[0]))
         self.print('  at %s' % (local[1],))
+        self.__matched_stack_uas = True
       return True
     return False
 
@@ -456,9 +492,18 @@ def main():
       sys.exit(1)
     symbolizer.read_linkify(args.linkify)
 
+  tag_dump = False
   for line in sys.stdin:
     if sys.version_info.major < 3:
       line = line.decode('utf-8')
+    if tag_dump:
+      tag_dump = symbolizer.process_tag_dump_line(line)
+      if tag_dump:
+        continue
+      symbolizer.finish_tag_dump()
+    if 'Memory tags around the buggy address' in line:
+      tag_dump = True
+
     symbolizer.save_access_address(line)
     if symbolizer.process_stack_history(line, ignore_tags=args.ignore_tags):
       continue
diff --git a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
new file mode 100644
index 0000000000000..254f1df0ee3af
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_hwasan -Wl,--build-id -g %s -o %t
+// RUN: %env_hwasan_opts=symbolize=0 not %run %t 16 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,AFTER0
+// RUN: %env_hwasan_opts=symbolize=0 not %run %t 17 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,AFTER1
+// RUN: %env_hwasan_opts=symbolize=0 not %run %t -1 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,BEFORE1
+// RUN: %env_hwasan_opts=symbolize=0 not %run %t -17 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,BEFORE17
+// RUN: %env_hwasan_opts=symbolize=0 not %run %t 1016 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,AFTER1000
+// RUN: %env_hwasan_opts=symbolize=0 not %run %t -1000 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,BEFORE1000
+
+// REQUIRES: pointer-tagging
+
+#include <sanitizer/hwasan_interface.h>
+#include <stdlib.h>
+
+static volatile char sink;
+
+int main(int argc, char **argv) {
+  volatile char x[16];
+  sink = x[atoi(argv[1])];
+  // CHECK: Potentially referenced stack object:
+  // AFTER0:   0 bytes after a variable "x" in stack frame of function "main"
+  // AFTER1:   1 bytes after a variable "x" in stack frame of function "main"
+  // BEFORE1:   1 bytes before a variable "x" in stack frame of function "main"
+  // BEFORE17:   17 bytes before a variable "x" in stack frame of function "main"
+  // BEFORE1000:   1000 bytes before a variable "x" in stack frame of function "main"
+  // AFTER1000:   1000 bytes after a variable "x" in stack frame of function "main"
+  // CHECK:   at {{.*}}hwasan_symbolize_stack_overflow.cpp:[[@LINE-9]]
+  return 0;
+}

>From a7d65dd074e76225f7565d86b4d85f8dd943cf12 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 12 Jun 2024 13:49:27 -0700
Subject: [PATCH 2/7] cleanup

Created using spr 1.3.4
---
 compiler-rt/lib/hwasan/scripts/hwasan_symbolize | 2 --
 1 file changed, 2 deletions(-)

diff --git a/compiler-rt/lib/hwasan/scripts/hwasan_symbolize b/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
index 9a9824d904334..80915613373c5 100755
--- a/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
+++ b/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
@@ -319,8 +319,6 @@ class Symbolizer:
     m = re.match(r'.*?(0x[0-9a-f]+):' + '([ ]*[\[ ][0-9a-f][0-9a-f]\]?)' * 16, line)
     if m is None:
       return False
-    if self.__matched_stack_uas:
-      return True
     addr = m.group(1)
     tags = m.group(*range(2, 18))
     fault = [i for i, x in enumerate(tags) if '[' in x]

>From c4e41d1f899520cd6ca031dd0ecb90a1306b801e Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 12 Jun 2024 13:51:08 -0700
Subject: [PATCH 3/7] more test

Created using spr 1.3.4
---
 compiler-rt/lib/hwasan/scripts/hwasan_symbolize               | 2 +-
 .../test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/hwasan/scripts/hwasan_symbolize b/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
index 80915613373c5..93c7ba4f0ca00 100755
--- a/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
+++ b/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
@@ -328,7 +328,7 @@ class Symbolizer:
     return True
 
   def finish_tag_dump(self):
-    if self.__matched_stack_uas or not self.__tag_dump_match_idx:
+    if self.__matched_stack_uas or self.__tag_dump_match_idx is None:
       return
     for offset, size, local in sorted(self.__offsets, key=lambda x: abs(x[0])):
       idx = self.__tag_dump_match_idx - offset // 16
diff --git a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
index 254f1df0ee3af..a7677eb2aeb35 100644
--- a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
+++ b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
@@ -5,6 +5,7 @@
 // RUN: %env_hwasan_opts=symbolize=0 not %run %t -17 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,BEFORE17
 // RUN: %env_hwasan_opts=symbolize=0 not %run %t 1016 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,AFTER1000
 // RUN: %env_hwasan_opts=symbolize=0 not %run %t -1000 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,BEFORE1000
+// RUN: %env_hwasan_opts=symbolize=0 not %run %t 1000000 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=TOOFAR
 
 // REQUIRES: pointer-tagging
 
@@ -16,6 +17,7 @@ static volatile char sink;
 int main(int argc, char **argv) {
   volatile char x[16];
   sink = x[atoi(argv[1])];
+  // TOOFAR-NOT: Potentially referenced stack object:
   // CHECK: Potentially referenced stack object:
   // AFTER0:   0 bytes after a variable "x" in stack frame of function "main"
   // AFTER1:   1 bytes after a variable "x" in stack frame of function "main"
@@ -23,6 +25,6 @@ int main(int argc, char **argv) {
   // BEFORE17:   17 bytes before a variable "x" in stack frame of function "main"
   // BEFORE1000:   1000 bytes before a variable "x" in stack frame of function "main"
   // AFTER1000:   1000 bytes after a variable "x" in stack frame of function "main"
-  // CHECK:   at {{.*}}hwasan_symbolize_stack_overflow.cpp:[[@LINE-9]]
+  // CHECK:   at {{.*}}hwasan_symbolize_stack_overflow.cpp:[[@LINE-10]]
   return 0;
 }

>From 2d5de0a91036ce87ef2bd99780760bdf3cf91c36 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 12 Jun 2024 13:52:54 -0700
Subject: [PATCH 4/7] test cleanup

Created using spr 1.3.4
---
 .../test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp    | 1 -
 1 file changed, 1 deletion(-)

diff --git a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
index a7677eb2aeb35..359266183b240 100644
--- a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
+++ b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
@@ -9,7 +9,6 @@
 
 // REQUIRES: pointer-tagging
 
-#include <sanitizer/hwasan_interface.h>
 #include <stdlib.h>
 
 static volatile char sink;

>From b31e2b5a738b0af3f63b57e0aafebdf4c719a1cb Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 12 Jun 2024 13:54:16 -0700
Subject: [PATCH 5/7] fix

Created using spr 1.3.4
---
 compiler-rt/lib/hwasan/scripts/hwasan_symbolize | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/lib/hwasan/scripts/hwasan_symbolize b/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
index 93c7ba4f0ca00..7ba956da5438c 100755
--- a/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
+++ b/compiler-rt/lib/hwasan/scripts/hwasan_symbolize
@@ -372,7 +372,7 @@ class Symbolizer:
         tag_offset = local[5]
         if not ignore_tags and (tag_offset is None or base_tag ^ tag_offset != self.__last_access_tag):
           continue
-        if obj_offset <= 0 or obj_offset >= size:
+        if obj_offset < 0 or obj_offset >= size:
           self.__offsets.append((obj_offset, size, local))
           continue
         self.print('')

>From 0c2bd2aaf069c48efb7cc4a46bbac6991a271fb2 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Thu, 13 Jun 2024 17:23:08 -0700
Subject: [PATCH 6/7] test

Created using spr 1.3.4
---
 .../test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
index 822420b0eb1ad..99c5a514baf70 100644
--- a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
+++ b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
@@ -7,7 +7,7 @@
 // RUN: %env_hwasan_opts=symbolize=0 not %run %t -1000 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,BEFORE1000
 // RUN: %env_hwasan_opts=symbolize=0 not %run %t 1000000 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=TOOFAR
 
-// REQUIRES: aarch64-target-arch
+// REQUIRES: android && pointer-tagging
 
 #include <stdlib.h>
 

>From 59a6132548511bd4172c330d01037f090e01ddf0 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Thu, 13 Jun 2024 17:24:50 -0700
Subject: [PATCH 7/7] actually this was correct

Created using spr 1.3.4
---
 .../test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
index 99c5a514baf70..822420b0eb1ad 100644
--- a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
+++ b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize_stack_overflow.cpp
@@ -7,7 +7,7 @@
 // RUN: %env_hwasan_opts=symbolize=0 not %run %t -1000 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=CHECK,BEFORE1000
 // RUN: %env_hwasan_opts=symbolize=0 not %run %t 1000000 2>&1 | hwasan_symbolize --symbols $(dirname %t) --index | FileCheck %s --check-prefixes=TOOFAR
 
-// REQUIRES: android && pointer-tagging
+// REQUIRES: aarch64-target-arch
 
 #include <stdlib.h>
 



More information about the llvm-commits mailing list