Skip to content

Commit

Permalink
[hwasan] Detect use after scope within function.
Browse files Browse the repository at this point in the history
Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D105201
  • Loading branch information
fmayer committed Aug 2, 2021
1 parent 7397dcb commit 66b4aaf
Show file tree
Hide file tree
Showing 16 changed files with 489 additions and 116 deletions.
68 changes: 68 additions & 0 deletions compiler-rt/test/hwasan/TestCases/stack-uas.c
@@ -0,0 +1,68 @@
// Tests use-after-scope detection and reporting.
// RUN: %clang_hwasan -mllvm -hwasan-use-after-scope -g %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clang_hwasan -mllvm -hwasan-use-after-scope -g %s -o %t && not %env_hwasan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM

// RUN: %clang_hwasan -mllvm -hwasan-use-after-scope=false -g %s -o %t && %run %t 2>&1
// Use after scope is turned off by default.
// RUN: %clang_hwasan -g %s -o %t && %run %t 2>&1

// RUN: %clang_hwasan -fexperimental-new-pass-manager -mllvm -hwasan-use-after-scope -g %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clang_hwasan -fno-experimental-new-pass-manager -mllvm -hwasan-use-after-scope -g %s -o %t && not %run %t 2>&1 | FileCheck %s

// REQUIRES: stable-runtime

// Stack histories currently are not recorded on x86.
// XFAIL: x86_64

void USE(void *x) { // pretend_to_do_something(void *x)
__asm__ __volatile__(""
:
: "r"(x)
: "memory");
}

__attribute__((noinline)) void Unrelated1() {
int A[2];
USE(&A[0]);
}
__attribute__((noinline)) void Unrelated2() {
int BB[3];
USE(&BB[0]);
}
__attribute__((noinline)) void Unrelated3() {
int CCC[4];
USE(&CCC[0]);
}

__attribute__((noinline)) char buggy() {
char *volatile p;
{
char zzz[0x1000];
p = zzz;
}
return *p;
}

int main() {
Unrelated1();
Unrelated2();
Unrelated3();
char p = buggy();
return p;
// CHECK: READ of size 1 at
// CHECK: #0 {{.*}} in buggy{{.*}}stack-uas.c:[[@LINE-10]]
// CHECK: Cause: stack tag-mismatch
// CHECK: is located in stack of thread
// CHECK: Potentially referenced stack objects:
// CHECK-NEXT: zzz in buggy {{.*}}stack-uas.c:[[@LINE-17]]
// CHECK-NEXT: Memory tags around the buggy address

// NOSYM: Previously allocated frames:
// NOSYM-NEXT: record_addr:0x{{.*}} record:0x{{.*}} ({{.*}}/stack-uas.c.tmp+0x{{.*}}){{$}}
// NOSYM-NEXT: record_addr:0x{{.*}} record:0x{{.*}} ({{.*}}/stack-uas.c.tmp+0x{{.*}}){{$}}
// NOSYM-NEXT: record_addr:0x{{.*}} record:0x{{.*}} ({{.*}}/stack-uas.c.tmp+0x{{.*}}){{$}}
// NOSYM-NEXT: record_addr:0x{{.*}} record:0x{{.*}} ({{.*}}/stack-uas.c.tmp+0x{{.*}}){{$}}
// NOSYM-NEXT: Memory tags around the buggy address

// CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in buggy
}
13 changes: 7 additions & 6 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-capture.cpp
@@ -1,8 +1,8 @@
// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan
// XFAIL: *
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope --std=c++11 -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s

// REQUIRES: aarch64-target-arch

#include <functional>

Expand All @@ -12,8 +12,9 @@ int main() {
int x = 0;
f = [&x]() __attribute__((noinline)) {
return x; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #0 0x{{.*}} in {{.*}}use-after-scope-capture.cpp:[[@LINE-2]]
// CHECK: Cause: stack tag-mismatch
};
}
return f(); // BOOM
Expand Down
12 changes: 7 additions & 5 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-dtor-order.cpp
@@ -1,16 +1,18 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -O1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

#include <stdio.h>

struct IntHolder {
explicit IntHolder(int *val = 0) : val_(val) {}
__attribute__((noinline)) ~IntHolder() {
printf("Value: %d\n", *val_); // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #0 0x{{.*}} in IntHolder::~IntHolder{{.*}}.cpp:[[@LINE-2]]
}
void set(int *val) { val_ = val; }
Expand Down
10 changes: 6 additions & 4 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-goto.cpp
@@ -1,10 +1,12 @@
// RUN: %clangxx_asan -O0 -fsanitize-address-use-after-scope %s -o %t && %run %t
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -O0 %s -o %t && %run %t

// Function jumps over variable initialization making lifetime analysis
// ambiguous. Asan should ignore such variable and program must not fail.
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

#include <stdlib.h>

Expand Down
13 changes: 8 additions & 5 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-if.cpp
@@ -1,8 +1,10 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -O1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

int *p;
bool b = true;
Expand All @@ -13,6 +15,7 @@ int main() {
p = x + 1;
}
return *p; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #0 0x{{.*}} in main {{.*}}.cpp:[[@LINE-2]]
// CHECK: Cause: stack tag-mismatch
}
21 changes: 8 additions & 13 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-inlined.cpp
@@ -1,15 +1,16 @@
// This is the ASAN test of the same name ported to HWAsan.

// Test with "-O2" only to make sure inlining (leading to use-after-scope)
// happens. "always_inline" is not enough, as Clang doesn't emit
// llvm.lifetime intrinsics at -O0.
//
// RUN: %clangxx_asan -O2 -fsanitize-address-use-after-scope %s -o %t && \
// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -O2 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

