diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7859,6 +7859,11 @@ return false; } +static bool isSanitizerAttributeAllowedOnGlobals(StringRef Sanitizer) { + return Sanitizer == "address" || Sanitizer == "hwaddress" || + Sanitizer == "memtag"; +} + static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.checkAtLeastNumArgs(S, 1)) return; @@ -7876,7 +7881,7 @@ SanitizerMask() && SanitizerName != "coverage") S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName; - else if (isGlobalVar(D) && SanitizerName != "address") + else if (isGlobalVar(D) && !isSanitizerAttributeAllowedOnGlobals(SanitizerName)) S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) << AL << ExpectedFunctionOrMethod; Sanitizers.push_back(SanitizerName); diff --git a/clang/test/CodeGen/Inputs/sanitizer-extra-source.cpp b/clang/test/CodeGen/Inputs/sanitizer-extra-source.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/Inputs/sanitizer-extra-source.cpp @@ -0,0 +1 @@ +int extra_global; diff --git a/clang/test/CodeGen/Inputs/sanitizer-ignorelist-global.txt b/clang/test/CodeGen/Inputs/sanitizer-ignorelist-global.txt new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/Inputs/sanitizer-ignorelist-global.txt @@ -0,0 +1 @@ +global:*ignorelisted_global* diff --git a/clang/test/CodeGen/Inputs/sanitizer-ignorelist-src.txt b/clang/test/CodeGen/Inputs/sanitizer-ignorelist-src.txt new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/Inputs/sanitizer-ignorelist-src.txt @@ -0,0 +1 @@ +src:*-globals.cpp diff --git a/clang/test/CodeGen/hwasan-globals.cpp b/clang/test/CodeGen/hwasan-globals.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/hwasan-globals.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -include %S/Inputs/sanitizer-extra-source.cpp \ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-ignorelist-global.txt \ +// RUN: -fsanitize=hwaddress -emit-llvm -o - %s | FileCheck %s + +// RUN: %clang_cc1 -include %S/Inputs/sanitizer-extra-source.cpp \ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-ignorelist-src.txt \ +// RUN: -fsanitize=hwaddress -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefix=IGNORELIST + +int global; +int __attribute__((no_sanitize("hwaddress"))) attributed_global; +int __attribute__((disable_sanitizer_instrumentation)) disable_instrumentation_global; +int ignorelisted_global; + +void func() { + static int static_var = 0; + const char *literal = "Hello, world!"; +} + +// CHECK: @{{.*}}attributed_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_hwaddress +// CHECK: @{{.*}}disable_instrumentation_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_hwaddress +// CHECK: @{{.*}}ignorelisted_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_hwaddress +// CHECK: @{{.*}}extra_global{{.*}}.hwasan{{.*}} = +// CHECK: @{{.*}}global{{.*}}.hwasan{{.*}} = +// CHECK: @{{.*}}static_var{{.*}}.hwasan{{.*}} = +// CHECK: @{{.*}}.hwasan{{.*}} = {{.*}} c"Hello, world!\00" + +// CHECK: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[DISABLE_INSTR_GLOBAL:[0-9]+]], ![[IGNORELISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} +// CHECK: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} +// CHECK: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} +// CHECK: ![[GLOBAL]] = !{{{.*}} ![[GLOBAL_LOC:[0-9]+]], !"global", i1 false, i1 false} +// CHECK: ![[GLOBAL_LOC]] = !{!"{{.*}}hwasan-globals.cpp", i32 10, i32 5} +// CHECK: ![[ATTR_GLOBAL]] = !{{{.*attributed_global.*}}, null, null, i1 false, i1 true} +// CHECK: ![[DISABLE_INSTR_GLOBAL]] = !{{{.*disable_instrumentation_global.*}}, null, null, i1 false, i1 true} +// CHECK: ![[IGNORELISTED_GLOBAL]] = !{{{.*ignorelisted_global.*}}, null, null, i1 false, i1 true} +// CHECK: ![[STATIC_VAR]] = !{{{.*}} ![[STATIC_LOC:[0-9]+]], !"static_var", i1 false, i1 false} +// CHECK: ![[STATIC_LOC]] = !{!"{{.*}}hwasan-globals.cpp", i32 16, i32 14} +// CHECK: ![[LITERAL]] = !{{{.*}} ![[LITERAL_LOC:[0-9]+]], !"", i1 false, i1 false} +// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}hwasan-globals.cpp", i32 17, i32 25} + +// IGNORELIST: @{{.*}}global{{.*}} ={{.*}} global {{.*}}, no_sanitize_hwaddress +// IGNORELIST: @{{.*}}attributed_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_hwaddress +// IGNORELIST: @{{.*}}disable_instrumentation_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_hwaddress +// IGNORELIST: @{{.*}}ignorelisted_globa{{.*}} ={{.*}} global {{.*}}, no_sanitize_hwaddress +// IGNORELIST: @{{.*}}static_var{{.*}} ={{.*}} global {{.*}}, no_sanitize_hwaddress +// IGNORELIST: @{{.*}} = {{.*}} c"Hello, world!\00"{{.*}}, no_sanitize_hwaddress +// IGNORELIST: @{{.*}}extra_global{{.*}}.hwasan{{.*}} = + +// IGNORELIST: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[DISABLE_INSTR_GLOBAL:[0-9]+]], ![[IGNORELISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} +// IGNORELIST: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} +// IGNORELIST: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} +// IGNORELIST: ![[GLOBAL]] = !{{{.*}} null, null, i1 false, i1 true} +// IGNORELIST: ![[ATTR_GLOBAL]] = !{{{.*attributed_global.*}}, null, null, i1 false, i1 true} +// IGNORELIST: ![[DISABLE_INSTR_GLOBAL]] = !{{{.*disable_instrumentation_global.*}}, null, null, i1 false, i1 true} +// IGNORELIST: ![[IGNORELISTED_GLOBAL]] = !{{{.*ignorelisted_global.*}}, null, null, i1 false, i1 true} +// IGNORELIST: ![[STATIC_VAR]] = !{{{.*}} null, null, i1 false, i1 true} +// IGNORELIST: ![[LITERAL]] = !{{{.*}} null, null, i1 false, i1 true} diff --git a/clang/test/CodeGen/memtag-globals.cpp b/clang/test/CodeGen/memtag-globals.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/memtag-globals.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -include %S/Inputs/sanitizer-extra-source.cpp \ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-ignorelist-global.txt \ +// RUN: -fsanitize=memtag-globals -emit-llvm -o - %s | FileCheck %s + +// RUN: %clang_cc1 -include %S/Inputs/sanitizer-extra-source.cpp \ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-ignorelist-src.txt \ +// RUN: -fsanitize=memtag-globals -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefix=IGNORELIST + +int global; +int __attribute__((no_sanitize("memtag"))) attributed_global; +int __attribute__((disable_sanitizer_instrumentation)) disable_instrumentation_global; +int ignorelisted_global; + +void func() { + static int static_var = 0; + const char *literal = "Hello, world!"; +} + +// CHECK: @{{.*}}extra_global{{.*}} = +// CHECK-NOT: no_sanitize_memtag +// CHECK: @{{.*}}global{{.*}} = +// CHECK-NOT: no_sanitize_memtag +// CHECK: @{{.*}}attributed_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_memtag +// CHECK: @{{.*}}disable_instrumentation_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_memtag +// CHECK: @{{.*}}ignorelisted_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_memtag +// CHECK: @{{.*}}static_var{{.*}} = +// CHECK-NOT: no_sanitize_memtag +// CHECK: @{{.*}} = {{.*}} c"Hello, world!\00" +// CHECK-NOT: no_sanitize_memtag + +// CHECK: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[DISABLE_INSTR_GLOBAL:[0-9]+]], ![[IGNORELISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} +// CHECK: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} +// CHECK: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} +// CHECK: ![[GLOBAL]] = !{{{.*}} ![[GLOBAL_LOC:[0-9]+]], !"global", i1 false, i1 false} +// CHECK: ![[GLOBAL_LOC]] = !{!"{{.*}}memtag-globals.cpp", i32 10, i32 5} +// CHECK: ![[ATTR_GLOBAL]] = !{{{.*attributed_global.*}}, null, null, i1 false, i1 true} +// CHECK: ![[DISABLE_INSTR_GLOBAL]] = !{{{.*disable_instrumentation_global.*}}, null, null, i1 false, i1 true} +// CHECK: ![[IGNORELISTED_GLOBAL]] = !{{{.*ignorelisted_global.*}}, null, null, i1 false, i1 true} +// CHECK: ![[STATIC_VAR]] = !{{{.*}} ![[STATIC_LOC:[0-9]+]], !"static_var", i1 false, i1 false} +// CHECK: ![[STATIC_LOC]] = !{!"{{.*}}memtag-globals.cpp", i32 16, i32 14} +// CHECK: ![[LITERAL]] = !{{{.*}} ![[LITERAL_LOC:[0-9]+]], !"", i1 false, i1 false} +// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}memtag-globals.cpp", i32 17, i32 25} + +// IGNORELIST: @{{.*}}extra_global{{.*}} ={{.*}} global +// IGNORELIST-NOT: no_sanitize_memtag +// IGNORELIST: @{{.*}}global{{.*}} ={{.*}} global {{.*}}, no_sanitize_memtag +// IGNORELIST: @{{.*}}attributed_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_memtag +// IGNORELIST: @{{.*}}disable_instrumentation_global{{.*}} ={{.*}} global {{.*}}, no_sanitize_memtag +// IGNORELIST: @{{.*}}ignorelisted_globa{{.*}} ={{.*}} global {{.*}}, no_sanitize_memtag +// IGNORELIST: @{{.*}}static_var{{.*}} ={{.*}} global {{.*}}, no_sanitize_memtag +// IGNORELIST: @{{.*}} = {{.*}} c"Hello, world!\00"{{.*}}, no_sanitize_memtag + +// IGNORELIST: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[DISABLE_INSTR_GLOBAL:[0-9]+]], ![[IGNORELISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} +// IGNORELIST: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} +// IGNORELIST: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} +// IGNORELIST: ![[GLOBAL]] = !{{{.*}} null, null, i1 false, i1 true} +// IGNORELIST: ![[ATTR_GLOBAL]] = !{{{.*attributed_global.*}}, null, null, i1 false, i1 true} +// IGNORELIST: ![[DISABLE_INSTR_GLOBAL]] = !{{{.*disable_instrumentation_global.*}}, null, null, i1 false, i1 true} +// IGNORELIST: ![[IGNORELISTED_GLOBAL]] = !{{{.*ignorelisted_global.*}}, null, null, i1 false, i1 true} +// IGNORELIST: ![[STATIC_VAR]] = !{{{.*}} null, null, i1 false, i1 true} +// IGNORELIST: ![[LITERAL]] = !{{{.*}} null, null, i1 false, i1 true} diff --git a/compiler-rt/test/hwasan/TestCases/global.c b/compiler-rt/test/hwasan/TestCases/global-with-reduction.c copy from compiler-rt/test/hwasan/TestCases/global.c copy to compiler-rt/test/hwasan/TestCases/global-with-reduction.c --- a/compiler-rt/test/hwasan/TestCases/global.c +++ b/compiler-rt/test/hwasan/TestCases/global-with-reduction.c @@ -14,20 +14,37 @@ // RUN: %clang_hwasan -O2 %s -o %t // RUN: not %run %t 1 2>&1 | FileCheck --check-prefixes=CHECK,RSYM %s +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t && %run %t 0 +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t && %run %t 1 +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t -fno-pic && %run %t 1 +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t -O2 && %run %t 1 +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t -fno-pic -O2 && %run %t 1 + // REQUIRES: pointer-tagging -int x = 1; +#include -int atoi(const char *); +// GlobalOpt may replace the current GV with a new boolean-typed GV. Previously, +// this resulted in the "nosanitize" getting dropped because while the data/code +// references to the GV were updated, the old metadata references weren't. +int* f() { +#ifdef USE_NOSANITIZE +__attribute__((no_sanitize("hwaddress"))) static int x = 1; +#else // USE_NOSANITIZE + static int x = 1; +#endif // USE_NOSANITIZE + if (x == 1) x = 0; + return &x; +} int main(int argc, char **argv) { // CHECK: Cause: global-overflow - // RSYM: is located 0 bytes to the right of 4-byte global variable x {{.*}} in {{.*}}global.c.tmp + // RSYM: is located 0 bytes to the right of 4-byte global variable f.x {{.*}} in {{.*}}global-with-reduction.c.tmp // RNOSYM: is located to the right of a 4-byte global variable in - // RNOSYM-NEXT: #0 0x{{.*}} ({{.*}}global.c.tmp+{{.*}}) - // LSYM: is located 4 bytes to the left of 4-byte global variable x {{.*}} in {{.*}}global.c.tmp + // RNOSYM-NEXT: #0 0x{{.*}} ({{.*}}global-with-reduction.c.tmp+{{.*}}) + // LSYM: is located 4 bytes to the left of 4-byte global variable f.x {{.*}} in {{.*}}global-with-reduction.c.tmp // LNOSYM: is located to the left of a 4-byte global variable in - // LNOSYM-NEXT: #0 0x{{.*}} ({{.*}}global.c.tmp+{{.*}}) + // LNOSYM-NEXT: #0 0x{{.*}} ({{.*}}global-with-reduction.c.tmp+{{.*}}) // CHECK-NOT: can not describe - (&x)[atoi(argv[1])] = 1; + f()[atoi(argv[1])] = 1; } diff --git a/compiler-rt/test/hwasan/TestCases/global.c b/compiler-rt/test/hwasan/TestCases/global.c --- a/compiler-rt/test/hwasan/TestCases/global.c +++ b/compiler-rt/test/hwasan/TestCases/global.c @@ -14,9 +14,23 @@ // RUN: %clang_hwasan -O2 %s -o %t // RUN: not %run %t 1 2>&1 | FileCheck --check-prefixes=CHECK,RSYM %s +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t && %run %t 0 +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t && %run %t 1 +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t -fno-pic && %run %t 1 +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t -O2 && %run %t 1 +// RUN: %clang_hwasan -DUSE_NOSANITIZE %s -o %t -fno-pic -O2 && %run %t 1 + // REQUIRES: pointer-tagging +#include + +int a = 1; +#ifdef USE_NOSANITIZE +__attribute__((no_sanitize("hwaddress"))) int x = 1; +#else // USE_NOSANITIZE int x = 1; +#endif // USE_NOSANITIZE +int b = 1; int atoi(const char *);