-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[hwasan] Classify stack overflow, and use after scope #76133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[hwasan] Classify stack overflow, and use after scope #76133
Conversation
Created using spr 1.3.4
Created using spr 1.3.4 [skip ci]
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Vitaly Buka (vitalybuka) ChangesWe can't distinguish UAR and UAS, but by definition Full diff: https://github.com/llvm/llvm-project/pull/76133.diff 5 Files Affected:
diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index dc34cded48e12c..253b64773fe384 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -221,29 +221,55 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
for (LocalInfo &local : frame.locals) {
if (!local.has_frame_offset || !local.has_size || !local.has_tag_offset)
continue;
+ if (!(local.name && internal_strlen(local.name)) &&
+ !(local.function_name && internal_strlen(local.name)) &&
+ !local.decl_file)
+ continue;
tag_t obj_tag = base_tag ^ local.tag_offset;
if (obj_tag != addr_tag)
continue;
- // Calculate the offset from the object address to the faulting
- // address. Because we only store bits 4-19 of FP (bits 0-3 are
- // guaranteed to be zero), the calculation is performed mod 2^20 and may
- // harmlessly underflow if the address mod 2^20 is below the object
- // address.
- uptr obj_offset =
- (untagged_addr - fp - local.frame_offset) & (kRecordFPModulus - 1);
- if (obj_offset >= local.size)
- continue;
+ uptr local_beg = (fp + local.frame_offset) |
+ (untagged_addr & ~(uptr(kRecordFPModulus) - 1));
+ uptr local_end = local_beg + local.size;
+
if (!found_local) {
Printf("\nPotentially referenced stack objects:\n");
found_local = true;
}
+
+ uptr offset;
+ const char *whence;
+ const char *cause;
+ if (local_beg <= untagged_addr && untagged_addr < local_end) {
+ offset = untagged_addr - local_beg;
+ whence = "inside";
+ cause = "use-after-scope";
+ } else if (untagged_addr >= local_end) {
+ offset = untagged_addr - local_end;
+ whence = "after";
+ cause = "stack-buffer-overflow";
+ } else {
+ offset = local_beg - untagged_addr;
+ whence = "before";
+ cause = "stack-buffer-overflow";
+ }
+ Decorator d;
+ Printf("%s", d.Error());
+ Printf("Cause: %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",
+ untagged_addr, offset, whence, local_end - local_beg, local_beg,
+ local_end);
+ Printf("%s", d.Allocation());
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,
+ Printf("declared as %s in %s %s\n", local.name, local.function_name,
location.data());
location.clear();
+ Printf("%s\n", d.Default());
}
frame.Clear();
}
diff --git a/compiler-rt/test/hwasan/TestCases/stack-overflow.c b/compiler-rt/test/hwasan/TestCases/stack-overflow.c
new file mode 100644
index 00000000000000..ba3e00551f5e00
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/stack-overflow.c
@@ -0,0 +1,26 @@
+// RUN: %clang_hwasan -g %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// Stack histories currently are not recorded on x86.
+// XFAIL: target=x86_64{{.*}}
+
+__attribute((noinline))
+void buggy() {
+ char c[64];
+ char *volatile p = c;
+ p[65] = 0;
+}
+
+int main() {
+ buggy();
+ // CHECK: WRITE of size 1 at
+ // CHECK: #0 {{.*}} in buggy{{.*}}stack-overflow.c:[[@LINE-6]]
+ // CHECK: Cause: stack tag-mismatch
+ // CHECK: is located in stack of thread
+ // CHECK: Potentially referenced stack objects:
+ // CHECK: Cause: stack-buffer-overflow
+ // CHECK-NEXT: 0x{{.*}} is located 1 bytes after a 64-byte region
+ // CHECK-NEXT: declared as c in buggy {{.*}}stack-overflow.c:
+ // CHECK: Memory tags around the buggy address
+
+ // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in buggy
+}
diff --git a/compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c b/compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c
index b06568e12eba7c..7a2a11593e7afe 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c
@@ -21,6 +21,8 @@ char *buggy(int b) {
int main() {
char *p = buggy(1);
// CHECK: Potentially referenced stack objects:
+ // CHECK-NEXT: use-after-scope
+ // CHECK-NEXT: 0x{{.*}} is located 0 bytes inside a 64-byte region
// CHECK-NEXT: c in buggy
p[0] = 0;
}
diff --git a/compiler-rt/test/hwasan/TestCases/stack-uar.c b/compiler-rt/test/hwasan/TestCases/stack-uar.c
index 48440a47d5f5f4..b2a40a19251ab6 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-uar.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-uar.c
@@ -50,15 +50,17 @@ int main() {
// CHECK: Cause: stack tag-mismatch
// CHECK: is located in stack of thread
// CHECK: Potentially referenced stack objects:
- // CHECK-NEXT: {{zzz|yyy}} in buggy {{.*}}stack-uar.c:
- // CHECK-NEXT: Memory tags around the buggy address
+ // CHECK: Cause: use-after-scope
+ // CHECK-NEXT: 0x{{.*}} is located 0 bytes inside a 2048-byte region
+ // CHECK-NEXT: declared as {{zzz|yyy}} in buggy {{.*}}stack-uar.c:
+ // CHECK: Memory tags around the buggy address
// NOSYM: Previously allocated frames:
// NOSYM-NEXT: record_addr:0x{{.*}} record:0x{{.*}} ({{.*}}/stack-uar.c.tmp+0x{{.*}}){{$}}
// NOSYM-NEXT: record_addr:0x{{.*}} record:0x{{.*}} ({{.*}}/stack-uar.c.tmp+0x{{.*}}){{$}}
// NOSYM-NEXT: record_addr:0x{{.*}} record:0x{{.*}} ({{.*}}/stack-uar.c.tmp+0x{{.*}}){{$}}
// NOSYM-NEXT: record_addr:0x{{.*}} record:0x{{.*}} ({{.*}}/stack-uar.c.tmp+0x{{.*}}){{$}}
- // NOSYM-NEXT: Memory tags around the buggy address
+ // NOSYM: Memory tags around the buggy address
// CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
}
diff --git a/compiler-rt/test/hwasan/TestCases/stack-underflow.c b/compiler-rt/test/hwasan/TestCases/stack-underflow.c
new file mode 100644
index 00000000000000..131140ce35e616
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/stack-underflow.c
@@ -0,0 +1,26 @@
+// RUN: %clang_hwasan -g %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// Stack histories currently are not recorded on x86.
+// XFAIL: target=x86_64{{.*}}
+
+__attribute((noinline))
+void buggy() {
+ char c[64];
+ char *volatile p = c;
+ p[-2] = 0;
+}
+
+int main() {
+ buggy();
+ // CHECK: WRITE of size 1 at
+ // CHECK: #0 {{.*}} in buggy{{.*}}stack-underflow.c:[[@LINE-6]]
+ // CHECK: Cause: stack tag-mismatch
+ // CHECK: is located in stack of thread
+ // CHECK: Potentially referenced stack objects:
+ // CHECK: Cause: stack-buffer-overflow
+ // 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
+
+ // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in buggy
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Created using spr 1.3.4
Created using spr 1.3.4 [skip ci]
Created using spr 1.3.4 [skip ci]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this comment?
Line 780
// TODO(fmayer): figure out how to distinguish use-after-return and
// stack-buffer-overflow.
done |
Hi, looks like patch broke 2 aarch64 bots: |
We can't distinguish UAR and UAS, but by definition
UAR is already UAS.