Skip to content

Commit 1755359

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 0fefa56 commit 1755359

File tree

3 files changed

+109
-5
lines changed

3 files changed

+109
-5
lines changed

clang/docs/AddressSanitizer.rst

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,19 @@ 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 false
178+
positives.
179+
167180
Memory leak detection
168181
---------------------
169182

@@ -242,6 +255,43 @@ AddressSanitizer also supports
242255
works similar to ``__attribute__((no_sanitize("address")))``, but it also
243256
prevents instrumentation performed by other sanitizers.
244257

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

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+
"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 crash 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 crash 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 crash 2>&1 | FileCheck --check-prefix=CHECK-NOCRASH %s
14+
//
15+
16+
#include <assert.h>
17+
#include <string.h>
18+
#include <stdio.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: ASAN_OPTIONS=detect_container_overflow=0
36+
// CHECK-NOCRASH-NOT: __ASAN_DISABLE_CONTAINER_OVERFLOW__
37+
return (int)t[60 * one]; // Touches the poisoned memory.
38+
}
39+
40+
int main(int argc, char **argv) {
41+
42+
int retval = 0;
43+
assert(argc == 2);
44+
if (!strcmp(argv[1], "crash"))
45+
retval=TestCrash();
46+
47+
printf("Exiting main\n");
48+
49+
return retval;
50+
}

0 commit comments

Comments
 (0)