Skip to content

Commit 50a524b

Browse files
[Clang][Sanitizers] Add numerical sanitizer
1 parent 1f67f34 commit 50a524b

File tree

10 files changed

+70
-2
lines changed

10 files changed

+70
-2
lines changed

clang/include/clang/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ FEATURE(nullability, true)
9696
FEATURE(nullability_on_arrays, true)
9797
FEATURE(nullability_on_classes, true)
9898
FEATURE(nullability_nullable_result, true)
99+
FEATURE(numerical_stability_sanitizer, LangOpts.Sanitize.has(SanitizerKind::NumericalStability))
99100
FEATURE(memory_sanitizer,
100101
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
101102
SanitizerKind::KernelMemory))

clang/include/clang/Basic/Sanitizers.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ SANITIZER("fuzzer-no-link", FuzzerNoLink)
7676
// ThreadSanitizer
7777
SANITIZER("thread", Thread)
7878

79+
// Numerical stability sanitizer.
80+
SANITIZER("numerical", NumericalStability)
81+
7982
// LeakSanitizer
8083
SANITIZER("leak", Leak)
8184

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ class SanitizerArgs {
103103
bool needsCfiDiagRt() const;
104104
bool needsStatsRt() const { return Stats; }
105105
bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); }
106+
bool needsNsanRt() const {
107+
return Sanitizers.has(SanitizerKind::NumericalStability);
108+
}
106109

107110
bool hasMemTag() const {
108111
return hasMemtagHeap() || hasMemtagStack() || hasMemtagGlobals();

clang/lib/CodeGen/CGDeclCXX.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
476476
!isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
477477
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
478478

479+
if (getLangOpts().Sanitize.has(SanitizerKind::NumericalStability) &&
480+
!isInNoSanitizeList(SanitizerKind::NumericalStability, Fn, Loc))
481+
Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
482+
479483
if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&
480484
!isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc))
481485
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
818818
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
819819
if (SanOpts.has(SanitizerKind::Thread))
820820
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
821+
if (SanOpts.has(SanitizerKind::NumericalStability))
822+
Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
821823
if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory))
822824
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
823825
}

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ static const SanitizerMask NotAllowedWithExecuteOnly =
4141
SanitizerKind::Function | SanitizerKind::KCFI;
4242
static const SanitizerMask NeedsUnwindTables =
4343
SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
44-
SanitizerKind::Memory | SanitizerKind::DataFlow;
44+
SanitizerKind::Memory | SanitizerKind::DataFlow |
45+
SanitizerKind::NumericalStability;
4546
static const SanitizerMask SupportsCoverage =
4647
SanitizerKind::Address | SanitizerKind::HWAddress |
4748
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
@@ -53,7 +54,8 @@ static const SanitizerMask SupportsCoverage =
5354
SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
5455
SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
5556
SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
56-
SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI;
57+
SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
58+
SanitizerKind::NumericalStability;
5759
static const SanitizerMask RecoverableByDefault =
5860
SanitizerKind::Undefined | SanitizerKind::Integer |
5961
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
@@ -175,6 +177,7 @@ static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
175177
{"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
176178
{"memtag_ignorelist.txt", SanitizerKind::MemTag},
177179
{"msan_ignorelist.txt", SanitizerKind::Memory},
180+
{"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
178181
{"tsan_ignorelist.txt", SanitizerKind::Thread},
179182
{"dfsan_abilist.txt", SanitizerKind::DataFlow},
180183
{"cfi_ignorelist.txt", SanitizerKind::CFI},

clang/lib/Driver/ToolChains/Linux.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,10 @@ SanitizerMask Linux::getSupportedSanitizers() const {
826826
if (IsX86_64 || IsAArch64) {
827827
Res |= SanitizerKind::KernelHWAddress;
828828
}
829+
if (IsX86_64) {
830+
Res |= SanitizerKind::NumericalStability;
831+
}
832+
829833
// Work around "Cannot represent a difference across sections".
830834
if (getTriple().getArch() == llvm::Triple::ppc64)
831835
Res &= ~SanitizerKind::Function;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
2+
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=numerical | FileCheck -check-prefix=NSAN %s
3+
// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t
4+
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=numerical -fsanitize-ignorelist=%t | FileCheck -check-prefix=BL %s
5+
6+
// WITHOUT: NoNSAN3{{.*}}) [[NOATTR:#[0-9]+]]
7+
// BL: NoNSAN3{{.*}}) [[NOATTR:#[0-9]+]]
8+
// NSAN: NoNSAN3{{.*}}) [[NOATTR:#[0-9]+]]
9+
__attribute__((no_sanitize("numerical")))
10+
int NoNSAN3(int *a) { return *a; }
11+
12+
// WITHOUT: NSANOk{{.*}}) [[NOATTR]]
13+
// BL: NSANOk{{.*}}) [[NOATTR]]
14+
// NSAN: NSANOk{{.*}}) [[WITH:#[0-9]+]]
15+
int NSANOk(int *a) { return *a; }
16+
17+
// WITHOUT: TemplateNSANOk{{.*}}) [[NOATTR]]
18+
// BL: TemplateNSANOk{{.*}}) [[NOATTR]]
19+
// NSAN: TemplateNSANOk{{.*}}) [[WITH]]
20+
template<int i>
21+
int TemplateNSANOk() { return i; }
22+
23+
// WITHOUT: TemplateNoNSAN{{.*}}) [[NOATTR]]
24+
// BL: TemplateNoNSAN{{.*}}) [[NOATTR]]
25+
// NSAN: TemplateNoNSAN{{.*}}) [[NOATTR]]
26+
template<int i>
27+
__attribute__((no_sanitize("numerical")))
28+
int TemplateNoNSAN() { return i; }
29+
30+
int force_instance = TemplateNSANOk<42>() + TemplateNoNSAN<42>();
31+
32+
// WITHOUT: attributes [[NOATTR]] = { mustprogress noinline nounwind{{.*}} }
33+
// BL: attributes [[NOATTR]] = { mustprogress noinline nounwind{{.*}} }
34+
// NSAN: attributes [[WITH]] = { mustprogress noinline nounwind optnone sanitize_numerical_stability{{.*}} }
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -E -fsanitize=numerical %s -o - | FileCheck --check-prefix=CHECK-NSAN %s
2+
// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-NSAN %s
3+
4+
#if __has_feature(numerical_stability_sanitizer)
5+
int NumericalStabilitySanitizerEnabled();
6+
#else
7+
int NumericalStabilitySanitizerDisabled();
8+
#endif
9+
10+
// CHECK-NSAN: NumericalStabilitySanitizerEnabled
11+
// CHECK-NO-NSAN: NumericalStabilitySanitizerDisabled

llvm/include/llvm/IR/Attributes.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress", [FnAttr]>;
285285
/// MemTagSanitizer is on.
286286
def SanitizeMemTag : EnumAttr<"sanitize_memtag", [FnAttr]>;
287287

288+
/// NumericalStabilitySanitizer is on.
289+
def SanitizeNumericalStability : EnumAttr<"sanitize_numerical_stability", [FnAttr]>;
290+
288291
/// Speculative Load Hardening is enabled.
289292
///
290293
/// Note that this uses the default compatibility (always compatible during

0 commit comments

Comments
 (0)