]> git.lizzy.rs Git - rust.git/blob - src/doc/unstable-book/src/compiler-flags/sanitizer.md
Auto merge of #97057 - bjorn3:sync_cg_clif-2022-05-15, r=bjorn3
[rust.git] / src / doc / unstable-book / src / compiler-flags / sanitizer.md
1 # `sanitizer`
2
3 The tracking issues for this feature are:
4
5 * [#39699](https://github.com/rust-lang/rust/issues/39699).
6 * [#89653](https://github.com/rust-lang/rust/issues/89653).
7
8 ------------------------
9
10 This feature allows for use of one of following sanitizers:
11
12 * [AddressSanitizer][clang-asan] a fast memory error detector.
13 * [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides
14   forward-edge control flow protection.
15 * [HWAddressSanitizer][clang-hwasan] a memory error detector similar to
16   AddressSanitizer, but based on partial hardware assistance.
17 * [LeakSanitizer][clang-lsan] a run-time memory leak detector.
18 * [MemorySanitizer][clang-msan] a detector of uninitialized reads.
19 * [MemTagSanitizer][clang-memtag] fast memory error detector based on
20   Armv8.5-A Memory Tagging Extension.
21 * [ThreadSanitizer][clang-tsan] a fast data race detector.
22
23 To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
24 `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`,
25 `-Zsanitizer=memtag`, or `-Zsanitizer=thread`. You might also need the `--target` and `build-std` flags. Example:
26 ```shell
27 $ RUSTFLAGS=-Zsanitizer=address cargo build -Zbuild-std --target x86_64-unknown-linux-gnu
28 ```
29
30 # AddressSanitizer
31
32 AddressSanitizer is a memory error detector. It can detect the following types
33 of bugs:
34
35 * Out of bound accesses to heap, stack and globals
36 * Use after free
37 * Use after return (runtime flag `ASAN_OPTIONS=detect_stack_use_after_return=1`)
38 * Use after scope
39 * Double-free, invalid free
40 * Memory leaks
41
42 The memory leak detection is enabled by default on Linux, and can be enabled
43 with runtime flag `ASAN_OPTIONS=detect_leaks=1` on macOS.
44
45 AddressSanitizer is supported on the following targets:
46
47 * `aarch64-apple-darwin`
48 * `aarch64-fuchsia`
49 * `aarch64-unknown-linux-gnu`
50 * `x86_64-apple-darwin`
51 * `x86_64-fuchsia`
52 * `x86_64-unknown-freebsd`
53 * `x86_64-unknown-linux-gnu`
54
55 AddressSanitizer works with non-instrumented code although it will impede its
56 ability to detect some bugs.  It is not expected to produce false positive
57 reports.
58
59 ## Examples
60
61 Stack buffer overflow:
62
63 ```rust
64 fn main() {
65     let xs = [0, 1, 2, 3];
66     let _y = unsafe { *xs.as_ptr().offset(4) };
67 }
68 ```
69
70 ```shell
71 $ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
72 $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
73 ==37882==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe400e6250 at pc 0x5609a841fb20 bp 0x7ffe400e6210 sp 0x7ffe400e6208
74 READ of size 4 at 0x7ffe400e6250 thread T0
75     #0 0x5609a841fb1f in example::main::h628ffc6626ed85b2 /.../src/main.rs:3:23
76     ...
77
78 Address 0x7ffe400e6250 is located in stack of thread T0 at offset 48 in frame
79     #0 0x5609a841f8af in example::main::h628ffc6626ed85b2 /.../src/main.rs:1
80
81   This frame has 1 object(s):
82     [32, 48) 'xs' (line 2) <== Memory access at offset 48 overflows this variable
83 HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
84       (longjmp and C++ exceptions *are* supported)
85 SUMMARY: AddressSanitizer: stack-buffer-overflow /.../src/main.rs:3:23 in example::main::h628ffc6626ed85b2
86 Shadow bytes around the buggy address:
87   0x100048014bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
88   0x100048014c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
89   0x100048014c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90   0x100048014c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
91   0x100048014c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
92 =>0x100048014c40: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
93   0x100048014c50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
94   0x100048014c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
95   0x100048014c70: f1 f1 f1 f1 00 00 f3 f3 00 00 00 00 00 00 00 00
96   0x100048014c80: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
97   0x100048014c90: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
98 Shadow byte legend (one shadow byte represents 8 application bytes):
99   Addressable:           00
100   Partially addressable: 01 02 03 04 05 06 07
101   Heap left redzone:       fa
102   Freed heap region:       fd
103   Stack left redzone:      f1
104   Stack mid redzone:       f2
105   Stack right redzone:     f3
106   Stack after return:      f5
107   Stack use after scope:   f8
108   Global redzone:          f9
109   Global init order:       f6
110   Poisoned by user:        f7
111   Container overflow:      fc
112   Array cookie:            ac
113   Intra object redzone:    bb
114   ASan internal:           fe
115   Left alloca redzone:     ca
116   Right alloca redzone:    cb
117   Shadow gap:              cc
118 ==37882==ABORTING
119 ```
120
121 Use of a stack object after its scope has already ended:
122
123 ```rust
124 static mut P: *mut usize = std::ptr::null_mut();
125
126 fn main() {
127     unsafe {
128         {
129             let mut x = 0;
130             P = &mut x;
131         }
132         std::ptr::write_volatile(P, 123);
133     }
134 }
135 ```
136
137 ```shell
138 $ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
139 $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
140 =================================================================
141 ==39249==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffc7ed3e1a0 at pc 0x55c98b262a8e bp 0x7ffc7ed3e050 sp 0x7ffc7ed3e048
142 WRITE of size 8 at 0x7ffc7ed3e1a0 thread T0
143     #0 0x55c98b262a8d in core::ptr::write_volatile::he21f1df5a82f329a /.../src/rust/src/libcore/ptr/mod.rs:1048:5
144     #1 0x55c98b262cd2 in example::main::h628ffc6626ed85b2 /.../src/main.rs:9:9
145     ...
146
147 Address 0x7ffc7ed3e1a0 is located in stack of thread T0 at offset 32 in frame
148     #0 0x55c98b262bdf in example::main::h628ffc6626ed85b2 /.../src/main.rs:3
149
150   This frame has 1 object(s):
151     [32, 40) 'x' (line 6) <== Memory access at offset 32 is inside this variable
152 HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
153       (longjmp and C++ exceptions *are* supported)
154 SUMMARY: AddressSanitizer: stack-use-after-scope /.../src/rust/src/libcore/ptr/mod.rs:1048:5 in core::ptr::write_volatile::he21f1df5a82f329a
155 Shadow bytes around the buggy address:
156   0x10000fd9fbe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
157   0x10000fd9fbf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
158   0x10000fd9fc00: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
159   0x10000fd9fc10: f8 f8 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
160   0x10000fd9fc20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
161 =>0x10000fd9fc30: f1 f1 f1 f1[f8]f3 f3 f3 00 00 00 00 00 00 00 00
162   0x10000fd9fc40: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
163   0x10000fd9fc50: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
164   0x10000fd9fc60: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3
165   0x10000fd9fc70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
166   0x10000fd9fc80: 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3 00 00 00 00
167 Shadow byte legend (one shadow byte represents 8 application bytes):
168   Addressable:           00
169   Partially addressable: 01 02 03 04 05 06 07
170   Heap left redzone:       fa
171   Freed heap region:       fd
172   Stack left redzone:      f1
173   Stack mid redzone:       f2
174   Stack right redzone:     f3
175   Stack after return:      f5
176   Stack use after scope:   f8
177   Global redzone:          f9
178   Global init order:       f6
179   Poisoned by user:        f7
180   Container overflow:      fc
181   Array cookie:            ac
182   Intra object redzone:    bb
183   ASan internal:           fe
184   Left alloca redzone:     ca
185   Right alloca redzone:    cb
186   Shadow gap:              cc
187 ==39249==ABORTING
188 ```
189
190 # ControlFlowIntegrity
191
192 The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially
193 provides forward-edge control flow protection for Rust-compiled code only by
194 aggregating function pointers in groups identified by their number of arguments.
195
196 Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
197 binaries" (i.e., for when C or C++ and Rust -compiled code share the same
198 virtual address space) will be provided in later work by defining and using
199 compatible type identifiers (see Type metadata in the design document in the
200 tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
201
202 LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto).
203
204 ## Example
205
206 ```text
207 #![feature(naked_functions)]
208
209 use std::arch::asm;
210 use std::mem;
211
212 fn add_one(x: i32) -> i32 {
213     x + 1
214 }
215
216 #[naked]
217 pub extern "C" fn add_two(x: i32) {
218     // x + 2 preceded by a landing pad/nop block
219     unsafe {
220         asm!(
221             "
222              nop
223              nop
224              nop
225              nop
226              nop
227              nop
228              nop
229              nop
230              nop
231              lea rax, [rdi+2]
232              ret
233         ",
234             options(noreturn)
235         );
236     }
237 }
238
239 fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
240     f(arg) + f(arg)
241 }
242
243 fn main() {
244     let answer = do_twice(add_one, 5);
245
246     println!("The answer is: {answer}");
247
248     println!("With CFI enabled, you should not see the next answer");
249     let f: fn(i32) -> i32 = unsafe {
250         // Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are
251         // invalid branch/call destinations (i.e., within the body of the function).
252         mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
253     };
254     let next_answer = do_twice(f, 5);
255
256     println!("The next answer is: {next_answer}");
257 }
258 ```
259 Fig. 1. Modified example from the [Advanced Functions and
260 Closures][rust-book-ch19-05] chapter of the [The Rust Programming
261 Language][rust-book] book.
262
263 [//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
264
265 ```shell
266 $ rustc rust_cfi.rs -o rust_cfi
267 $ ./rust_cfi
268 The answer is: 12
269 With CFI enabled, you should not see the next answer
270 The next answer is: 14
271 $
272 ```
273 Fig. 2. Build and execution of the modified example with LLVM CFI disabled.
274
275 [//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
276
277 ```shell
278 $ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi
279 $ ./rust_cfi
280 The answer is: 12
281 With CFI enabled, you should not see the next answer
282 Illegal instruction
283 $
284 ```
285 Fig. 3. Build and execution of the modified example with LLVM CFI enabled.
286
287 When LLVM CFI is enabled, if there are any attempts to change/hijack control
288 flow using an indirect branch/call to an invalid destination, the execution is
289 terminated (see Fig. 3).
290
291 ```rust
292 use std::mem;
293
294 fn add_one(x: i32) -> i32 {
295     x + 1
296 }
297
298 fn add_two(x: i32, _y: i32) -> i32 {
299     x + 2
300 }
301
302 fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
303     f(arg) + f(arg)
304 }
305
306 fn main() {
307     let answer = do_twice(add_one, 5);
308
309     println!("The answer is: {answer}");
310
311     println!("With CFI enabled, you should not see the next answer");
312     let f: fn(i32) -> i32 =
313         unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) };
314     let next_answer = do_twice(f, 5);
315
316     println!("The next answer is: {next_answer}");
317 }
318 ```
319 Fig. 4. Another modified example from the [Advanced Functions and
320 Closures][rust-book-ch19-05] chapter of the [The Rust Programming
321 Language][rust-book] book.
322
323 [//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
324
325 ```shell
326 $ rustc rust_cfi.rs -o rust_cfi
327 $ ./rust_cfi
328 The answer is: 12
329 With CFI enabled, you should not see the next answer
330 The next answer is: 14
331 $
332 ```
333 Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
334
335 [//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
336
337 ```shell
338 $ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi
339 $ ./rust_cfi
340 The answer is: 12
341 With CFI enabled, you should not see the next answer
342 Illegal instruction
343 $
344 ```
345 Fig. 6. Build and execution of the modified example with LLVM CFI enabled.
346
347 When LLVM CFI is enabled, if there are any attempts to change/hijack control
348 flow using an indirect branch/call to a function with different number of
349 arguments than intended/passed in the call/branch site, the execution is also
350 terminated (see Fig. 6).
351
352 Forward-edge control flow protection not only by aggregating function pointers
353 in groups identified by their number of arguments, but also their argument
354 types, will also be provided in later work by defining and using compatible type
355 identifiers (see Type metadata in the design document in the tracking
356 issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
357
358 [rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
359 [rust-book]: https://doc.rust-lang.org/book/title-page.html
360
361 # HWAddressSanitizer
362
363 HWAddressSanitizer is a newer variant of AddressSanitizer that consumes much
364 less memory.
365
366 HWAddressSanitizer is supported on the following targets:
367
368 * `aarch64-linux-android`
369 * `aarch64-unknown-linux-gnu`
370
371 HWAddressSanitizer requires `tagged-globals` target feature to instrument
372 globals. To enable this target feature compile with `-C
373 target-feature=+tagged-globals`
374
375 ## Example
376
377 Heap buffer overflow:
378
379 ```rust
380 fn main() {
381     let xs = vec![0, 1, 2, 3];
382     let _y = unsafe { *xs.as_ptr().offset(4) };
383 }
384 ```
385
386 ```shell
387 $ rustc main.rs -Zsanitizer=hwaddress -C target-feature=+tagged-globals -C
388 linker=aarch64-linux-gnu-gcc -C link-arg=-fuse-ld=lld --target
389 aarch64-unknown-linux-gnu
390 ```
391
392 ```shell
393 $ ./main
394 ==241==ERROR: HWAddressSanitizer: tag-mismatch on address 0xefdeffff0050 at pc 0xaaaae0ae4a98
395 READ of size 4 at 0xefdeffff0050 tags: 2c/00 (ptr/mem) in thread T0
396     #0 0xaaaae0ae4a94  (/.../main+0x54a94)
397     ...
398
399 [0xefdeffff0040,0xefdeffff0060) is a small allocated heap chunk; size: 32 offset: 16
400 0xefdeffff0050 is located 0 bytes to the right of 16-byte region [0xefdeffff0040,0xefdeffff0050)
401 allocated here:
402     #0 0xaaaae0acb80c  (/.../main+0x3b80c)
403     ...
404
405 Thread: T0 0xeffe00002000 stack: [0xffffc28ad000,0xffffc30ad000) sz: 8388608 tls: [0xffffaa10a020,0xffffaa10a7d0)
406 Memory tags around the buggy address (one tag corresponds to 16 bytes):
407   0xfefcefffef80: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
408   0xfefcefffef90: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
409   0xfefcefffefa0: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
410   0xfefcefffefb0: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
411   0xfefcefffefc0: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
412   0xfefcefffefd0: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
413   0xfefcefffefe0: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
414   0xfefcefffeff0: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
415 =>0xfefceffff000: d7  d7  05  00  2c [00] 00  00  00  00  00  00  00  00  00  00
416   0xfefceffff010: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
417   0xfefceffff020: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
418   0xfefceffff030: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
419   0xfefceffff040: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
420   0xfefceffff050: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
421   0xfefceffff060: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
422   0xfefceffff070: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
423   0xfefceffff080: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
424 Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
425   0xfefcefffeff0: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
426 =>0xfefceffff000: ..  ..  8c  ..  .. [..] ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
427   0xfefceffff010: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
428 See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags
429 Registers where the failure occurred (pc 0xaaaae0ae4a98):
430     x0  2c00efdeffff0050  x1  0000000000000004  x2  0000000000000004  x3  0000000000000000
431     x4  0000fffefc30ac37  x5  000000000000005d  x6  00000ffffc30ac37  x7  0000efff00000000
432     x8  2c00efdeffff0050  x9  0200efff00000000  x10 0000000000000000  x11 0200efff00000000
433     x12 0200effe00000310  x13 0200effe00000310  x14 0000000000000008  x15 5d00ffffc30ac360
434     x16 0000aaaae0ad062c  x17 0000000000000003  x18 0000000000000001  x19 0000ffffc30ac658
435     x20 4e00ffffc30ac6e0  x21 0000aaaae0ac5e10  x22 0000000000000000  x23 0000000000000000
436     x24 0000000000000000  x25 0000000000000000  x26 0000000000000000  x27 0000000000000000
437     x28 0000000000000000  x29 0000ffffc30ac5a0  x30 0000aaaae0ae4a98
438 SUMMARY: HWAddressSanitizer: tag-mismatch (/.../main+0x54a94)
439 ```
440
441 # LeakSanitizer
442
443 LeakSanitizer is run-time memory leak detector.
444
445 LeakSanitizer is supported on the following targets:
446
447 * `aarch64-apple-darwin`
448 * `aarch64-unknown-linux-gnu`
449 * `x86_64-apple-darwin`
450 * `x86_64-unknown-linux-gnu`
451
452 # MemorySanitizer
453
454 MemorySanitizer is detector of uninitialized reads.
455
456 MemorySanitizer is supported on the following targets:
457
458 * `aarch64-unknown-linux-gnu`
459 * `x86_64-unknown-freebsd`
460 * `x86_64-unknown-linux-gnu`
461
462 MemorySanitizer requires all program code to be instrumented. C/C++ dependencies
463 need to be recompiled using Clang with `-fsanitize=memory` option. Failing to
464 achieve that will result in false positive reports.
465
466 ## Example
467
468 Detecting the use of uninitialized memory. The `-Zbuild-std` flag rebuilds and
469 instruments the standard library, and is strictly necessary for the correct
470 operation of the tool. The `-Zsanitizer-memory-track-origins` enables tracking
471 of the origins of uninitialized memory:
472
473 ```rust
474 use std::mem::MaybeUninit;
475
476 fn main() {
477     unsafe {
478         let a = MaybeUninit::<[usize; 4]>::uninit();
479         let a = a.assume_init();
480         println!("{}", a[2]);
481     }
482 }
483 ```
484
485 ```shell
486 $ export \
487   RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' \
488   RUSTDOCFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins'
489 $ cargo clean
490 $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
491 ==9416==WARNING: MemorySanitizer: use-of-uninitialized-value
492     #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16
493 ...
494   Uninitialized value was stored to memory at
495     #0 0x560c04ae898a in __msan_memcpy.part.0 $RUST/src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cc:1558:3
496     #1 0x560c04b2bf88 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:6:16
497
498   Uninitialized value was created by an allocation of 'a' in the stack frame of function '_ZN6memory4main17hd2333c1899d997f5E'
499     #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
500 ```
501
502 # MemTagSanitizer
503
504 MemTagSanitizer detects a similar class of errors as AddressSanitizer and HardwareAddressSanitizer, but with lower overhead suitable for use as hardening for production binaries.
505
506 MemTagSanitizer is supported on the following targets:
507
508 * `aarch64-linux-android`
509 * `aarch64-unknown-linux-gnu`
510
511 MemTagSanitizer requires hardware support and the `mte` target feature.
512 To enable this target feature compile with `-C target-feature="+mte"`.
513
514 More information can be found in the associated [LLVM documentation](https://llvm.org/docs/MemTagSanitizer.html).
515
516 # ThreadSanitizer
517
518 ThreadSanitizer is a data race detection tool. It is supported on the following
519 targets:
520
521 * `aarch64-apple-darwin`
522 * `aarch64-unknown-linux-gnu`
523 * `x86_64-apple-darwin`
524 * `x86_64-unknown-freebsd`
525 * `x86_64-unknown-linux-gnu`
526
527 To work correctly ThreadSanitizer needs to be "aware" of all synchronization
528 operations in a program. It generally achieves that through combination of
529 library interception (for example synchronization performed through
530 `pthread_mutex_lock` / `pthread_mutex_unlock`) and compile time instrumentation
531 (e.g. atomic operations). Using it without instrumenting all the program code
532 can lead to false positive reports.
533
534 ThreadSanitizer does not support atomic fences `std::sync::atomic::fence`,
535 nor synchronization performed using inline assembly code.
536
537 ## Example
538
539 ```rust
540 static mut A: usize = 0;
541
542 fn main() {
543     let t = std::thread::spawn(|| {
544         unsafe { A += 1 };
545     });
546     unsafe { A += 1 };
547
548     t.join().unwrap();
549 }
550 ```
551
552 ```shell
553 $ export RUSTFLAGS=-Zsanitizer=thread RUSTDOCFLAGS=-Zsanitizer=thread
554 $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
555 ==================
556 WARNING: ThreadSanitizer: data race (pid=10574)
557   Read of size 8 at 0x5632dfe3d030 by thread T1:
558     #0 example::main::_$u7b$$u7b$closure$u7d$$u7d$::h23f64b0b2f8c9484 ../src/main.rs:5:18 (example+0x86cec)
559     ...
560
561   Previous write of size 8 at 0x5632dfe3d030 by main thread:
562     #0 example::main::h628ffc6626ed85b2 /.../src/main.rs:7:14 (example+0x868c8)
563     ...
564     #11 main <null> (example+0x86a1a)
565
566   Location is global 'example::A::h43ac149ddf992709' of size 8 at 0x5632dfe3d030 (example+0x000000bd9030)
567 ```
568
569 # Instrumentation of external dependencies and std
570
571 The sanitizers to varying degrees work correctly with partially instrumented
572 code. On the one extreme is LeakSanitizer that doesn't use any compile time
573 instrumentation, on the other is MemorySanitizer that requires that all program
574 code to be instrumented (failing to achieve that will inevitably result in
575 false positives).
576
577 It is strongly recommended to combine sanitizers with recompiled and
578 instrumented standard library, for example using [cargo `-Zbuild-std`
579 functionality][build-std].
580
581 [build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
582
583 # Build scripts and procedural macros
584
585 Use of sanitizers together with build scripts and procedural macros is
586 technically possible, but in almost all cases it would be best avoided.  This
587 is especially true for procedural macros which would require an instrumented
588 version of rustc.
589
590 In more practical terms when using cargo always remember to pass `--target`
591 flag, so that rustflags will not be applied to build scripts and procedural
592 macros.
593
594 # Symbolizing the Reports
595
596 Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PATH`.
597
598 # Additional Information
599
600 * [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
601 * [AddressSanitizer in Clang][clang-asan]
602 * [ControlFlowIntegrity in Clang][clang-cfi]
603 * [HWAddressSanitizer in Clang][clang-hwasan]
604 * [LeakSanitizer in Clang][clang-lsan]
605 * [MemorySanitizer in Clang][clang-msan]
606 * [ThreadSanitizer in Clang][clang-tsan]
607
608 [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
609 [clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
610 [clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
611 [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
612 [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
613 [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html