Skip to content

Commit ccc6f58

Browse files
committed
Document a define 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: - Update documentation in AddressSanitizer.rst to suggest and illustrate use of the define - Add details of the define in PrintContainerOverflowHint() - Add test disable_container_overflow_checks to verify new hints on the error and fill the testing gap that ASAN_OPTIONS=detect_container_overflow=0 works This requires no compiler changes and should be supportable cross compiler toolchains. An RFC has been opened to discuss: https://discourse.llvm.org/t/rfc-add-fsanitize-address-disable-container-overflow-flag-to-addresssanitizer/88349
1 parent a909ec6 commit ccc6f58

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

clang/docs/AddressSanitizer.rst

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,18 @@ To summarize: ``-fsanitize-address-use-after-return=<mode>``
164164
* ``always``: Enables detection of UAR errors in all cases. (reduces code
165165
size, but not as much as ``never``).
166166

167+
Container Overflow Detection
168+
----------------------------
169+
170+
AddressSanitizer can detect overflows in containers with custom allocators
171+
(such as std::vector) where the library developers have added calls into the
172+
AddressSanitizer runtime to indicate which memory is poisoned etc.
173+
174+
In environments where not all the process binaries can be recompiled with
175+
AddressSanitizer enabled, these checks can cause false positives.
176+
177+
See `Disabling container overflow checks`_ for details on suppressing checks.
178+
167179
Memory leak detection
168180
---------------------
169181

@@ -242,6 +254,43 @@ AddressSanitizer also supports
242254
works similar to ``__attribute__((no_sanitize("address")))``, but it also
243255
prevents instrumentation performed by other sanitizers.
244256

257+
Disabling container overflow checks
258+
-----------------------------------
259+
260+
Runtime suppression
261+
^^^^^^^^^^^^^^^^^^^
262+
263+
Container overflow checks can be disabled at runtime using the
264+
``ASAN_OPTIONS=detect_container_overflow=0`` environment variable.
265+
266+
Compile time suppression
267+
^^^^^^^^^^^^^^^^^^^^^^^^
268+
269+
``-D__ASAN_DISABLE_CONTAINER_OVERFLOW__`` can be used at compile time to
270+
disable container overflow checks if the container library has added support
271+
for this define.
272+
273+
To support a standard way to disable container overflow checks at compile time,
274+
library developers should use this definition in conjunction with the
275+
AddressSanitizer feature test to conditionally include container overflow
276+
related code compiled into user code:
277+
278+
The recommended form is
279+
280+
.. code-block:: c
281+
282+
#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__
283+
// Container overflow detection enabled - include annotations
284+
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid);
285+
#endif
286+
287+
This pattern ensures that:
288+
289+
* Container overflow annotations are only included when AddressSanitizer is
290+
enabled
291+
* Container overflow detection can be disabled by passing
292+
``-D__ASAN_DISABLE_CONTAINER_OVERFLOW__`` to the compiler
293+
245294
Suppressing Errors in Recompiled Code (Ignorelist)
246295
--------------------------------------------------
247296

compiler-rt/lib/asan/asan_errors.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -514,11 +514,15 @@ ErrorGeneric::ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr,
514514
}
515515

516516
static void PrintContainerOverflowHint() {
517-
Printf("HINT: if you don't care about these errors you may set "
518-
"ASAN_OPTIONS=detect_container_overflow=0.\n"
519-
"If you suspect a false positive see also: "
520-
"https://github.com/google/sanitizers/wiki/"
521-
"AddressSanitizerContainerOverflow.\n");
517+
Printf(
518+
"HINT: if you don't care about these errors you may set "
519+
"ASAN_OPTIONS=detect_container_overflow=0.\n"
520+
"Or if supported by the container library, pass "
521+
"-D__ASAN_DISABLE_CONTAINER_OVERFLOW__ to the compiler to disable "
522+
" instrumentation.\n"
523+
"If you suspect a false positive see also: "
524+
"https://github.com/google/sanitizers/wiki/"
525+
"AddressSanitizerContainerOverflow.\n");
522526
}
523527

524528
static void PrintShadowByte(InternalScopedString *str, const char *before,
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Test crash gives guidance on -D__ASAN_DISABLE_CONTAINER_OVERFLOW__ and
2+
// ASAN_OPTIONS=detect_container_overflow=0
3+
// RUN: %clangxx_asan -O %s -o %t
4+
// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
5+
//
6+
// Test overflow checks can be disabled at runtime with
7+
// ASAN_OPTIONS=detect_container_overflow=0
8+
// RUN: %env_asan_opts=detect_container_overflow=0 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NOCRASH %s
9+
//
10+
// Illustrate use of -D__ASAN_DISABLE_CONTAINER_OVERFLOW__ flag to suppress
11+
// overflow checks at compile time.
12+
// RUN: %clangxx_asan -D__ASAN_DISABLE_CONTAINER_OVERFLOW__ -O %s -o %t-no-overflow
13+
// RUN: %run %t-no-overflow 2>&1 | FileCheck --check-prefix=CHECK-NOCRASH %s
14+
//
15+
16+
#include <assert.h>
17+
#include <stdio.h>
18+
#include <string.h>
19+
20+
// public definition of __sanitizer_annotate_contiguous_container
21+
#include "sanitizer/common_interface_defs.h"
22+
23+
static volatile int one = 1;
24+
25+
int TestCrash() {
26+
long t[100];
27+
t[60] = 0;
28+
#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__
29+
__sanitizer_annotate_contiguous_container(&t[0], &t[0] + 100, &t[0] + 100,
30+
&t[0] + 50);
31+
#endif
32+
// CHECK-CRASH: AddressSanitizer: container-overflow
33+
// CHECK-CRASH: ASAN_OPTIONS=detect_container_overflow=0
34+
// CHECK-CRASH: __ASAN_DISABLE_CONTAINER_OVERFLOW__
35+
// CHECK-NOCRASH-NOT: AddressSanitizer: container-overflow
36+
// CHECK-NOCRASH-NOT: ASAN_OPTIONS=detect_container_overflow=0
37+
// CHECK-NOCRASH-NOT: __ASAN_DISABLE_CONTAINER_OVERFLOW__
38+
return (int)t[60 * one]; // Touches the poisoned memory.
39+
}
40+
41+
int main(int argc, char **argv) {
42+
43+
int retval = 0;
44+
45+
retval = TestCrash();
46+
47+
printf("Exiting main\n");
48+
49+
return retval;
50+
}

0 commit comments

Comments
 (0)