Skip to content

Commit c478139

Browse files
authored
Reapply "[HWASan] symbolize stack overflows" (#102951) (#104036)
This reverts commit d4f6fcf. Relanding with fixed obj_offset calculation (precedence of operations was wrong), and the suggestion in #95308 (comment)
1 parent 98f2eb7 commit c478139

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

compiler-rt/lib/hwasan/scripts/hwasan_symbolize

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ class Symbolizer:
109109
self.__html = False
110110
self.__last_access_address = None
111111
self.__last_access_tag = None
112+
self.__tag_dump = []
113+
self.__tag_dump_match_idx = None
114+
self.__matched_stack_uas = False
115+
self.__offsets = []
112116

113117
def enable_html(self, enable):
114118
self.__html = enable
@@ -311,6 +315,34 @@ class Symbolizer:
311315
if match:
312316
self.__last_access_tag = int(match.group(2), 16)
313317

318+
def process_tag_dump_line(self, line, ignore_tags=False):
319+
m = re.match(r'.*?(0x[0-9a-f]+):' + '([ ]*[\[ ][0-9a-f][0-9a-f]\]?)' * 16, line)
320+
if m is None:
321+
return False
322+
addr = m.group(1)
323+
tags = m.group(*range(2, 18))
324+
fault = [i for i, x in enumerate(tags) if '[' in x]
325+
if fault:
326+
self.__tag_dump_match_idx = len(self.__tag_dump) + fault[0]
327+
self.__tag_dump.extend(int(x.strip(' [').rstrip('] '), 16) for x in tags)
328+
return True
329+
330+
def finish_tag_dump(self):
331+
if self.__matched_stack_uas or self.__tag_dump_match_idx is None:
332+
return
333+
for offset, size, local in sorted(self.__offsets, key=lambda x: abs(x[0])):
334+
idx = self.__tag_dump_match_idx - offset // 16
335+
if idx < 0 or idx > len(self.__tag_dump):
336+
continue
337+
if self.__tag_dump[idx] == self.__last_access_tag:
338+
self.print('')
339+
self.print('Potentially referenced stack object:')
340+
if offset > 0:
341+
self.print(' %d bytes after a variable "%s" in stack frame of function "%s"' % (offset - size, local[2], local[0]))
342+
if offset < 0:
343+
self.print(' %d bytes before a variable "%s" in stack frame of function "%s"' % (-offset, local[2], local[0]))
344+
self.print(' at %s' % (local[1],))
345+
314346
def process_stack_history(self, line, ignore_tags=False):
315347
if self.__last_access_address is None or self.__last_access_tag is None:
316348
return
@@ -336,16 +368,18 @@ class Symbolizer:
336368
size = local[4]
337369
if frame_offset is None or size is None:
338370
continue
339-
obj_offset = (self.__last_access_address - fp - frame_offset) & fp_mask
340-
if obj_offset >= size:
341-
continue
371+
obj_offset = (self.__last_access_address & fp_mask) - ((fp & fp_mask) + frame_offset)
342372
tag_offset = local[5]
343373
if not ignore_tags and (tag_offset is None or base_tag ^ tag_offset != self.__last_access_tag):
344374
continue
375+
if obj_offset < 0 or obj_offset >= size:
376+
self.__offsets.append((obj_offset, size, local))
377+
continue
345378
self.print('')
346379
self.print('Potentially referenced stack object:')
347380
self.print(' %d bytes inside a variable "%s" in stack frame of function "%s"' % (obj_offset, local[2], local[0]))
348381
self.print(' at %s' % (local[1],))
382+
self.__matched_stack_uas = True
349383
return True
350384
return False
351385

@@ -456,9 +490,18 @@ def main():
456490
sys.exit(1)
457491
symbolizer.read_linkify(args.linkify)
458492

493+
tag_dump = False
459494
for line in sys.stdin:
460495
if sys.version_info.major < 3:
461496
line = line.decode('utf-8')
497+
if tag_dump:
498+
tag_dump = symbolizer.process_tag_dump_line(line)
499+
if tag_dump:
500+
continue
501+
symbolizer.finish_tag_dump()
502+
if 'Memory tags around the buggy address' in line:
503+
tag_dump = True
504+
462505
symbolizer.save_access_address(line)
463506
if symbolizer.process_stack_history(line, ignore_tags=args.ignore_tags):
464507
continue
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: rm -rf %t; mkdir %t
2+
// RUN: %clang_hwasan -Wl,--build-id -g %s -o %t/hwasan_overflow
3+
// RUN: %env_hwasan_opts=symbolize=0 not %run %t/hwasan_overflow 16 2>&1 | hwasan_symbolize --symbols %t --index | FileCheck %s --check-prefixes=CHECK,AFTER0
4+
// RUN: %env_hwasan_opts=symbolize=0 not %run %t/hwasan_overflow 17 2>&1 | hwasan_symbolize --symbols %t --index | FileCheck %s --check-prefixes=CHECK,AFTER1
5+
// RUN: %env_hwasan_opts=symbolize=0 not %run %t/hwasan_overflow -1 2>&1 | hwasan_symbolize --symbols %t --index | FileCheck %s --check-prefixes=CHECK,BEFORE1
6+
// RUN: %env_hwasan_opts=symbolize=0 not %run %t/hwasan_overflow -17 2>&1 | hwasan_symbolize --symbols %t --index | FileCheck %s --check-prefixes=CHECK,BEFORE17
7+
// RUN: %env_hwasan_opts=symbolize=0 not %run %t/hwasan_overflow 1016 2>&1 | hwasan_symbolize --symbols %t --index | FileCheck %s --check-prefixes=CHECK,AFTER1000
8+
// RUN: %env_hwasan_opts=symbolize=0 not %run %t/hwasan_overflow -1000 2>&1 | hwasan_symbolize --symbols %t --index | FileCheck %s --check-prefixes=CHECK,BEFORE1000
9+
// RUN: %env_hwasan_opts=symbolize=0 not %run %t/hwasan_overflow 1000000 2>&1 | hwasan_symbolize --symbols %t --index | FileCheck %s --check-prefixes=TOOFAR
10+
11+
// REQUIRES: aarch64-target-arch
12+
13+
#include <stdlib.h>
14+
15+
static volatile char sink;
16+
17+
int main(int argc, char **argv) {
18+
volatile char x[16];
19+
sink = x[atoi(argv[1])];
20+
// TOOFAR-NOT: Potentially referenced stack object:
21+
// CHECK: Potentially referenced stack object:
22+
// AFTER0: 0 bytes after a variable "x" in stack frame of function "main"
23+
// AFTER1: 1 bytes after a variable "x" in stack frame of function "main"
24+
// BEFORE1: 1 bytes before a variable "x" in stack frame of function "main"
25+
// BEFORE17: 17 bytes before a variable "x" in stack frame of function "main"
26+
// BEFORE1000: 1000 bytes before a variable "x" in stack frame of function "main"
27+
// AFTER1000: 1000 bytes after a variable "x" in stack frame of function "main"
28+
// CHECK: at {{.*}}hwasan_symbolize_stack_overflow.cpp:[[@LINE-10]]
29+
return 0;
30+
}

0 commit comments

Comments
 (0)