[compiler-rt] [HWASan] symbolize stack overflows (PR #95308)
Florian Mayer via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 12 13:48:22 PDT 2024
https://github.com/fmayer created https://github.com/llvm/llvm-project/pull/95308
None
>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] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=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;
+}
More information about the llvm-commits
mailing list