1 //===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 #include "clang/Driver/SanitizerArgs.h"
9 #include "ToolChains/CommonArgs.h"
10 #include "clang/Basic/Sanitizers.h"
11 #include "clang/Driver/Driver.h"
12 #include "clang/Driver/DriverDiagnostic.h"
13 #include "clang/Driver/Options.h"
14 #include "clang/Driver/ToolChain.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/SpecialCaseList.h"
20 #include "llvm/Support/VirtualFileSystem.h"
21 #include "llvm/TargetParser/AArch64TargetParser.h"
22 #include "llvm/TargetParser/RISCVTargetParser.h"
23 #include "llvm/TargetParser/TargetParser.h"
24 #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
27 using namespace clang
;
28 using namespace clang::driver
;
29 using namespace llvm::opt
;
31 static const SanitizerMask NeedsUbsanRt
=
32 SanitizerKind::Undefined
| SanitizerKind::Integer
|
33 SanitizerKind::ImplicitConversion
| SanitizerKind::Nullability
|
34 SanitizerKind::CFI
| SanitizerKind::FloatDivideByZero
|
35 SanitizerKind::ObjCCast
;
36 static const SanitizerMask NeedsUbsanCxxRt
=
37 SanitizerKind::Vptr
| SanitizerKind::CFI
;
38 static const SanitizerMask NotAllowedWithTrap
= SanitizerKind::Vptr
;
39 static const SanitizerMask NotAllowedWithMinimalRuntime
= SanitizerKind::Vptr
;
40 static const SanitizerMask NotAllowedWithExecuteOnly
=
41 SanitizerKind::Function
| SanitizerKind::KCFI
;
42 static const SanitizerMask RequiresPIE
=
43 SanitizerKind::DataFlow
| SanitizerKind::Scudo
;
44 static const SanitizerMask NeedsUnwindTables
=
45 SanitizerKind::Address
| SanitizerKind::HWAddress
| SanitizerKind::Thread
|
46 SanitizerKind::Memory
| SanitizerKind::DataFlow
;
47 static const SanitizerMask SupportsCoverage
=
48 SanitizerKind::Address
| SanitizerKind::HWAddress
|
49 SanitizerKind::KernelAddress
| SanitizerKind::KernelHWAddress
|
50 SanitizerKind::MemtagStack
| SanitizerKind::MemtagHeap
|
51 SanitizerKind::MemtagGlobals
| SanitizerKind::Memory
|
52 SanitizerKind::KernelMemory
| SanitizerKind::Leak
|
53 SanitizerKind::Undefined
| SanitizerKind::Integer
| SanitizerKind::Bounds
|
54 SanitizerKind::ImplicitConversion
| SanitizerKind::Nullability
|
55 SanitizerKind::DataFlow
| SanitizerKind::Fuzzer
|
56 SanitizerKind::FuzzerNoLink
| SanitizerKind::FloatDivideByZero
|
57 SanitizerKind::SafeStack
| SanitizerKind::ShadowCallStack
|
58 SanitizerKind::Thread
| SanitizerKind::ObjCCast
| SanitizerKind::KCFI
;
59 static const SanitizerMask RecoverableByDefault
=
60 SanitizerKind::Undefined
| SanitizerKind::Integer
|
61 SanitizerKind::ImplicitConversion
| SanitizerKind::Nullability
|
62 SanitizerKind::FloatDivideByZero
| SanitizerKind::ObjCCast
;
63 static const SanitizerMask Unrecoverable
=
64 SanitizerKind::Unreachable
| SanitizerKind::Return
;
65 static const SanitizerMask AlwaysRecoverable
= SanitizerKind::KernelAddress
|
66 SanitizerKind::KernelHWAddress
|
68 static const SanitizerMask NeedsLTO
= SanitizerKind::CFI
;
69 static const SanitizerMask TrappingSupported
=
70 (SanitizerKind::Undefined
& ~SanitizerKind::Vptr
) | SanitizerKind::Integer
|
71 SanitizerKind::Nullability
| SanitizerKind::LocalBounds
|
72 SanitizerKind::CFI
| SanitizerKind::FloatDivideByZero
|
73 SanitizerKind::ObjCCast
;
74 static const SanitizerMask TrappingDefault
= SanitizerKind::CFI
;
75 static const SanitizerMask CFIClasses
=
76 SanitizerKind::CFIVCall
| SanitizerKind::CFINVCall
|
77 SanitizerKind::CFIMFCall
| SanitizerKind::CFIDerivedCast
|
78 SanitizerKind::CFIUnrelatedCast
;
79 static const SanitizerMask CompatibleWithMinimalRuntime
=
80 TrappingSupported
| SanitizerKind::Scudo
| SanitizerKind::ShadowCallStack
|
81 SanitizerKind::MemtagStack
| SanitizerKind::MemtagHeap
|
82 SanitizerKind::MemtagGlobals
| SanitizerKind::KCFI
;
84 enum CoverageFeature
{
85 CoverageFunc
= 1 << 0,
87 CoverageEdge
= 1 << 2,
88 CoverageIndirCall
= 1 << 3,
89 CoverageTraceBB
= 1 << 4, // Deprecated.
90 CoverageTraceCmp
= 1 << 5,
91 CoverageTraceDiv
= 1 << 6,
92 CoverageTraceGep
= 1 << 7,
93 Coverage8bitCounters
= 1 << 8, // Deprecated.
94 CoverageTracePC
= 1 << 9,
95 CoverageTracePCGuard
= 1 << 10,
96 CoverageNoPrune
= 1 << 11,
97 CoverageInline8bitCounters
= 1 << 12,
98 CoveragePCTable
= 1 << 13,
99 CoverageStackDepth
= 1 << 14,
100 CoverageInlineBoolFlag
= 1 << 15,
101 CoverageTraceLoads
= 1 << 16,
102 CoverageTraceStores
= 1 << 17,
103 CoverageControlFlow
= 1 << 18,
106 enum BinaryMetadataFeature
{
107 BinaryMetadataCovered
= 1 << 0,
108 BinaryMetadataAtomics
= 1 << 1,
109 BinaryMetadataUAR
= 1 << 2,
112 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
113 /// invalid components. Returns a SanitizerMask.
114 static SanitizerMask
parseArgValues(const Driver
&D
, const llvm::opt::Arg
*A
,
115 bool DiagnoseErrors
);
117 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
118 /// components. Returns OR of members of \c CoverageFeature enumeration.
119 static int parseCoverageFeatures(const Driver
&D
, const llvm::opt::Arg
*A
,
120 bool DiagnoseErrors
);
122 /// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid
123 /// components. Returns OR of members of \c BinaryMetadataFeature enumeration.
124 static int parseBinaryMetadataFeatures(const Driver
&D
, const llvm::opt::Arg
*A
,
125 bool DiagnoseErrors
);
127 /// Produce an argument string from ArgList \p Args, which shows how it
128 /// provides some sanitizer kind from \p Mask. For example, the argument list
129 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
130 /// would produce "-fsanitize=vptr".
131 static std::string
lastArgumentForMask(const Driver
&D
,
132 const llvm::opt::ArgList
&Args
,
135 /// Produce an argument string from argument \p A, which shows how it provides
136 /// a value in \p Mask. For instance, the argument
137 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
138 /// "-fsanitize=alignment".
139 static std::string
describeSanitizeArg(const llvm::opt::Arg
*A
,
142 /// Produce a string containing comma-separated names of sanitizers in \p
144 static std::string
toString(const clang::SanitizerSet
&Sanitizers
);
146 /// Return true if an execute-only target disallows data access to code
148 static bool isExecuteOnlyTarget(const llvm::Triple
&Triple
,
149 const llvm::opt::ArgList
&Args
) {
152 return Args
.hasFlagNoClaim(options::OPT_mexecute_only
,
153 options::OPT_mno_execute_only
, false);
156 static void validateSpecialCaseListFormat(const Driver
&D
,
157 std::vector
<std::string
> &SCLFiles
,
158 unsigned MalformedSCLErrorDiagID
,
159 bool DiagnoseErrors
) {
160 if (SCLFiles
.empty())
164 std::unique_ptr
<llvm::SpecialCaseList
> SCL(
165 llvm::SpecialCaseList::create(SCLFiles
, D
.getVFS(), BLError
));
166 if (!SCL
.get() && DiagnoseErrors
)
167 D
.Diag(MalformedSCLErrorDiagID
) << BLError
;
170 static void addDefaultIgnorelists(const Driver
&D
, SanitizerMask Kinds
,
171 std::vector
<std::string
> &IgnorelistFiles
,
172 bool DiagnoseErrors
) {
176 } Ignorelists
[] = {{"asan_ignorelist.txt", SanitizerKind::Address
},
177 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress
},
178 {"memtag_ignorelist.txt", SanitizerKind::MemTag
},
179 {"msan_ignorelist.txt", SanitizerKind::Memory
},
180 {"tsan_ignorelist.txt", SanitizerKind::Thread
},
181 {"dfsan_abilist.txt", SanitizerKind::DataFlow
},
182 {"cfi_ignorelist.txt", SanitizerKind::CFI
},
183 {"ubsan_ignorelist.txt",
184 SanitizerKind::Undefined
| SanitizerKind::Integer
|
185 SanitizerKind::Nullability
|
186 SanitizerKind::FloatDivideByZero
}};
188 for (auto BL
: Ignorelists
) {
189 if (!(Kinds
& BL
.Mask
))
192 clang::SmallString
<64> Path(D
.ResourceDir
);
193 llvm::sys::path::append(Path
, "share", BL
.File
);
194 if (D
.getVFS().exists(Path
))
195 IgnorelistFiles
.push_back(std::string(Path
.str()));
196 else if (BL
.Mask
== SanitizerKind::CFI
&& DiagnoseErrors
)
197 // If cfi_ignorelist.txt cannot be found in the resource dir, driver
199 D
.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist
) << Path
;
201 validateSpecialCaseListFormat(
202 D
, IgnorelistFiles
, clang::diag::err_drv_malformed_sanitizer_ignorelist
,
206 /// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,
207 /// diagnosing any invalid file paths and validating special case list format.
208 static void parseSpecialCaseListArg(const Driver
&D
,
209 const llvm::opt::ArgList
&Args
,
210 std::vector
<std::string
> &SCLFiles
,
211 llvm::opt::OptSpecifier SCLOptionID
,
212 llvm::opt::OptSpecifier NoSCLOptionID
,
213 unsigned MalformedSCLErrorDiagID
,
214 bool DiagnoseErrors
) {
215 for (const auto *Arg
: Args
) {
216 // Match -fsanitize-(coverage-)?(allow|ignore)list.
217 if (Arg
->getOption().matches(SCLOptionID
)) {
219 std::string SCLPath
= Arg
->getValue();
220 if (D
.getVFS().exists(SCLPath
)) {
221 SCLFiles
.push_back(SCLPath
);
222 } else if (DiagnoseErrors
) {
223 D
.Diag(clang::diag::err_drv_no_such_file
) << SCLPath
;
225 // Match -fno-sanitize-ignorelist.
226 } else if (Arg
->getOption().matches(NoSCLOptionID
)) {
231 validateSpecialCaseListFormat(D
, SCLFiles
, MalformedSCLErrorDiagID
,
235 /// Sets group bits for every group that has at least one representative already
236 /// enabled in \p Kinds.
237 static SanitizerMask
setGroupBits(SanitizerMask Kinds
) {
238 #define SANITIZER(NAME, ID)
239 #define SANITIZER_GROUP(NAME, ID, ALIAS) \
240 if (Kinds & SanitizerKind::ID) \
241 Kinds |= SanitizerKind::ID##Group;
242 #include "clang/Basic/Sanitizers.def"
246 static SanitizerMask
parseSanitizeTrapArgs(const Driver
&D
,
247 const llvm::opt::ArgList
&Args
,
248 bool DiagnoseErrors
) {
249 SanitizerMask TrapRemove
; // During the loop below, the accumulated set of
250 // sanitizers disabled by the current sanitizer
251 // argument or any argument after it.
252 SanitizerMask TrappingKinds
;
253 SanitizerMask TrappingSupportedWithGroups
= setGroupBits(TrappingSupported
);
255 for (const llvm::opt::Arg
*Arg
: llvm::reverse(Args
)) {
256 if (Arg
->getOption().matches(options::OPT_fsanitize_trap_EQ
)) {
258 SanitizerMask Add
= parseArgValues(D
, Arg
, true);
260 SanitizerMask InvalidValues
= Add
& ~TrappingSupportedWithGroups
;
261 if (InvalidValues
&& DiagnoseErrors
) {
263 S
.Mask
= InvalidValues
;
264 D
.Diag(diag::err_drv_unsupported_option_argument
)
265 << Arg
->getSpelling() << toString(S
);
267 TrappingKinds
|= expandSanitizerGroups(Add
) & ~TrapRemove
;
268 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_trap_EQ
)) {
271 expandSanitizerGroups(parseArgValues(D
, Arg
, DiagnoseErrors
));
275 // Apply default trapping behavior.
276 TrappingKinds
|= TrappingDefault
& ~TrapRemove
;
278 return TrappingKinds
;
281 bool SanitizerArgs::needsFuzzerInterceptors() const {
282 return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
285 bool SanitizerArgs::needsUbsanRt() const {
286 // All of these include ubsan.
287 if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
288 needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
289 (needsScudoRt() && !requiresMinimalRuntime()))
292 return (Sanitizers
.Mask
& NeedsUbsanRt
& ~TrapSanitizers
.Mask
) ||
296 bool SanitizerArgs::needsCfiRt() const {
297 return !(Sanitizers
.Mask
& SanitizerKind::CFI
& ~TrapSanitizers
.Mask
) &&
298 CfiCrossDso
&& !ImplicitCfiRuntime
;
301 bool SanitizerArgs::needsCfiDiagRt() const {
302 return (Sanitizers
.Mask
& SanitizerKind::CFI
& ~TrapSanitizers
.Mask
) &&
303 CfiCrossDso
&& !ImplicitCfiRuntime
;
306 bool SanitizerArgs::requiresPIE() const {
307 return NeedPIE
|| (Sanitizers
.Mask
& RequiresPIE
);
310 bool SanitizerArgs::needsUnwindTables() const {
311 return static_cast<bool>(Sanitizers
.Mask
& NeedsUnwindTables
);
314 bool SanitizerArgs::needsLTO() const {
315 return static_cast<bool>(Sanitizers
.Mask
& NeedsLTO
);
318 SanitizerArgs::SanitizerArgs(const ToolChain
&TC
,
319 const llvm::opt::ArgList
&Args
,
320 bool DiagnoseErrors
) {
321 SanitizerMask AllRemove
; // During the loop below, the accumulated set of
322 // sanitizers disabled by the current sanitizer
323 // argument or any argument after it.
324 SanitizerMask AllAddedKinds
; // Mask of all sanitizers ever enabled by
325 // -fsanitize= flags (directly or via group
326 // expansion), some of which may be disabled
327 // later. Used to carefully prune
328 // unused-argument diagnostics.
329 SanitizerMask DiagnosedKinds
; // All Kinds we have diagnosed up to now.
330 // Used to deduplicate diagnostics.
332 const SanitizerMask Supported
= setGroupBits(TC
.getSupportedSanitizers());
334 CfiCrossDso
= Args
.hasFlag(options::OPT_fsanitize_cfi_cross_dso
,
335 options::OPT_fno_sanitize_cfi_cross_dso
, false);
337 ToolChain::RTTIMode RTTIMode
= TC
.getRTTIMode();
339 const Driver
&D
= TC
.getDriver();
340 SanitizerMask TrappingKinds
= parseSanitizeTrapArgs(D
, Args
, DiagnoseErrors
);
341 SanitizerMask InvalidTrappingKinds
= TrappingKinds
& NotAllowedWithTrap
;
344 Args
.hasFlag(options::OPT_fsanitize_minimal_runtime
,
345 options::OPT_fno_sanitize_minimal_runtime
, MinimalRuntime
);
347 // The object size sanitizer should not be enabled at -O0.
348 Arg
*OptLevel
= Args
.getLastArg(options::OPT_O_Group
);
349 bool RemoveObjectSizeAtO0
=
350 !OptLevel
|| OptLevel
->getOption().matches(options::OPT_O0
);
352 for (const llvm::opt::Arg
*Arg
: llvm::reverse(Args
)) {
353 if (Arg
->getOption().matches(options::OPT_fsanitize_EQ
)) {
355 SanitizerMask Add
= parseArgValues(D
, Arg
, DiagnoseErrors
);
357 if (RemoveObjectSizeAtO0
) {
358 AllRemove
|= SanitizerKind::ObjectSize
;
360 // The user explicitly enabled the object size sanitizer. Warn
361 // that this does nothing at -O0.
362 if ((Add
& SanitizerKind::ObjectSize
) && DiagnoseErrors
)
363 D
.Diag(diag::warn_drv_object_size_disabled_O0
)
364 << Arg
->getAsString(Args
);
367 AllAddedKinds
|= expandSanitizerGroups(Add
);
369 // Avoid diagnosing any sanitizer which is disabled later.
371 // At this point we have not expanded groups, so any unsupported
372 // sanitizers in Add are those which have been explicitly enabled.
374 if (SanitizerMask KindsToDiagnose
=
375 Add
& InvalidTrappingKinds
& ~DiagnosedKinds
) {
376 if (DiagnoseErrors
) {
377 std::string Desc
= describeSanitizeArg(Arg
, KindsToDiagnose
);
378 D
.Diag(diag::err_drv_argument_not_allowed_with
)
379 << Desc
<< "-fsanitize-trap=undefined";
381 DiagnosedKinds
|= KindsToDiagnose
;
383 Add
&= ~InvalidTrappingKinds
;
385 if (MinimalRuntime
) {
386 if (SanitizerMask KindsToDiagnose
=
387 Add
& NotAllowedWithMinimalRuntime
& ~DiagnosedKinds
) {
388 if (DiagnoseErrors
) {
389 std::string Desc
= describeSanitizeArg(Arg
, KindsToDiagnose
);
390 D
.Diag(diag::err_drv_argument_not_allowed_with
)
391 << Desc
<< "-fsanitize-minimal-runtime";
393 DiagnosedKinds
|= KindsToDiagnose
;
395 Add
&= ~NotAllowedWithMinimalRuntime
;
398 if (llvm::opt::Arg
*A
= Args
.getLastArg(options::OPT_mcmodel_EQ
)) {
399 StringRef CM
= A
->getValue();
401 (Add
& SanitizerKind::Function
& ~DiagnosedKinds
)) {
403 D
.Diag(diag::err_drv_argument_only_allowed_with
)
404 << "-fsanitize=function"
406 Add
&= ~SanitizerKind::Function
;
407 DiagnosedKinds
|= SanitizerKind::Function
;
410 // -fsanitize=function and -fsanitize=kcfi instrument indirect function
411 // calls to load a type hash before the function label. Therefore, an
412 // execute-only target doesn't support the function and kcfi sanitizers.
413 const llvm::Triple
&Triple
= TC
.getTriple();
414 if (isExecuteOnlyTarget(Triple
, Args
)) {
415 if (SanitizerMask KindsToDiagnose
=
416 Add
& NotAllowedWithExecuteOnly
& ~DiagnosedKinds
) {
417 if (DiagnoseErrors
) {
418 std::string Desc
= describeSanitizeArg(Arg
, KindsToDiagnose
);
419 D
.Diag(diag::err_drv_argument_not_allowed_with
)
420 << Desc
<< Triple
.str();
422 DiagnosedKinds
|= KindsToDiagnose
;
424 Add
&= ~NotAllowedWithExecuteOnly
;
427 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
428 // There are currently two problems:
429 // - Virtual function call checks need to pass a pointer to the function
430 // address to llvm.type.test and a pointer to the address point to the
431 // diagnostic function. Currently we pass the same pointer to both
433 // - Non-virtual function call checks may need to check multiple type
435 // Fixing both of those may require changes to the cross-DSO CFI
437 if (CfiCrossDso
&& (Add
& SanitizerKind::CFIMFCall
& ~DiagnosedKinds
)) {
439 D
.Diag(diag::err_drv_argument_not_allowed_with
)
440 << "-fsanitize=cfi-mfcall"
441 << "-fsanitize-cfi-cross-dso";
442 Add
&= ~SanitizerKind::CFIMFCall
;
443 DiagnosedKinds
|= SanitizerKind::CFIMFCall
;
446 if (SanitizerMask KindsToDiagnose
= Add
& ~Supported
& ~DiagnosedKinds
) {
447 if (DiagnoseErrors
) {
448 std::string Desc
= describeSanitizeArg(Arg
, KindsToDiagnose
);
449 D
.Diag(diag::err_drv_unsupported_opt_for_target
)
450 << Desc
<< TC
.getTriple().str();
452 DiagnosedKinds
|= KindsToDiagnose
;
456 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
457 // so we don't error out if -fno-rtti and -fsanitize=undefined were
459 if ((Add
& SanitizerKind::Vptr
) && (RTTIMode
== ToolChain::RM_Disabled
)) {
460 if (const llvm::opt::Arg
*NoRTTIArg
= TC
.getRTTIArg()) {
461 assert(NoRTTIArg
->getOption().matches(options::OPT_fno_rtti
) &&
462 "RTTI disabled without -fno-rtti option?");
463 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
464 // the vptr sanitizer requires RTTI, so this is a user error.
466 D
.Diag(diag::err_drv_argument_not_allowed_with
)
467 << "-fsanitize=vptr" << NoRTTIArg
->getAsString(Args
);
469 // The vptr sanitizer requires RTTI, but RTTI is disabled (by
470 // default). Warn that the vptr sanitizer is being disabled.
472 D
.Diag(diag::warn_drv_disabling_vptr_no_rtti_default
);
475 // Take out the Vptr sanitizer from the enabled sanitizers
476 AllRemove
|= SanitizerKind::Vptr
;
479 Add
= expandSanitizerGroups(Add
);
480 // Group expansion may have enabled a sanitizer which is disabled later.
482 // Silently discard any unsupported sanitizers implicitly enabled through
484 Add
&= ~InvalidTrappingKinds
;
485 if (MinimalRuntime
) {
486 Add
&= ~NotAllowedWithMinimalRuntime
;
488 // NotAllowedWithExecuteOnly is silently discarded on an execute-only
489 // target if implicitly enabled through group expansion.
490 if (isExecuteOnlyTarget(Triple
, Args
))
491 Add
&= ~NotAllowedWithExecuteOnly
;
493 Add
&= ~SanitizerKind::CFIMFCall
;
496 if (Add
& SanitizerKind::Fuzzer
)
497 Add
|= SanitizerKind::FuzzerNoLink
;
499 // Enable coverage if the fuzzing flag is set.
500 if (Add
& SanitizerKind::FuzzerNoLink
) {
501 CoverageFeatures
|= CoverageInline8bitCounters
| CoverageIndirCall
|
502 CoverageTraceCmp
| CoveragePCTable
;
503 // Due to TLS differences, stack depth tracking is only enabled on Linux
504 if (TC
.getTriple().isOSLinux())
505 CoverageFeatures
|= CoverageStackDepth
;
509 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_EQ
)) {
511 SanitizerMask Remove
= parseArgValues(D
, Arg
, DiagnoseErrors
);
512 AllRemove
|= expandSanitizerGroups(Remove
);
516 std::pair
<SanitizerMask
, SanitizerMask
> IncompatibleGroups
[] = {
517 std::make_pair(SanitizerKind::Address
,
518 SanitizerKind::Thread
| SanitizerKind::Memory
),
519 std::make_pair(SanitizerKind::Thread
, SanitizerKind::Memory
),
520 std::make_pair(SanitizerKind::Leak
,
521 SanitizerKind::Thread
| SanitizerKind::Memory
),
522 std::make_pair(SanitizerKind::KernelAddress
,
523 SanitizerKind::Address
| SanitizerKind::Leak
|
524 SanitizerKind::Thread
| SanitizerKind::Memory
),
525 std::make_pair(SanitizerKind::HWAddress
,
526 SanitizerKind::Address
| SanitizerKind::Thread
|
527 SanitizerKind::Memory
| SanitizerKind::KernelAddress
),
528 std::make_pair(SanitizerKind::Scudo
,
529 SanitizerKind::Address
| SanitizerKind::HWAddress
|
530 SanitizerKind::Leak
| SanitizerKind::Thread
|
531 SanitizerKind::Memory
| SanitizerKind::KernelAddress
),
532 std::make_pair(SanitizerKind::SafeStack
,
533 (TC
.getTriple().isOSFuchsia() ? SanitizerMask()
534 : SanitizerKind::Leak
) |
535 SanitizerKind::Address
| SanitizerKind::HWAddress
|
536 SanitizerKind::Thread
| SanitizerKind::Memory
|
537 SanitizerKind::KernelAddress
),
538 std::make_pair(SanitizerKind::KernelHWAddress
,
539 SanitizerKind::Address
| SanitizerKind::HWAddress
|
540 SanitizerKind::Leak
| SanitizerKind::Thread
|
541 SanitizerKind::Memory
| SanitizerKind::KernelAddress
|
542 SanitizerKind::SafeStack
),
543 std::make_pair(SanitizerKind::KernelMemory
,
544 SanitizerKind::Address
| SanitizerKind::HWAddress
|
545 SanitizerKind::Leak
| SanitizerKind::Thread
|
546 SanitizerKind::Memory
| SanitizerKind::KernelAddress
|
547 SanitizerKind::Scudo
| SanitizerKind::SafeStack
),
548 std::make_pair(SanitizerKind::MemTag
,
549 SanitizerKind::Address
| SanitizerKind::KernelAddress
|
550 SanitizerKind::HWAddress
|
551 SanitizerKind::KernelHWAddress
),
552 std::make_pair(SanitizerKind::KCFI
, SanitizerKind::Function
)};
553 // Enable toolchain specific default sanitizers if not explicitly disabled.
554 SanitizerMask Default
= TC
.getDefaultSanitizers() & ~AllRemove
;
556 // Disable default sanitizers that are incompatible with explicitly requested
558 for (auto G
: IncompatibleGroups
) {
559 SanitizerMask Group
= G
.first
;
560 if ((Default
& Group
) && (Kinds
& G
.second
))
566 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
568 if ((Kinds
& SanitizerKind::Vptr
) && (RTTIMode
== ToolChain::RM_Disabled
)) {
569 Kinds
&= ~SanitizerKind::Vptr
;
572 // Check that LTO is enabled if we need it.
573 if ((Kinds
& NeedsLTO
) && !D
.isUsingLTO() && DiagnoseErrors
) {
574 D
.Diag(diag::err_drv_argument_only_allowed_with
)
575 << lastArgumentForMask(D
, Args
, Kinds
& NeedsLTO
) << "-flto";
578 if ((Kinds
& SanitizerKind::ShadowCallStack
) && TC
.getTriple().isAArch64() &&
579 !llvm::AArch64::isX18ReservedByDefault(TC
.getTriple()) &&
580 !Args
.hasArg(options::OPT_ffixed_x18
) && DiagnoseErrors
) {
581 D
.Diag(diag::err_drv_argument_only_allowed_with
)
582 << lastArgumentForMask(D
, Args
, Kinds
& SanitizerKind::ShadowCallStack
)
586 // Report error if there are non-trapping sanitizers that require
587 // c++abi-specific parts of UBSan runtime, and they are not provided by the
588 // toolchain. We don't have a good way to check the latter, so we just
589 // check if the toolchan supports vptr.
590 if (~Supported
& SanitizerKind::Vptr
) {
591 SanitizerMask KindsToDiagnose
= Kinds
& ~TrappingKinds
& NeedsUbsanCxxRt
;
592 // The runtime library supports the Microsoft C++ ABI, but only well enough
593 // for CFI. FIXME: Remove this once we support vptr on Windows.
594 if (TC
.getTriple().isOSWindows())
595 KindsToDiagnose
&= ~SanitizerKind::CFI
;
596 if (KindsToDiagnose
) {
598 S
.Mask
= KindsToDiagnose
;
600 D
.Diag(diag::err_drv_unsupported_opt_for_target
)
601 << ("-fno-sanitize-trap=" + toString(S
)) << TC
.getTriple().str();
602 Kinds
&= ~KindsToDiagnose
;
606 // Warn about incompatible groups of sanitizers.
607 for (auto G
: IncompatibleGroups
) {
608 SanitizerMask Group
= G
.first
;
610 if (SanitizerMask Incompatible
= Kinds
& G
.second
) {
612 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
613 << lastArgumentForMask(D
, Args
, Group
)
614 << lastArgumentForMask(D
, Args
, Incompatible
);
615 Kinds
&= ~Incompatible
;
619 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
620 // -fsanitize=address. Perhaps it should print an error, or perhaps
621 // -f(-no)sanitize=leak should change whether leak detection is enabled by
624 // Parse -f(no-)?sanitize-recover flags.
625 SanitizerMask RecoverableKinds
= RecoverableByDefault
| AlwaysRecoverable
;
626 SanitizerMask DiagnosedUnrecoverableKinds
;
627 SanitizerMask DiagnosedAlwaysRecoverableKinds
;
628 for (const auto *Arg
: Args
) {
629 if (Arg
->getOption().matches(options::OPT_fsanitize_recover_EQ
)) {
630 SanitizerMask Add
= parseArgValues(D
, Arg
, DiagnoseErrors
);
631 // Report error if user explicitly tries to recover from unrecoverable
633 if (SanitizerMask KindsToDiagnose
=
634 Add
& Unrecoverable
& ~DiagnosedUnrecoverableKinds
) {
635 SanitizerSet SetToDiagnose
;
636 SetToDiagnose
.Mask
|= KindsToDiagnose
;
638 D
.Diag(diag::err_drv_unsupported_option_argument
)
639 << Arg
->getSpelling() << toString(SetToDiagnose
);
640 DiagnosedUnrecoverableKinds
|= KindsToDiagnose
;
642 RecoverableKinds
|= expandSanitizerGroups(Add
);
644 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_recover_EQ
)) {
645 SanitizerMask Remove
= parseArgValues(D
, Arg
, DiagnoseErrors
);
646 // Report error if user explicitly tries to disable recovery from
647 // always recoverable sanitizer.
648 if (SanitizerMask KindsToDiagnose
=
649 Remove
& AlwaysRecoverable
& ~DiagnosedAlwaysRecoverableKinds
) {
650 SanitizerSet SetToDiagnose
;
651 SetToDiagnose
.Mask
|= KindsToDiagnose
;
653 D
.Diag(diag::err_drv_unsupported_option_argument
)
654 << Arg
->getSpelling() << toString(SetToDiagnose
);
655 DiagnosedAlwaysRecoverableKinds
|= KindsToDiagnose
;
657 RecoverableKinds
&= ~expandSanitizerGroups(Remove
);
661 RecoverableKinds
&= Kinds
;
662 RecoverableKinds
&= ~Unrecoverable
;
664 TrappingKinds
&= Kinds
;
665 RecoverableKinds
&= ~TrappingKinds
;
667 // Setup ignorelist files.
668 // Add default ignorelist from resource directory for activated sanitizers,
669 // and validate special case lists format.
670 if (!Args
.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist
))
671 addDefaultIgnorelists(D
, Kinds
, SystemIgnorelistFiles
, DiagnoseErrors
);
673 // Parse -f(no-)?sanitize-ignorelist options.
674 // This also validates special case lists format.
675 parseSpecialCaseListArg(
676 D
, Args
, UserIgnorelistFiles
, options::OPT_fsanitize_ignorelist_EQ
,
677 options::OPT_fno_sanitize_ignorelist
,
678 clang::diag::err_drv_malformed_sanitizer_ignorelist
, DiagnoseErrors
);
680 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
681 if (AllAddedKinds
& SanitizerKind::Memory
) {
683 Args
.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ
,
684 options::OPT_fno_sanitize_memory_track_origins
)) {
685 if (!A
->getOption().matches(
686 options::OPT_fno_sanitize_memory_track_origins
)) {
687 StringRef S
= A
->getValue();
688 if (S
.getAsInteger(0, MsanTrackOrigins
) || MsanTrackOrigins
< 0 ||
689 MsanTrackOrigins
> 2) {
691 D
.Diag(clang::diag::err_drv_invalid_value
)
692 << A
->getAsString(Args
) << S
;
696 MsanUseAfterDtor
= Args
.hasFlag(
697 options::OPT_fsanitize_memory_use_after_dtor
,
698 options::OPT_fno_sanitize_memory_use_after_dtor
, MsanUseAfterDtor
);
699 MsanParamRetval
= Args
.hasFlag(
700 options::OPT_fsanitize_memory_param_retval
,
701 options::OPT_fno_sanitize_memory_param_retval
, MsanParamRetval
);
702 NeedPIE
|= !(TC
.getTriple().isOSLinux() &&
703 TC
.getTriple().getArch() == llvm::Triple::x86_64
);
704 } else if (AllAddedKinds
& SanitizerKind::KernelMemory
) {
705 MsanUseAfterDtor
= false;
706 MsanParamRetval
= Args
.hasFlag(
707 options::OPT_fsanitize_memory_param_retval
,
708 options::OPT_fno_sanitize_memory_param_retval
, MsanParamRetval
);
710 MsanUseAfterDtor
= false;
711 MsanParamRetval
= false;
714 if (AllAddedKinds
& SanitizerKind::MemTag
) {
716 Args
.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ
, "sync");
717 if (S
== "async" || S
== "sync") {
718 MemtagMode
= S
.str();
720 D
.Diag(clang::diag::err_drv_invalid_value_with_suggestion
)
721 << "-fsanitize-memtag-mode=" << S
<< "{async, sync}";
726 if (AllAddedKinds
& SanitizerKind::Thread
) {
727 TsanMemoryAccess
= Args
.hasFlag(
728 options::OPT_fsanitize_thread_memory_access
,
729 options::OPT_fno_sanitize_thread_memory_access
, TsanMemoryAccess
);
730 TsanFuncEntryExit
= Args
.hasFlag(
731 options::OPT_fsanitize_thread_func_entry_exit
,
732 options::OPT_fno_sanitize_thread_func_entry_exit
, TsanFuncEntryExit
);
734 Args
.hasFlag(options::OPT_fsanitize_thread_atomics
,
735 options::OPT_fno_sanitize_thread_atomics
, TsanAtomics
);
738 if (AllAddedKinds
& SanitizerKind::CFI
) {
739 // Without PIE, external function address may resolve to a PLT record, which
740 // can not be verified by the target module.
741 NeedPIE
|= CfiCrossDso
;
742 CfiICallGeneralizePointers
=
743 Args
.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers
);
745 CfiICallNormalizeIntegers
=
746 Args
.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers
);
748 if (CfiCrossDso
&& CfiICallGeneralizePointers
&& DiagnoseErrors
)
749 D
.Diag(diag::err_drv_argument_not_allowed_with
)
750 << "-fsanitize-cfi-cross-dso"
751 << "-fsanitize-cfi-icall-generalize-pointers";
753 CfiCanonicalJumpTables
=
754 Args
.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables
,
755 options::OPT_fno_sanitize_cfi_canonical_jump_tables
, true);
758 if (AllAddedKinds
& SanitizerKind::KCFI
) {
759 CfiICallNormalizeIntegers
=
760 Args
.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers
);
762 if (AllAddedKinds
& SanitizerKind::CFI
&& DiagnoseErrors
)
763 D
.Diag(diag::err_drv_argument_not_allowed_with
)
765 << lastArgumentForMask(D
, Args
, SanitizerKind::CFI
);
768 Stats
= Args
.hasFlag(options::OPT_fsanitize_stats
,
769 options::OPT_fno_sanitize_stats
, false);
771 if (MinimalRuntime
) {
772 SanitizerMask IncompatibleMask
=
773 Kinds
& ~setGroupBits(CompatibleWithMinimalRuntime
);
774 if (IncompatibleMask
&& DiagnoseErrors
)
775 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
776 << "-fsanitize-minimal-runtime"
777 << lastArgumentForMask(D
, Args
, IncompatibleMask
);
779 SanitizerMask NonTrappingCfi
= Kinds
& SanitizerKind::CFI
& ~TrappingKinds
;
780 if (NonTrappingCfi
&& DiagnoseErrors
)
781 D
.Diag(clang::diag::err_drv_argument_only_allowed_with
)
782 << "fsanitize-minimal-runtime"
783 << "fsanitize-trap=cfi";
786 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
787 // enabled sanitizers.
788 for (const auto *Arg
: Args
) {
789 if (Arg
->getOption().matches(options::OPT_fsanitize_coverage
)) {
790 int LegacySanitizeCoverage
;
791 if (Arg
->getNumValues() == 1 &&
792 !StringRef(Arg
->getValue(0))
793 .getAsInteger(0, LegacySanitizeCoverage
)) {
794 CoverageFeatures
= 0;
796 if (LegacySanitizeCoverage
!= 0 && DiagnoseErrors
) {
797 D
.Diag(diag::warn_drv_deprecated_arg
)
798 << Arg
->getAsString(Args
) << "-fsanitize-coverage=trace-pc-guard";
802 CoverageFeatures
|= parseCoverageFeatures(D
, Arg
, DiagnoseErrors
);
804 // Disable coverage and not claim the flags if there is at least one
805 // non-supporting sanitizer.
806 if (!(AllAddedKinds
& ~AllRemove
& ~setGroupBits(SupportsCoverage
))) {
809 CoverageFeatures
= 0;
811 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_coverage
)) {
813 CoverageFeatures
&= ~parseCoverageFeatures(D
, Arg
, DiagnoseErrors
);
816 // Choose at most one coverage type: function, bb, or edge.
817 if (DiagnoseErrors
) {
818 if ((CoverageFeatures
& CoverageFunc
) && (CoverageFeatures
& CoverageBB
))
819 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
820 << "-fsanitize-coverage=func"
821 << "-fsanitize-coverage=bb";
822 if ((CoverageFeatures
& CoverageFunc
) && (CoverageFeatures
& CoverageEdge
))
823 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
824 << "-fsanitize-coverage=func"
825 << "-fsanitize-coverage=edge";
826 if ((CoverageFeatures
& CoverageBB
) && (CoverageFeatures
& CoverageEdge
))
827 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
828 << "-fsanitize-coverage=bb"
829 << "-fsanitize-coverage=edge";
830 // Basic block tracing and 8-bit counters require some type of coverage
832 if (CoverageFeatures
& CoverageTraceBB
)
833 D
.Diag(clang::diag::warn_drv_deprecated_arg
)
834 << "-fsanitize-coverage=trace-bb"
835 << "-fsanitize-coverage=trace-pc-guard";
836 if (CoverageFeatures
& Coverage8bitCounters
)
837 D
.Diag(clang::diag::warn_drv_deprecated_arg
)
838 << "-fsanitize-coverage=8bit-counters"
839 << "-fsanitize-coverage=trace-pc-guard";
842 int InsertionPointTypes
= CoverageFunc
| CoverageBB
| CoverageEdge
;
843 int InstrumentationTypes
= CoverageTracePC
| CoverageTracePCGuard
|
844 CoverageInline8bitCounters
| CoverageTraceLoads
|
845 CoverageTraceStores
| CoverageInlineBoolFlag
|
847 if ((CoverageFeatures
& InsertionPointTypes
) &&
848 !(CoverageFeatures
& InstrumentationTypes
) && DiagnoseErrors
) {
849 D
.Diag(clang::diag::warn_drv_deprecated_arg
)
850 << "-fsanitize-coverage=[func|bb|edge]"
851 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
855 // trace-pc w/o func/bb/edge implies edge.
856 if (!(CoverageFeatures
& InsertionPointTypes
)) {
857 if (CoverageFeatures
&
858 (CoverageTracePC
| CoverageTracePCGuard
| CoverageInline8bitCounters
|
859 CoverageInlineBoolFlag
| CoverageControlFlow
))
860 CoverageFeatures
|= CoverageEdge
;
862 if (CoverageFeatures
& CoverageStackDepth
)
863 CoverageFeatures
|= CoverageFunc
;
866 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
867 // This also validates special case lists format.
868 // Here, OptSpecifier() acts as a never-matching command-line argument.
869 // So, there is no way to clear coverage lists but you can append to them.
870 if (CoverageFeatures
) {
871 parseSpecialCaseListArg(
872 D
, Args
, CoverageAllowlistFiles
,
873 options::OPT_fsanitize_coverage_allowlist
, OptSpecifier(),
874 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist
,
876 parseSpecialCaseListArg(
877 D
, Args
, CoverageIgnorelistFiles
,
878 options::OPT_fsanitize_coverage_ignorelist
, OptSpecifier(),
879 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist
,
883 // Parse -f(no-)?sanitize-metadata.
884 for (const auto *Arg
:
885 Args
.filtered(options::OPT_fexperimental_sanitize_metadata_EQ
,
886 options::OPT_fno_experimental_sanitize_metadata_EQ
)) {
887 if (Arg
->getOption().matches(
888 options::OPT_fexperimental_sanitize_metadata_EQ
)) {
890 BinaryMetadataFeatures
|=
891 parseBinaryMetadataFeatures(D
, Arg
, DiagnoseErrors
);
894 BinaryMetadataFeatures
&=
895 ~parseBinaryMetadataFeatures(D
, Arg
, DiagnoseErrors
);
899 // Parse -fsanitize-metadata-ignorelist option if enabled.
900 if (BinaryMetadataFeatures
) {
901 parseSpecialCaseListArg(
902 D
, Args
, BinaryMetadataIgnorelistFiles
,
903 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ
,
904 OptSpecifier(), // Cannot clear ignore list, only append.
905 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist
,
910 Args
.hasFlag(options::OPT_shared_libsan
, options::OPT_static_libsan
,
911 TC
.getTriple().isAndroid() || TC
.getTriple().isOSFuchsia() ||
912 TC
.getTriple().isOSDarwin());
914 ImplicitCfiRuntime
= TC
.getTriple().isAndroid();
916 if (AllAddedKinds
& SanitizerKind::Address
) {
917 NeedPIE
|= TC
.getTriple().isOSFuchsia();
919 Args
.getLastArg(options::OPT_fsanitize_address_field_padding
)) {
920 StringRef S
= A
->getValue();
921 // Legal values are 0 and 1, 2, but in future we may add more levels.
922 if ((S
.getAsInteger(0, AsanFieldPadding
) || AsanFieldPadding
< 0 ||
923 AsanFieldPadding
> 2) &&
925 D
.Diag(clang::diag::err_drv_invalid_value
) << A
->getAsString(Args
) << S
;
929 if (Arg
*WindowsDebugRTArg
=
930 Args
.getLastArg(options::OPT__SLASH_MTd
, options::OPT__SLASH_MT
,
931 options::OPT__SLASH_MDd
, options::OPT__SLASH_MD
,
932 options::OPT__SLASH_LDd
, options::OPT__SLASH_LD
)) {
933 switch (WindowsDebugRTArg
->getOption().getID()) {
934 case options::OPT__SLASH_MTd
:
935 case options::OPT__SLASH_MDd
:
936 case options::OPT__SLASH_LDd
:
937 if (DiagnoseErrors
) {
938 D
.Diag(clang::diag::err_drv_argument_not_allowed_with
)
939 << WindowsDebugRTArg
->getAsString(Args
)
940 << lastArgumentForMask(D
, Args
, SanitizerKind::Address
);
941 D
.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime
);
946 StableABI
= Args
.hasFlag(options::OPT_fsanitize_stable_abi
,
947 options::OPT_fno_sanitize_stable_abi
, false);
949 AsanUseAfterScope
= Args
.hasFlag(
950 options::OPT_fsanitize_address_use_after_scope
,
951 options::OPT_fno_sanitize_address_use_after_scope
, AsanUseAfterScope
);
953 AsanPoisonCustomArrayCookie
= Args
.hasFlag(
954 options::OPT_fsanitize_address_poison_custom_array_cookie
,
955 options::OPT_fno_sanitize_address_poison_custom_array_cookie
,
956 AsanPoisonCustomArrayCookie
);
958 AsanOutlineInstrumentation
=
959 Args
.hasFlag(options::OPT_fsanitize_address_outline_instrumentation
,
960 options::OPT_fno_sanitize_address_outline_instrumentation
,
961 AsanOutlineInstrumentation
);
963 AsanGlobalsDeadStripping
= Args
.hasFlag(
964 options::OPT_fsanitize_address_globals_dead_stripping
,
965 options::OPT_fno_sanitize_address_globals_dead_stripping
, true);
967 // Enable ODR indicators which allow better handling of mixed instrumented
968 // and uninstrumented globals. Disable them for Windows where weak odr
969 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
970 // errors in the absence of -lldmingw.
971 AsanUseOdrIndicator
=
972 Args
.hasFlag(options::OPT_fsanitize_address_use_odr_indicator
,
973 options::OPT_fno_sanitize_address_use_odr_indicator
,
974 !TC
.getTriple().isOSWindows());
976 if (AllAddedKinds
& SanitizerKind::PointerCompare
& ~AllRemove
) {
977 AsanInvalidPointerCmp
= true;
980 if (AllAddedKinds
& SanitizerKind::PointerSubtract
& ~AllRemove
) {
981 AsanInvalidPointerSub
= true;
984 if (TC
.getTriple().isOSDarwin() &&
985 (Args
.hasArg(options::OPT_mkernel
) ||
986 Args
.hasArg(options::OPT_fapple_kext
))) {
987 AsanDtorKind
= llvm::AsanDtorKind::None
;
990 if (const auto *Arg
=
991 Args
.getLastArg(options::OPT_sanitize_address_destructor_EQ
)) {
992 auto parsedAsanDtorKind
= AsanDtorKindFromString(Arg
->getValue());
993 if (parsedAsanDtorKind
== llvm::AsanDtorKind::Invalid
&& DiagnoseErrors
) {
994 TC
.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument
)
995 << Arg
->getSpelling() << Arg
->getValue();
997 AsanDtorKind
= parsedAsanDtorKind
;
1000 if (const auto *Arg
= Args
.getLastArg(
1001 options::OPT_sanitize_address_use_after_return_EQ
)) {
1002 auto parsedAsanUseAfterReturn
=
1003 AsanDetectStackUseAfterReturnModeFromString(Arg
->getValue());
1004 if (parsedAsanUseAfterReturn
==
1005 llvm::AsanDetectStackUseAfterReturnMode::Invalid
&&
1007 TC
.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument
)
1008 << Arg
->getSpelling() << Arg
->getValue();
1010 AsanUseAfterReturn
= parsedAsanUseAfterReturn
;
1014 AsanUseAfterScope
= false;
1015 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1016 SanitizerMask DetectInvalidPointerPairs
=
1017 SanitizerKind::PointerCompare
| SanitizerKind::PointerSubtract
;
1018 if ((AllAddedKinds
& DetectInvalidPointerPairs
& ~AllRemove
) &&
1020 TC
.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with
)
1021 << lastArgumentForMask(D
, Args
,
1022 SanitizerKind::PointerCompare
|
1023 SanitizerKind::PointerSubtract
)
1024 << "-fsanitize=address";
1028 if (AllAddedKinds
& SanitizerKind::HWAddress
) {
1029 if (Arg
*HwasanAbiArg
=
1030 Args
.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ
)) {
1031 HwasanAbi
= HwasanAbiArg
->getValue();
1032 if (HwasanAbi
!= "platform" && HwasanAbi
!= "interceptor" &&
1034 D
.Diag(clang::diag::err_drv_invalid_value
)
1035 << HwasanAbiArg
->getAsString(Args
) << HwasanAbi
;
1037 HwasanAbi
= "interceptor";
1039 if (TC
.getTriple().getArch() == llvm::Triple::x86_64
)
1040 HwasanUseAliases
= Args
.hasFlag(
1041 options::OPT_fsanitize_hwaddress_experimental_aliasing
,
1042 options::OPT_fno_sanitize_hwaddress_experimental_aliasing
,
1046 if (AllAddedKinds
& SanitizerKind::SafeStack
) {
1047 // SafeStack runtime is built into the system on Android and Fuchsia.
1049 !TC
.getTriple().isAndroid() && !TC
.getTriple().isOSFuchsia();
1053 Args
.hasFlag(options::OPT_fsanitize_link_runtime
,
1054 options::OPT_fno_sanitize_link_runtime
, LinkRuntimes
);
1056 // Parse -link-cxx-sanitizer flag.
1057 LinkCXXRuntimes
= Args
.hasArg(options::OPT_fsanitize_link_cxx_runtime
,
1058 options::OPT_fno_sanitize_link_cxx_runtime
,
1062 NeedsMemProfRt
= Args
.hasFlag(options::OPT_fmemory_profile
,
1063 options::OPT_fmemory_profile_EQ
,
1064 options::OPT_fno_memory_profile
, false);
1066 // Finally, initialize the set of available and recoverable sanitizers.
1067 Sanitizers
.Mask
|= Kinds
;
1068 RecoverableSanitizers
.Mask
|= RecoverableKinds
;
1069 TrapSanitizers
.Mask
|= TrappingKinds
;
1070 assert(!(RecoverableKinds
& TrappingKinds
) &&
1071 "Overlap between recoverable and trapping sanitizers");
1074 static std::string
toString(const clang::SanitizerSet
&Sanitizers
) {
1076 #define SANITIZER(NAME, ID) \
1077 if (Sanitizers.has(SanitizerKind::ID)) { \
1082 #include "clang/Basic/Sanitizers.def"
1086 static void addSpecialCaseListOpt(const llvm::opt::ArgList
&Args
,
1087 llvm::opt::ArgStringList
&CmdArgs
,
1088 const char *SCLOptFlag
,
1089 const std::vector
<std::string
> &SCLFiles
) {
1090 for (const auto &SCLPath
: SCLFiles
) {
1091 SmallString
<64> SCLOpt(SCLOptFlag
);
1093 CmdArgs
.push_back(Args
.MakeArgString(SCLOpt
));
1097 static void addIncludeLinkerOption(const ToolChain
&TC
,
1098 const llvm::opt::ArgList
&Args
,
1099 llvm::opt::ArgStringList
&CmdArgs
,
1100 StringRef SymbolName
) {
1101 SmallString
<64> LinkerOptionFlag
;
1102 LinkerOptionFlag
= "--linker-option=/include:";
1103 if (TC
.getTriple().getArch() == llvm::Triple::x86
) {
1104 // Win32 mangles C function names with a '_' prefix.
1105 LinkerOptionFlag
+= '_';
1107 LinkerOptionFlag
+= SymbolName
;
1108 CmdArgs
.push_back(Args
.MakeArgString(LinkerOptionFlag
));
1111 static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList
&CmdArgs
) {
1112 for (auto Start
= CmdArgs
.begin(), End
= CmdArgs
.end(); Start
!= End
;
1114 auto It
= std::find(Start
, End
, StringRef("+mte"));
1117 if (It
> Start
&& *std::prev(It
) == StringRef("-target-feature"))
1124 void SanitizerArgs::addArgs(const ToolChain
&TC
, const llvm::opt::ArgList
&Args
,
1125 llvm::opt::ArgStringList
&CmdArgs
,
1126 types::ID InputType
) const {
1127 // NVPTX doesn't currently support sanitizers. Bailing out here means
1128 // that e.g. -fsanitize=address applies only to host code, which is what we
1130 if (TC
.getTriple().isNVPTX())
1132 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1133 bool GPUSanitize
= false;
1134 if (TC
.getTriple().isAMDGPU()) {
1135 if (!Args
.hasFlag(options::OPT_fgpu_sanitize
, options::OPT_fno_gpu_sanitize
,
1141 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1142 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1144 std::pair
<int, const char *> CoverageFlags
[] = {
1145 std::make_pair(CoverageFunc
, "-fsanitize-coverage-type=1"),
1146 std::make_pair(CoverageBB
, "-fsanitize-coverage-type=2"),
1147 std::make_pair(CoverageEdge
, "-fsanitize-coverage-type=3"),
1148 std::make_pair(CoverageIndirCall
, "-fsanitize-coverage-indirect-calls"),
1149 std::make_pair(CoverageTraceBB
, "-fsanitize-coverage-trace-bb"),
1150 std::make_pair(CoverageTraceCmp
, "-fsanitize-coverage-trace-cmp"),
1151 std::make_pair(CoverageTraceDiv
, "-fsanitize-coverage-trace-div"),
1152 std::make_pair(CoverageTraceGep
, "-fsanitize-coverage-trace-gep"),
1153 std::make_pair(Coverage8bitCounters
, "-fsanitize-coverage-8bit-counters"),
1154 std::make_pair(CoverageTracePC
, "-fsanitize-coverage-trace-pc"),
1155 std::make_pair(CoverageTracePCGuard
,
1156 "-fsanitize-coverage-trace-pc-guard"),
1157 std::make_pair(CoverageInline8bitCounters
,
1158 "-fsanitize-coverage-inline-8bit-counters"),
1159 std::make_pair(CoverageInlineBoolFlag
,
1160 "-fsanitize-coverage-inline-bool-flag"),
1161 std::make_pair(CoveragePCTable
, "-fsanitize-coverage-pc-table"),
1162 std::make_pair(CoverageNoPrune
, "-fsanitize-coverage-no-prune"),
1163 std::make_pair(CoverageStackDepth
, "-fsanitize-coverage-stack-depth"),
1164 std::make_pair(CoverageTraceLoads
, "-fsanitize-coverage-trace-loads"),
1165 std::make_pair(CoverageTraceStores
, "-fsanitize-coverage-trace-stores"),
1166 std::make_pair(CoverageControlFlow
, "-fsanitize-coverage-control-flow")};
1167 for (auto F
: CoverageFlags
) {
1168 if (CoverageFeatures
& F
.first
)
1169 CmdArgs
.push_back(F
.second
);
1171 addSpecialCaseListOpt(
1172 Args
, CmdArgs
, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles
);
1173 addSpecialCaseListOpt(Args
, CmdArgs
, "-fsanitize-coverage-ignorelist=",
1174 CoverageIgnorelistFiles
);
1177 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1178 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1179 const std::pair
<int, std::string
> BinaryMetadataFlags
[] = {
1180 std::make_pair(BinaryMetadataCovered
, "covered"),
1181 std::make_pair(BinaryMetadataAtomics
, "atomics"),
1182 std::make_pair(BinaryMetadataUAR
, "uar")};
1183 for (const auto &F
: BinaryMetadataFlags
) {
1184 if (BinaryMetadataFeatures
& F
.first
)
1186 Args
.MakeArgString("-fexperimental-sanitize-metadata=" + F
.second
));
1188 addSpecialCaseListOpt(Args
, CmdArgs
,
1189 "-fexperimental-sanitize-metadata-ignorelist=",
1190 BinaryMetadataIgnorelistFiles
);
1193 if (TC
.getTriple().isOSWindows() && needsUbsanRt()) {
1194 // Instruct the code generator to embed linker directives in the object file
1195 // that cause the required runtime libraries to be linked.
1197 Args
.MakeArgString("--dependent-lib=" +
1198 TC
.getCompilerRTBasename(Args
, "ubsan_standalone")));
1199 if (types::isCXX(InputType
))
1200 CmdArgs
.push_back(Args
.MakeArgString(
1201 "--dependent-lib=" +
1202 TC
.getCompilerRTBasename(Args
, "ubsan_standalone_cxx")));
1204 if (TC
.getTriple().isOSWindows() && needsStatsRt()) {
1205 CmdArgs
.push_back(Args
.MakeArgString(
1206 "--dependent-lib=" + TC
.getCompilerRTBasename(Args
, "stats_client")));
1208 // The main executable must export the stats runtime.
1209 // FIXME: Only exporting from the main executable (e.g. based on whether the
1210 // translation unit defines main()) would save a little space, but having
1211 // multiple copies of the runtime shouldn't hurt.
1212 CmdArgs
.push_back(Args
.MakeArgString(
1213 "--dependent-lib=" + TC
.getCompilerRTBasename(Args
, "stats")));
1214 addIncludeLinkerOption(TC
, Args
, CmdArgs
, "__sanitizer_stats_register");
1217 if (Sanitizers
.empty())
1219 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize=" + toString(Sanitizers
)));
1221 if (!RecoverableSanitizers
.empty())
1222 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize-recover=" +
1223 toString(RecoverableSanitizers
)));
1225 if (!TrapSanitizers
.empty())
1227 Args
.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers
)));
1229 addSpecialCaseListOpt(Args
, CmdArgs
,
1230 "-fsanitize-ignorelist=", UserIgnorelistFiles
);
1231 addSpecialCaseListOpt(Args
, CmdArgs
,
1232 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles
);
1234 if (MsanTrackOrigins
)
1235 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize-memory-track-origins=" +
1236 Twine(MsanTrackOrigins
)));
1238 if (MsanUseAfterDtor
)
1239 CmdArgs
.push_back("-fsanitize-memory-use-after-dtor");
1241 if (!MsanParamRetval
)
1242 CmdArgs
.push_back("-fno-sanitize-memory-param-retval");
1244 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1245 if (!TsanMemoryAccess
) {
1246 CmdArgs
.push_back("-mllvm");
1247 CmdArgs
.push_back("-tsan-instrument-memory-accesses=0");
1248 CmdArgs
.push_back("-mllvm");
1249 CmdArgs
.push_back("-tsan-instrument-memintrinsics=0");
1251 if (!TsanFuncEntryExit
) {
1252 CmdArgs
.push_back("-mllvm");
1253 CmdArgs
.push_back("-tsan-instrument-func-entry-exit=0");
1256 CmdArgs
.push_back("-mllvm");
1257 CmdArgs
.push_back("-tsan-instrument-atomics=0");
1260 if (HwasanUseAliases
) {
1261 CmdArgs
.push_back("-mllvm");
1262 CmdArgs
.push_back("-hwasan-experimental-use-page-aliases=1");
1266 CmdArgs
.push_back("-fsanitize-cfi-cross-dso");
1268 if (CfiICallGeneralizePointers
)
1269 CmdArgs
.push_back("-fsanitize-cfi-icall-generalize-pointers");
1271 if (CfiICallNormalizeIntegers
)
1272 CmdArgs
.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1274 if (CfiCanonicalJumpTables
)
1275 CmdArgs
.push_back("-fsanitize-cfi-canonical-jump-tables");
1278 CmdArgs
.push_back("-fsanitize-stats");
1281 CmdArgs
.push_back("-fsanitize-minimal-runtime");
1283 if (AsanFieldPadding
)
1284 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize-address-field-padding=" +
1285 Twine(AsanFieldPadding
)));
1287 if (AsanUseAfterScope
)
1288 CmdArgs
.push_back("-fsanitize-address-use-after-scope");
1290 if (AsanPoisonCustomArrayCookie
)
1291 CmdArgs
.push_back("-fsanitize-address-poison-custom-array-cookie");
1293 if (AsanGlobalsDeadStripping
)
1294 CmdArgs
.push_back("-fsanitize-address-globals-dead-stripping");
1296 if (!AsanUseOdrIndicator
)
1297 CmdArgs
.push_back("-fno-sanitize-address-use-odr-indicator");
1299 if (AsanInvalidPointerCmp
) {
1300 CmdArgs
.push_back("-mllvm");
1301 CmdArgs
.push_back("-asan-detect-invalid-pointer-cmp");
1304 if (AsanInvalidPointerSub
) {
1305 CmdArgs
.push_back("-mllvm");
1306 CmdArgs
.push_back("-asan-detect-invalid-pointer-sub");
1309 if (AsanOutlineInstrumentation
) {
1310 CmdArgs
.push_back("-mllvm");
1311 CmdArgs
.push_back("-asan-instrumentation-with-call-threshold=0");
1314 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1315 // inlining shadow memory poisoning. While this is a big performance burden
1316 // for now it allows full abstraction from implementation details.
1318 CmdArgs
.push_back("-mllvm");
1319 CmdArgs
.push_back("-asan-instrumentation-with-call-threshold=0");
1320 CmdArgs
.push_back("-mllvm");
1321 CmdArgs
.push_back("-asan-max-inline-poisoning-size=0");
1322 CmdArgs
.push_back("-mllvm");
1323 CmdArgs
.push_back("-asan-guard-against-version-mismatch=0");
1326 // Only pass the option to the frontend if the user requested,
1327 // otherwise the frontend will just use the codegen default.
1328 if (AsanDtorKind
!= llvm::AsanDtorKind::Invalid
) {
1329 CmdArgs
.push_back(Args
.MakeArgString("-fsanitize-address-destructor=" +
1330 AsanDtorKindToString(AsanDtorKind
)));
1333 if (AsanUseAfterReturn
!= llvm::AsanDetectStackUseAfterReturnMode::Invalid
) {
1334 CmdArgs
.push_back(Args
.MakeArgString(
1335 "-fsanitize-address-use-after-return=" +
1336 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn
)));
1339 if (!HwasanAbi
.empty()) {
1340 CmdArgs
.push_back("-default-function-attr");
1341 CmdArgs
.push_back(Args
.MakeArgString("hwasan-abi=" + HwasanAbi
));
1344 if (Sanitizers
.has(SanitizerKind::HWAddress
) && !HwasanUseAliases
) {
1345 CmdArgs
.push_back("-target-feature");
1346 CmdArgs
.push_back("+tagged-globals");
1349 // MSan: Workaround for PR16386.
1350 // ASan: This is mainly to help LSan with cases such as
1351 // https://github.com/google/sanitizers/issues/373
1352 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1353 // affect compilation.
1354 if (Sanitizers
.has(SanitizerKind::Memory
) ||
1355 Sanitizers
.has(SanitizerKind::Address
))
1356 CmdArgs
.push_back("-fno-assume-sane-operator-new");
1358 // libFuzzer wants to intercept calls to certain library functions, so the
1359 // following -fno-builtin-* flags force the compiler to emit interposable
1360 // libcalls to these functions. Other sanitizers effectively do the same thing
1361 // by marking all library call sites with NoBuiltin attribute in their LLVM
1362 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1363 if (Sanitizers
.has(SanitizerKind::FuzzerNoLink
)) {
1364 CmdArgs
.push_back("-fno-builtin-bcmp");
1365 CmdArgs
.push_back("-fno-builtin-memcmp");
1366 CmdArgs
.push_back("-fno-builtin-strncmp");
1367 CmdArgs
.push_back("-fno-builtin-strcmp");
1368 CmdArgs
.push_back("-fno-builtin-strncasecmp");
1369 CmdArgs
.push_back("-fno-builtin-strcasecmp");
1370 CmdArgs
.push_back("-fno-builtin-strstr");
1371 CmdArgs
.push_back("-fno-builtin-strcasestr");
1372 CmdArgs
.push_back("-fno-builtin-memmem");
1375 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1377 if (Sanitizers
.hasOneOf(CFIClasses
) && !TC
.getTriple().isOSWindows() &&
1378 !Args
.hasArg(options::OPT_fvisibility_EQ
)) {
1379 TC
.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with
)
1380 << lastArgumentForMask(TC
.getDriver(), Args
,
1381 Sanitizers
.Mask
& CFIClasses
)
1385 if (Sanitizers
.has(SanitizerKind::MemtagStack
) &&
1386 !hasTargetFeatureMTE(CmdArgs
))
1387 TC
.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature
);
1390 SanitizerMask
parseArgValues(const Driver
&D
, const llvm::opt::Arg
*A
,
1391 bool DiagnoseErrors
) {
1392 assert((A
->getOption().matches(options::OPT_fsanitize_EQ
) ||
1393 A
->getOption().matches(options::OPT_fno_sanitize_EQ
) ||
1394 A
->getOption().matches(options::OPT_fsanitize_recover_EQ
) ||
1395 A
->getOption().matches(options::OPT_fno_sanitize_recover_EQ
) ||
1396 A
->getOption().matches(options::OPT_fsanitize_trap_EQ
) ||
1397 A
->getOption().matches(options::OPT_fno_sanitize_trap_EQ
)) &&
1398 "Invalid argument in parseArgValues!");
1399 SanitizerMask Kinds
;
1400 for (int i
= 0, n
= A
->getNumValues(); i
!= n
; ++i
) {
1401 const char *Value
= A
->getValue(i
);
1403 // Special case: don't accept -fsanitize=all.
1404 if (A
->getOption().matches(options::OPT_fsanitize_EQ
) &&
1405 0 == strcmp("all", Value
))
1406 Kind
= SanitizerMask();
1408 Kind
= parseSanitizerValue(Value
, /*AllowGroups=*/true);
1412 else if (DiagnoseErrors
)
1413 D
.Diag(clang::diag::err_drv_unsupported_option_argument
)
1414 << A
->getSpelling() << Value
;
1419 int parseCoverageFeatures(const Driver
&D
, const llvm::opt::Arg
*A
,
1420 bool DiagnoseErrors
) {
1421 assert(A
->getOption().matches(options::OPT_fsanitize_coverage
) ||
1422 A
->getOption().matches(options::OPT_fno_sanitize_coverage
));
1424 for (int i
= 0, n
= A
->getNumValues(); i
!= n
; ++i
) {
1425 const char *Value
= A
->getValue(i
);
1426 int F
= llvm::StringSwitch
<int>(Value
)
1427 .Case("func", CoverageFunc
)
1428 .Case("bb", CoverageBB
)
1429 .Case("edge", CoverageEdge
)
1430 .Case("indirect-calls", CoverageIndirCall
)
1431 .Case("trace-bb", CoverageTraceBB
)
1432 .Case("trace-cmp", CoverageTraceCmp
)
1433 .Case("trace-div", CoverageTraceDiv
)
1434 .Case("trace-gep", CoverageTraceGep
)
1435 .Case("8bit-counters", Coverage8bitCounters
)
1436 .Case("trace-pc", CoverageTracePC
)
1437 .Case("trace-pc-guard", CoverageTracePCGuard
)
1438 .Case("no-prune", CoverageNoPrune
)
1439 .Case("inline-8bit-counters", CoverageInline8bitCounters
)
1440 .Case("inline-bool-flag", CoverageInlineBoolFlag
)
1441 .Case("pc-table", CoveragePCTable
)
1442 .Case("stack-depth", CoverageStackDepth
)
1443 .Case("trace-loads", CoverageTraceLoads
)
1444 .Case("trace-stores", CoverageTraceStores
)
1445 .Case("control-flow", CoverageControlFlow
)
1447 if (F
== 0 && DiagnoseErrors
)
1448 D
.Diag(clang::diag::err_drv_unsupported_option_argument
)
1449 << A
->getSpelling() << Value
;
1455 int parseBinaryMetadataFeatures(const Driver
&D
, const llvm::opt::Arg
*A
,
1456 bool DiagnoseErrors
) {
1458 A
->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ
) ||
1459 A
->getOption().matches(
1460 options::OPT_fno_experimental_sanitize_metadata_EQ
));
1462 for (int i
= 0, n
= A
->getNumValues(); i
!= n
; ++i
) {
1463 const char *Value
= A
->getValue(i
);
1464 int F
= llvm::StringSwitch
<int>(Value
)
1465 .Case("covered", BinaryMetadataCovered
)
1466 .Case("atomics", BinaryMetadataAtomics
)
1467 .Case("uar", BinaryMetadataUAR
)
1470 if (F
== 0 && DiagnoseErrors
)
1471 D
.Diag(clang::diag::err_drv_unsupported_option_argument
)
1472 << A
->getSpelling() << Value
;
1478 std::string
lastArgumentForMask(const Driver
&D
, const llvm::opt::ArgList
&Args
,
1479 SanitizerMask Mask
) {
1480 for (llvm::opt::ArgList::const_reverse_iterator I
= Args
.rbegin(),
1483 const auto *Arg
= *I
;
1484 if (Arg
->getOption().matches(options::OPT_fsanitize_EQ
)) {
1485 SanitizerMask AddKinds
=
1486 expandSanitizerGroups(parseArgValues(D
, Arg
, false));
1487 if (AddKinds
& Mask
)
1488 return describeSanitizeArg(Arg
, Mask
);
1489 } else if (Arg
->getOption().matches(options::OPT_fno_sanitize_EQ
)) {
1490 SanitizerMask RemoveKinds
=
1491 expandSanitizerGroups(parseArgValues(D
, Arg
, false));
1492 Mask
&= ~RemoveKinds
;
1495 llvm_unreachable("arg list didn't provide expected value");
1498 std::string
describeSanitizeArg(const llvm::opt::Arg
*A
, SanitizerMask Mask
) {
1499 assert(A
->getOption().matches(options::OPT_fsanitize_EQ
) &&
1500 "Invalid argument in describeSanitizerArg!");
1502 std::string Sanitizers
;
1503 for (int i
= 0, n
= A
->getNumValues(); i
!= n
; ++i
) {
1504 if (expandSanitizerGroups(
1505 parseSanitizerValue(A
->getValue(i
), /*AllowGroups=*/true)) &
1507 if (!Sanitizers
.empty())
1509 Sanitizers
+= A
->getValue(i
);
1513 assert(!Sanitizers
.empty() && "arg didn't provide expected value");
1514 return "-fsanitize=" + Sanitizers
;