int *arr;
// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

int *arr;
__attribute__((always_inline)) void inlined(int arg) {
int x[5];
for (int i = 0; i < arg; i++)
Expand All @@ -20,12 +21,6 @@ __attribute__((always_inline)) void inlined(int arg) {
int main(int argc, char *argv[]) {
inlined(argc);
return arr[argc - 1]; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: READ of size 4 at 0x{{.*}} thread T0
// CHECK: #0 0x{{.*}} in main
// CHECK: {{.*}}use-after-scope-inlined.cpp:[[@LINE-4]]
// CHECK: Address 0x{{.*}} is located in stack of thread T0 at offset [[OFFSET:[^ ]*]] in frame
// CHECK: {{.*}} in main
// CHECK: This frame has
// CHECK: {{\[}}[[OFFSET]], {{.*}}) 'x.i' (line [[@LINE-15]])
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: Cause: stack tag-mismatch
}
15 changes: 8 additions & 7 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-loop-bug.cpp
@@ -1,8 +1,10 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -O1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

volatile int *p;

Expand All @@ -13,8 +15,7 @@ int main() {
p = x + i;
}
return *p; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-loop-bug.cpp:[[@LINE-2]]
// CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame
// {{\[}}[[OFFSET]], {{[0-9]+}}) 'x'
// CHECK: Cause: stack tag-mismatch
}
@@ -1,8 +1,10 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -O1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

#include <stdlib.h>

Expand All @@ -14,8 +16,7 @@ int main() {
p = &x;
}
return *p; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-loop-removed.cpp:[[@LINE-2]]
// CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame
// {{\[}}[[OFFSET]], {{[0-9]+}}) 'x'
// CHECK: Cause: stack tag-mismatch
}
13 changes: 8 additions & 5 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-loop.cpp
@@ -1,8 +1,10 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -O1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

int *p[3];

Expand All @@ -12,6 +14,7 @@ int main() {
p[i] = &x;
}
return **p; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #0 0x{{.*}} in main {{.*}}.cpp:[[@LINE-2]]
// CHECK: Cause: stack tag-mismatch
}
10 changes: 6 additions & 4 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-nobug.cpp
@@ -1,7 +1,9 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && %run %t
//
// Not expected to work yet with HWAsan.
// XFAIL: *
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -O1 %s -o %t && %run %t

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

#include <stdio.h>
#include <stdlib.h>
Expand Down
13 changes: 8 additions & 5 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-temp.cpp
@@ -1,8 +1,10 @@
// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -std=c++11 -O1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

struct IntHolder {
int val;
Expand All @@ -17,7 +19,8 @@ __attribute__((noinline)) void save(const IntHolder &holder) {
int main(int argc, char *argv[]) {
save({argc});
int x = saved->val; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp.cpp:[[@LINE-2]]
// CHECK: Cause: stack tag-mismatch
return x;
}
13 changes: 8 additions & 5 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-temp2.cpp
@@ -1,8 +1,10 @@
// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -std=c++11 -O1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

struct IntHolder {
__attribute__((noinline)) const IntHolder &Self() const {
Expand All @@ -16,7 +18,8 @@ const IntHolder *saved;
int main(int argc, char *argv[]) {
saved = &IntHolder().Self();
int x = saved->val; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp2.cpp:[[@LINE-2]]
// CHECK: Cause: stack tag-mismatch
return x;
}
18 changes: 10 additions & 8 deletions compiler-rt/test/hwasan/TestCases/use-after-scope-types.cpp
@@ -1,18 +1,21 @@
// RUN: %clangxx_asan %stdcxx11 -O0 -fsanitize-address-use-after-scope %s -o %t
// This is the ASAN test of the same name ported to HWAsan.

// RUN: %clangxx_hwasan -mllvm -hwasan-use-after-scope -std=c++11 -O0 %s -o %t
// RUN: not %run %t 0 2>&1 | FileCheck %s
// RUN: not %run %t 1 2>&1 | FileCheck %s
// RUN: not %run %t 2 2>&1 | FileCheck %s
// RUN: not %run %t 3 2>&1 | FileCheck %s
// RUN: not %run %t 4 2>&1 | FileCheck %s
// RUN: not %run %t 5 2>&1 | FileCheck %s
// RUN: not %run %t 6 2>&1 | FileCheck %s
// The std::vector case is broken because of limited lifetime tracking.
// TODO(fmayer): Fix and enable.
// RUN: not %run %t 7 2>&1 | FileCheck %s
// RUN: not %run %t 8 2>&1 | FileCheck %s
// RUN: not %run %t 9 2>&1 | FileCheck %s
// RUN: not %run %t 10 2>&1 | FileCheck %s
//
// Not expected to work yet with HWAsan.
// XFAIL: *

// REQUIRES: aarch64-target-arch
// REQUIRES: stable-runtime

#include <stdlib.h>
#include <string>
Expand Down Expand Up @@ -46,10 +49,9 @@ __attribute__((noinline)) void test() {
}

ptr.Access();
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch
// CHECK: #{{[0-9]+}} 0x{{.*}} in {{(void )?test.*\((void)?\) .*}}use-after-scope-types.cpp
// CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame
// {{\[}}[[OFFSET]], {{[0-9]+}}) 'x'
// CHECK: Cause: stack tag-mismatch
}

int main(int argc, char **argv) {
Expand Down

0 comments on commit 66b4aaf

Please sign in to comment.