Skip to content

Commit 7350a20

Browse files
committed
[clang] Add flag to disable container overflow checks at compile time.
Add a compiler flag to allow library developers to support disabling AddressSanitizer's container overflow detection in template code at compile time. The primary motivation is to reduce false positives in environments where libraries and frameworks that cannot be recompiled with sanitizers enabled are called from application code. This supports disabling checks when the runtime environment cannot be reliably controlled to use ASAN_OPTIONS. Key changes: - Add -fsanitize-address-disable-container-overflow driver flag - Add __has_feature(sanitize_address_disable_container_overflow) feature test - Connect flag through LangOptions and CodeGenOptions - Update compiler-rt test to conditionally use container annotations - Add comprehensive test coverage for driver flag and feature macro - Update documentation in AddressSanitizer.rst and UsersManual.rst The recommended usage pattern is: This provides backward compatibility with compilers that don't support the new feature test macro. The flag is marked experimental.
1 parent b241cc9 commit 7350a20

File tree

12 files changed

+150
-0
lines changed

12 files changed

+150
-0
lines changed

clang/docs/AddressSanitizer.rst

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ following types of bugs:
1818
* Enable with: ``ASAN_OPTIONS=detect_stack_use_after_return=1`` (already enabled on Linux).
1919
* Disable with: ``ASAN_OPTIONS=detect_stack_use_after_return=0``.
2020
* Use-after-scope (clang flag ``-fsanitize-address-use-after-scope``)
21+
* Container overflow detection (clang flag ``-fsanitize-address-disable-container-overflow`` to disable (experimental))
2122
* Double-free, invalid free
2223
* Memory leaks (experimental)
2324

@@ -164,6 +165,23 @@ To summarize: ``-fsanitize-address-use-after-return=<mode>``
164165
* ``always``: Enables detection of UAR errors in all cases. (reduces code
165166
size, but not as much as ``never``).
166167

168+
Container Overflow Detection
169+
----------------------------
170+
171+
AddressSanitizer can detect overflows in containers with custom allocators
172+
(such as std::vector) where the Library developers have added calls into the
173+
AddressSanitizer runtime to indicate which memory is poisoned etc.
174+
175+
In environments where not all the process binaries can be recompiled with
176+
AddressSanitizer enabled, these checks can cause false positives.
177+
178+
These checks can be disabled at runtime using
179+
``ASAN_OPTIONS=detect_container_overflow=0``
180+
181+
``-fsanitize-address-disable-container-overflow`` can be used at compile time
182+
to disable container overflow checks if both the container and compiler support
183+
the flag (experimental).
184+
167185
Memory leak detection
168186
---------------------
169187

@@ -242,6 +260,32 @@ AddressSanitizer also supports
242260
works similar to ``__attribute__((no_sanitize("address")))``, but it also
243261
prevents instrumentation performed by other sanitizers.
244262

263+
Disabling container overflow checks with ``__has_feature(sanitize_address_disable_container_overflow)``
264+
-------------------------------------------------------------------------------------------------------
265+
266+
Library developers may use this feature test in conjunction with the
267+
AddressSanitizer feature test to conditionally include container overflow
268+
related code compiled into user code:
269+
270+
The recommended form is
271+
272+
.. code-block:: c
273+
274+
#if __has_feature(address_sanitizer) && !__has_feature(sanitize_address_disable_container_overflow)
275+
// Container overflow detection enabled - include annotations
276+
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid);
277+
#endif
278+
279+
This pattern ensures that:
280+
281+
* Container overflow annotations are only included when AddressSanitizer is
282+
enabled
283+
* Container overflow detection can be disabled by
284+
``-fsanitize-address-disable-container-overflow``
285+
* Code compiles correctly with older compilers that don't support the
286+
``sanitize_address_disable_container_overflow`` feature test (defaulting to
287+
enabled container overflow checks)
288+
245289
Suppressing Errors in Recompiled Code (Ignorelist)
246290
--------------------------------------------------
247291

