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); @@ -8876,7 +8881,7 @@ case ParsedAttr::AT_Thread: handleDeclspecThreadAttr(S, D, AL); break; - + // HLSL attributes: case ParsedAttr::AT_HLSLNumThreads: handleHLSLNumThreadsAttr(S, D, AL); 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,55 @@ +// RUN: echo "int extra_global;" > %t.extra-source.cpp +// RUN: echo "global:*ignorelisted_global*" > %t.ignorelist +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=hwaddress -fsanitize-ignorelist=%t.ignorelist -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK +// The ignorelist file uses regexps, so Windows path backslashes. +// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.ignorelist-src +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=hwaddress -fsanitize-ignorelist=%t.ignorelist-src -emit-llvm -o - %s | 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 8, 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 14, i32 14} +// CHECK: ![[LITERAL]] = !{{{.*}} ![[LITERAL_LOC:[0-9]+]], !"", i1 false, i1 false} +// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}hwasan-globals.cpp", i32 15, 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,60 @@ +// RUN: echo "int extra_global;" > %t.extra-source.cpp +// RUN: echo "global:*ignorelisted_global*" > %t.ignorelist +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=memtag-globals -fsanitize-ignorelist=%t.ignorelist -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK +// The ignorelist file uses regexps, so Windows path backslashes. +// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.ignorelist-src +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=memtag-globals -fsanitize-ignorelist=%t.ignorelist-src -emit-llvm -o - %s | 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 8, 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 14, i32 14} +// CHECK: ![[LITERAL]] = !{{{.*}} ![[LITERAL_LOC:[0-9]+]], !"", i1 false, i1 false} +// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}memtag-globals.cpp", i32 15, 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 *);