[clang] 48f8130 - [Clang][Sanitizers] Add numerical sanitizer (#93783)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 10 22:14:30 PDT 2024
Author: Alexander Shaposhnikov
Date: 2024-06-10T22:14:26-07:00
New Revision: 48f8130a49aad715ff6d5136dad2447d41e9537b
URL: https://github.com/llvm/llvm-project/commit/48f8130a49aad715ff6d5136dad2447d41e9537b
DIFF: https://github.com/llvm/llvm-project/commit/48f8130a49aad715ff6d5136dad2447d41e9537b.diff
LOG: [Clang][Sanitizers] Add numerical sanitizer (#93783)
Add plumbing for the numerical sanitizer on Clang's side.
Added:
clang/test/CodeGen/sanitize-numerical-stability-attr.cpp
clang/test/Lexer/has_feature_numerical_stability_sanitizer.cpp
Modified:
clang/include/clang/Basic/Features.def
clang/include/clang/Basic/Sanitizers.def
clang/include/clang/Driver/SanitizerArgs.h
clang/lib/CodeGen/CGDeclCXX.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/Driver/SanitizerArgs.cpp
clang/lib/Driver/ToolChains/Darwin.cpp
clang/lib/Driver/ToolChains/Linux.cpp
clang/test/Driver/fsanitize.c
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index b762e44e755ec..53f410d3cb4bd 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -96,6 +96,7 @@ FEATURE(nullability, true)
FEATURE(nullability_on_arrays, true)
FEATURE(nullability_on_classes, true)
FEATURE(nullability_nullable_result, true)
+FEATURE(numerical_stability_sanitizer, LangOpts.Sanitize.has(SanitizerKind::NumericalStability))
FEATURE(memory_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
SanitizerKind::KernelMemory))
diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def
index b228ffd07ee74..bee35e9dca7c3 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -76,6 +76,9 @@ SANITIZER("fuzzer-no-link", FuzzerNoLink)
// ThreadSanitizer
SANITIZER("thread", Thread)
+// Numerical stability sanitizer.
+SANITIZER("numerical", NumericalStability)
+
// LeakSanitizer
SANITIZER("leak", Leak)
diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h
index 07070ec4fc065..47ef175302679 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -103,6 +103,9 @@ class SanitizerArgs {
bool needsCfiDiagRt() const;
bool needsStatsRt() const { return Stats; }
bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); }
+ bool needsNsanRt() const {
+ return Sanitizers.has(SanitizerKind::NumericalStability);
+ }
bool hasMemTag() const {
return hasMemtagHeap() || hasMemtagStack() || hasMemtagGlobals();
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index b047279912f6b..a88bb2af59fee 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -476,6 +476,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
!isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
+ if (getLangOpts().Sanitize.has(SanitizerKind::NumericalStability) &&
+ !isInNoSanitizeList(SanitizerKind::NumericalStability, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
+
if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&
!isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index f84b3b08220fd..cea0d84c64bc4 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -818,6 +818,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
if (SanOpts.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
+ if (SanOpts.has(SanitizerKind::NumericalStability))
+ Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
}
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 273f215ca94a8..86825a6ccf7a1 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -41,7 +41,8 @@ static const SanitizerMask NotAllowedWithExecuteOnly =
SanitizerKind::Function | SanitizerKind::KCFI;
static const SanitizerMask NeedsUnwindTables =
SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
- SanitizerKind::Memory | SanitizerKind::DataFlow;
+ SanitizerKind::Memory | SanitizerKind::DataFlow |
+ SanitizerKind::NumericalStability;
static const SanitizerMask SupportsCoverage =
SanitizerKind::Address | SanitizerKind::HWAddress |
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
@@ -53,7 +54,8 @@ static const SanitizerMask SupportsCoverage =
SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
- SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI;
+ SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
+ SanitizerKind::NumericalStability;
static const SanitizerMask RecoverableByDefault =
SanitizerKind::Undefined | SanitizerKind::Integer |
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
@@ -175,6 +177,7 @@ static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
{"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
{"memtag_ignorelist.txt", SanitizerKind::MemTag},
{"msan_ignorelist.txt", SanitizerKind::Memory},
+ {"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
{"tsan_ignorelist.txt", SanitizerKind::Thread},
{"dfsan_abilist.txt", SanitizerKind::DataFlow},
{"cfi_ignorelist.txt", SanitizerKind::CFI},
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 593b403a1e3f0..ed5737915aa96 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -3448,6 +3448,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
Res |= SanitizerKind::PointerCompare;
Res |= SanitizerKind::PointerSubtract;
Res |= SanitizerKind::Leak;
+ Res |= SanitizerKind::NumericalStability;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
Res |= SanitizerKind::ObjCCast;
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index db2c20d7b461d..2c583ac724a2a 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -826,6 +826,9 @@ SanitizerMask Linux::getSupportedSanitizers() const {
if (IsX86_64 || IsAArch64) {
Res |= SanitizerKind::KernelHWAddress;
}
+ if (IsX86_64 || IsAArch64)
+ Res |= SanitizerKind::NumericalStability;
+
// Work around "Cannot represent a
diff erence across sections".
if (getTriple().getArch() == llvm::Triple::ppc64)
Res &= ~SanitizerKind::Function;
diff --git a/clang/test/CodeGen/sanitize-numerical-stability-attr.cpp b/clang/test/CodeGen/sanitize-numerical-stability-attr.cpp
new file mode 100644
index 0000000000000..f51fb79bda6af
--- /dev/null
+++ b/clang/test/CodeGen/sanitize-numerical-stability-attr.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=numerical | FileCheck -check-prefix=NSAN %s
+// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=numerical -fsanitize-ignorelist=%t | FileCheck -check-prefix=BL %s
+
+// WITHOUT: NoNSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+// BL: NoNSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+// NSAN: NoNSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+__attribute__((no_sanitize("numerical")))
+int NoNSAN3(int *a) { return *a; }
+
+// WITHOUT: NSANOk{{.*}}) [[NOATTR]]
+// BL: NSANOk{{.*}}) [[NOATTR]]
+// NSAN: NSANOk{{.*}}) [[WITH:#[0-9]+]]
+int NSANOk(int *a) { return *a; }
+
+// WITHOUT: TemplateNSANOk{{.*}}) [[NOATTR]]
+// BL: TemplateNSANOk{{.*}}) [[NOATTR]]
+// NSAN: TemplateNSANOk{{.*}}) [[WITH]]
+template<int i>
+int TemplateNSANOk() { return i; }
+
+// WITHOUT: TemplateNoNSAN{{.*}}) [[NOATTR]]
+// BL: TemplateNoNSAN{{.*}}) [[NOATTR]]
+// NSAN: TemplateNoNSAN{{.*}}) [[NOATTR]]
+template<int i>
+__attribute__((no_sanitize("numerical")))
+int TemplateNoNSAN() { return i; }
+
+int force_instance = TemplateNSANOk<42>() + TemplateNoNSAN<42>();
+
+// WITHOUT: attributes [[NOATTR]] = { mustprogress noinline nounwind{{.*}} }
+// BL: attributes [[NOATTR]] = { mustprogress noinline nounwind{{.*}} }
+// NSAN: attributes [[WITH]] = { mustprogress noinline nounwind optnone sanitize_numerical_stability{{.*}} }
diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c
index 571f79a6e7f70..ba64b3dcb11aa 100644
--- a/clang/test/Driver/fsanitize.c
+++ b/clang/test/Driver/fsanitize.c
@@ -459,6 +459,21 @@
// CHECK-TSAN-MSAN-MSAN-DARWIN: unsupported option '-fsanitize=memory' for target 'x86_64-apple-darwin10'
// CHECK-TSAN-MSAN-MSAN-DARWIN-NOT: unsupported option
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=numerical %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NSAN-X86-64-LINUX
+// CHECK-NSAN-X86-64-LINUX: "-fsanitize=numerical"
+
+// RUN: %clang --target=aarch64-unknown-linux-gnu -fsanitize=numerical %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NSAN-AARCH64-LINUX
+// CHECK-NSAN-AARCH64-LINUX: "-fsanitize=numerical"
+
+// RUN: not %clang --target=mips-unknown-linux -fsanitize=numerical %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NSAN-MIPS-LINUX
+// CHECK-NSAN-MIPS-LINUX: error: unsupported option '-fsanitize=numerical' for target 'mips-unknown-linux'
+
+// RUN: %clang --target=x86_64-apple-macos -fsanitize=numerical %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NSAN-X86-64-MACOS
+// CHECK-NSAN-X86-64-MACOS: "-fsanitize=numerical"
+
+// RUN: %clang --target=arm64-apple-macos -fsanitize=numerical %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NSAN-ARM64-MACOS
+// CHECK-NSAN-ARM64-MACOS: "-fsanitize=numerical"
+
// RUN: %clang --target=x86_64-apple-darwin -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-DARWIN
// CHECK-TSAN-X86-64-DARWIN-NOT: unsupported option
// RUN: %clang --target=x86_64-apple-macos -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-MACOS
diff --git a/clang/test/Lexer/has_feature_numerical_stability_sanitizer.cpp b/clang/test/Lexer/has_feature_numerical_stability_sanitizer.cpp
new file mode 100644
index 0000000000000..78884977322b8
--- /dev/null
+++ b/clang/test/Lexer/has_feature_numerical_stability_sanitizer.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -E -fsanitize=numerical %s -o - | FileCheck --check-prefix=CHECK-NSAN %s
+// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-NSAN %s
+
+#if __has_feature(numerical_stability_sanitizer)
+int NumericalStabilitySanitizerEnabled();
+#else
+int NumericalStabilitySanitizerDisabled();
+#endif
+
+// CHECK-NSAN: NumericalStabilitySanitizerEnabled
+// CHECK-NO-NSAN: NumericalStabilitySanitizerDisabled
More information about the cfe-commits
mailing list