clang/docs/UsersManual.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5125,6 +5125,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
51255125
Select the mode of detecting stack use-after-return in AddressSanitizer: never | runtime (default) | always
51265126
-fsanitize-address-use-after-scope
51275127
Enable use-after-scope detection in AddressSanitizer
5128+
-fsanitize-address-disable-container-overflow
5129+
Disable container overflow detection at compile time in AddressSanitizer (experimental)
51285130
-fsanitize-address-use-odr-indicator
51295131
Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size
51305132
-fsanitize-ignorelist=<value>

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ CODEGENOPT(NewStructPathTBAA , 1, 0, Benign) ///< Whether or not to use enhanced
245245
CODEGENOPT(SaveTempLabels , 1, 0, Benign) ///< Save temporary labels.
246246
CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0, Benign) ///< Enable use-after-scope detection
247247
///< in AddressSanitizer
248+
CODEGENOPT(SanitizeAddressDisableContainerOverflow, 1, 0, Benign) ///< Disable container overflow checks
249+
///< in AddressSanitizer
248250
ENUM_CODEGENOPT(SanitizeAddressUseAfterReturn,
249251
AsanDetectStackUseAfterReturnMode, 2,
250252
AsanDetectStackUseAfterReturnMode::Runtime,

clang/include/clang/Basic/Features.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ FEATURE(speculative_load_hardening, LangOpts.SpeculativeLoadHardening)
4040
FEATURE(address_sanitizer,
4141
LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
4242
SanitizerKind::KernelAddress))
43+
FEATURE(sanitize_address_disable_container_overflow,
44+
LangOpts.SanitizeAddressDisableContainerOverflow)
4345
FEATURE(leak_sanitizer,
4446
LangOpts.Sanitize.has(SanitizerKind::Leak))
4547
FEATURE(hwaddress_sanitizer,

clang/include/clang/Basic/LangOptions.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,9 @@ LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety
499499

500500
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
501501

502+
LANGOPT(SanitizeAddressDisableContainerOverflow, 1, 0, NotCompatible,
503+
"Disable container overflow checks in AddressSanitizer (experimental)")
504+
502505
#undef LANGOPT
503506
#undef ENUM_LANGOPT
504507
#undef VALUE_LANGOPT

clang/include/clang/Driver/Options.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,6 +2512,12 @@ An operator new\[\] is "custom" if it is not one of the allocation functions
25122512
provided by the C++ standard library. Array cookies from non-custom allocation
25132513
functions are always poisoned.}]>,
25142514
Group<f_clang_Group>;
2515+
defm sanitize_address_disable_container_overflow : BoolOption<"f", "sanitize-address-disable-container-overflow",
2516+
CodeGenOpts<"SanitizeAddressDisableContainerOverflow">, DefaultFalse,
2517+
PosFlag<SetTrue, [], [ClangOption], "Disable">,
2518+
NegFlag<SetFalse, [], [ClangOption], "Enable">,
2519+
BothFlags<[], [ClangOption], " container overflow checks in AddressSanitizer (experimental)">>,
2520+
Group<f_clang_Group>;
25152521
defm sanitize_address_globals_dead_stripping : BoolOption<"f", "sanitize-address-globals-dead-stripping",
25162522
CodeGenOpts<"SanitizeAddressGlobalsDeadStripping">, DefaultFalse,
25172523
PosFlag<SetTrue, [], [ClangOption], "Enable linker dead stripping of globals in AddressSanitizer">,

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class SanitizerArgs {
5050
bool SharedRuntime = false;
5151
bool StableABI = false;
5252
bool AsanUseAfterScope = true;
53+
bool AsanDisableContainerOverflow = false;
5354
bool AsanPoisonCustomArrayCookie = false;
5455
bool AsanGlobalsDeadStripping = false;
5556
bool AsanUseOdrIndicator = false;

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,8 +1131,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
11311131
AsanUseAfterScope = Args.hasFlag(
11321132
options::OPT_fsanitize_address_use_after_scope,
11331133
options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
1134+
AsanDisableContainerOverflow = Args.hasFlag(
1135+
options::OPT_fsanitize_address_disable_container_overflow,
1136+
options::OPT_fno_sanitize_address_disable_container_overflow,
1137+
AsanDisableContainerOverflow);
11341138
} else {
11351139
AsanUseAfterScope = false;
1140+
AsanDisableContainerOverflow = false;
11361141
}
11371142

11381143
if (AllAddedKinds & SanitizerKind::HWAddress) {
@@ -1459,6 +1464,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
14591464
if (AsanUseAfterScope)
14601465
CmdArgs.push_back("-fsanitize-address-use-after-scope");
14611466

1467+
if (AsanDisableContainerOverflow)
1468+
CmdArgs.push_back("-fsanitize-address-disable-container-overflow");
1469+
14621470
if (AsanPoisonCustomArrayCookie)
14631471
CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
14641472

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,8 @@ static bool FixupInvocation(CompilerInvocation &Invocation,
586586
LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;
587587
LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;
588588
LangOpts.CurrentModule = LangOpts.ModuleName;
589+
LangOpts.SanitizeAddressDisableContainerOverflow =
590+
CodeGenOpts.SanitizeAddressDisableContainerOverflow;
589591

590592
llvm::Triple T(TargetOpts.Triple);
591593
llvm::Triple::ArchType Arch = T.getArch();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Test the -fsanitize-address-disable-container-overflow option
2+
3+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s \
4+
// RUN: -### 2>&1 | \
5+
// RUN: FileCheck %s --check-prefix=CHECK-DEFAULT
6+
// CHECK-DEFAULT-NOT: -fsanitize-address-disable-container-overflow
7+
8+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address \
9+
// RUN: -fsanitize-address-disable-container-overflow %s -### 2>&1 | \
10+
// RUN: FileCheck -check-prefix=CHECK-ENABLE %s
11+
// CHECK-ENABLE: "-fsanitize-address-disable-container-overflow"
12+
13+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address \
14+
// RUN: -fno-sanitize-address-disable-container-overflow %s -### 2>&1 | \
15+
// RUN: FileCheck -check-prefix=CHECK-DISABLE %s
16+
// CHECK-DISABLE-NOT: -fsanitize-address-disable-container-overflow
17+
18+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address \
19+
// RUN: -fsanitize-address-disable-container-overflow \
20+
// RUN: -fno-sanitize-address-disable-container-overflow %s -### 2>&1 | \
21+
// RUN: FileCheck -check-prefix=CHECK-OVERRIDE %s
22+
// CHECK-OVERRIDE-NOT: -fsanitize-address-disable-container-overflow
23+
24+
// Test that the flag generates unused warning without address sanitizer
25+
// RUN: %clang -target x86_64-linux-gnu -fsanitize-address-disable-container-overflow %s \
26+
// RUN: -### 2>&1 | \
27+
// RUN: FileCheck -check-prefix=CHECK-NO-ASAN %s
28+
// CHECK-NO-ASAN: warning: argument unused during compilation: '-fsanitize-address-disable-container-overflow'
29+
30+
// Test with kernel address sanitizer
31+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address \
32+
// RUN: -fsanitize-address-disable-container-overflow %s -### 2>&1 | \
33+
// RUN: FileCheck -check-prefix=CHECK-KERNEL-ASAN %s
34+
// CHECK-KERNEL-ASAN: "-fsanitize-address-disable-container-overflow"

0 commit comments

Comments
 (0)