Skip to content

Commit 913344b

Browse files
authored
[Clang] Improve documentation for __builtin_allow_sanitize_check() (#175106)
Clarify that the builtin is intended for guarding explicit sanitizer checks that use the runtime API to perform such checks. Update the description to use "allowed" instead of "active" to better reflect the intended usage and semantics, which would allow policy refinements in future [1]. Also make the examples more concrete. [1] https://discourse.llvm.org/t/explicit-sanitizer-checks-with-builtin-allow-sanitize-check/89383
1 parent 5b9751b commit 913344b

File tree

3 files changed

+48
-39
lines changed

3 files changed

+48
-39
lines changed

clang/docs/AddressSanitizer.rst

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -269,37 +269,40 @@ Interaction of Inlining with Disabling Sanitizer Instrumentation
269269
#define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
270270
#endif
271271
272-
Conditional Sanitizer Checks with ``__builtin_allow_sanitize_check``
273-
--------------------------------------------------------------------
272+
Explicit Sanitizer Checks with ``__builtin_allow_sanitize_check``
273+
-----------------------------------------------------------------
274274

275275
The ``__builtin_allow_sanitize_check("address")`` builtin can be used to
276-
conditionally execute code only when AddressSanitizer is active for the current
277-
function (after inlining). This is particularly useful for inserting explicit,
278-
sanitizer-specific checks around operations like syscalls or inline assembly,
279-
which might otherwise be unchecked by the sanitizer.
276+
conditionally execute code depending on whether AddressSanitizer checks are
277+
enabled and permitted by the current policy (after inlining). This is
278+
particularly useful for inserting explicit, sanitizer-specific checks around
279+
operations like syscalls or inline assembly, which might otherwise be unchecked
280+
by the sanitizer.
280281

281282
Example:
282283

283284
.. code-block:: c
284285
286+
void __asan_load8(void *);
287+
285288
inline __attribute__((always_inline))
286-
void copy_to_device(void *addr, size_t size) {
287-
if (__builtin_allow_sanitize_check("address")) {
288-
// Custom checks that address range is valid.
289-
}
290-
// ... actual device memory copy logic, potentially a syscall ...
289+
void my_helper(void *addr) {
290+
if (__builtin_allow_sanitize_check("address"))
291+
__asan_load8(addr);
292+
// ... actual logic, e.g. inline assembly ...
293+
asm volatile ("..." : : "r" (addr) : "memory");
291294
}
292295
293296
void instrumented_function() {
294297
...
295-
copy_to_device(buf, sizeof(buf)); // checks are active
298+
my_helper(buf); // checks are active
296299
...
297300
}
298301
299302
__attribute__((no_sanitize("address")))
300303
void uninstrumented_function() {
301304
...
302-
copy_to_device(buf, sizeof(buf)); // checks are skipped
305+
my_helper(buf); // checks are skipped
303306
...
304307
}
305308

clang/docs/MemorySanitizer.rst

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,37 +117,40 @@ Interaction of Inlining with Disabling Sanitizer Instrumentation
117117
#define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
118118
#endif
119119

120-
Conditional Sanitizer Checks with ``__builtin_allow_sanitize_check``
121-
--------------------------------------------------------------------
120+
Explicit Sanitizer Checks with ``__builtin_allow_sanitize_check``
121+
-----------------------------------------------------------------
122122

123123
The ``__builtin_allow_sanitize_check("memory")`` builtin can be used to
124-
conditionally execute code only when MemorySanitizer is active for the current
125-
function (after inlining). This is particularly useful for inserting explicit,
126-
sanitizer-specific checks around operations like syscalls or inline assembly,
127-
which might otherwise be unchecked by the sanitizer.
124+
conditionally execute code depending on whether MemorySanitizer checks are
125+
enabled and permitted by the current policy (after inlining). This is
126+
particularly useful for inserting explicit, sanitizer-specific checks around
127+
operations like syscalls or inline assembly, which might otherwise be unchecked
128+
by the sanitizer.
128129

129130
Example:
130131

131132
.. code-block:: c
132133
134+
void __msan_check_mem_is_initialized(const void *, size_t);
135+
133136
inline __attribute__((always_inline))
134-
void copy_to_device(void *addr, size_t size) {
135-
if (__builtin_allow_sanitize_check("memory")) {
136-
// Custom checks if `data` is initialized.
137-
}
138-
// ... actual device memory copy logic, potentially a syscall ...
137+
void my_send(void *addr, size_t size) {
138+
if (__builtin_allow_sanitize_check("memory"))
139+
__msan_check_mem_is_initialized(addr, size);
140+
// ... syscall or other logic where MSan may not see the access ...
141+
send(addr, size);
139142
}
140143
141144
void instrumented_function() {
142145
...
143-
copy_to_device(buf, sizeof(buf)); // checks are active
146+
my_send(buf, sizeof(buf)); // checks are active
144147
...
145148
}
146149
147150
__attribute__((no_sanitize("memory")))
148151
void uninstrumented_function() {
149152
...
150-
copy_to_device(buf, sizeof(buf)); // checks are skipped
153+
my_send(buf, sizeof(buf)); // checks are skipped
151154
...
152155
}
153156

clang/docs/ThreadSanitizer.rst

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,37 +126,40 @@ Interaction of Inlining with Disabling Sanitizer Instrumentation
126126
#define ALWAYS_INLINE_IF_UNINSTRUMENTED __attribute__((always_inline))
127127
#endif
128128

129-
Conditional Sanitizer Checks with ``__builtin_allow_sanitize_check``
130-
--------------------------------------------------------------------
129+
Explicit Sanitizer Checks with ``__builtin_allow_sanitize_check``
130+
-----------------------------------------------------------------
131131

132132
The ``__builtin_allow_sanitize_check("thread")`` builtin can be used to
133-
conditionally execute code only when ThreadSanitizer is active for the current
134-
function (after inlining). This is particularly useful for inserting explicit,
135-
sanitizer-specific checks around operations like syscalls or inline assembly,
136-
which might otherwise be unchecked by the sanitizer.
133+
conditionally execute code depending on whether ThreadSanitizer checks are
134+
enabled and permitted by the current policy (after inlining). This is
135+
particularly useful for inserting explicit, sanitizer-specific checks around
136+
operations like syscalls or inline assembly, which might otherwise be unchecked
137+
by the sanitizer.
137138

138139
Example:
139140

140141
.. code-block:: c
141142
143+
void __tsan_read8(void *);
144+
142145
inline __attribute__((always_inline))
143-
void copy_to_device(void *addr, size_t size) {
144-
if (__builtin_allow_sanitize_check("thread")) {
145-
// Custom checks that `data` is not concurrently modified.
146-
}
147-
// ... actual device memory copy logic, potentially a syscall ...
146+
void my_helper(void *addr) {
147+
if (__builtin_allow_sanitize_check("thread"))
148+
__tsan_read8(addr);
149+
// ... actual logic, e.g. inline assembly ...
150+
asm volatile ("..." : : "r" (addr) : "memory");
148151
}
149152
150153
void instrumented_function() {
151154
...
152-
copy_to_device(&shared_data, size); // checks are active
155+
my_helper(&shared_data); // checks are active
153156
...
154157
}
155158
156159
__attribute__((no_sanitize("thread")))
157160
void uninstrumented_function() {
158161
...
159-
copy_to_device(&shared_data, size); // checks are skipped
162+
my_helper(&shared_data); // checks are skipped
160163
...
161164
}
162165

0 commit comments

Comments
 (0)