@@ -6,73 +6,78 @@ The tracking issue for this feature is: [#39699](https://github.com/rust-lang/ru
66
77This feature allows for use of one of following sanitizers:
88
9- *  [ AddressSanitizer] [ clang-asan ]  a faster memory error detector. Can
10-   detect out-of-bounds access to heap, stack, and globals, use after free, use
11-   after return, double free, invalid free, memory leaks.
9+ *  [ AddressSanitizer] [ clang-asan ]  a fast memory error detector.
1210*  [ LeakSanitizer] [ clang-lsan ]  a run-time memory leak detector.
1311*  [ MemorySanitizer] [ clang-msan ]  a detector of uninitialized reads.
1412*  [ ThreadSanitizer] [ clang-tsan ]  a fast data race detector.
1513
16- To enable a sanitizer compile with ` -Zsanitizer=... `  option, where value is one
17- of ` address ` , ` leak ` , ` memory `  or ` thread ` .
14+ To enable a sanitizer compile with ` -Zsanitizer=address ` , ` -Zsanitizer=leak ` ,
15+ ` -Zsanitizer=memory `  or ` -Zsanitizer=thread ` . Only a single sanitizer can be
16+ enabled at a time.
1817
19- # Examples  
18+ # AddressSanitizer  
2019
21- This sections show various issues that can be detected with sanitizers.  For
22- simplicity, the examples are prepared under assumption that optimization level
23- used is zero.
20+ AddressSanitizer is a memory error detector. It can detect the following types
21+ of bugs:
2422
25- ## AddressSanitizer  
23+ *  Out of bound accesses to heap, stack and globals
24+ *  Use after free
25+ *  Use after return (runtime flag ` ASAN_OPTIONS=detect_stack_use_after_return=1 ` )
26+ *  Use after scope
27+ *  Double-free, invalid free
28+ *  Memory leaks
29+ 
30+ AddressSanitizer is supported on the following targets:
31+ 
32+ *  ` x86_64-apple-darwin ` 
33+ *  ` x86_64-unknown-linux-gnu ` 
34+ 
35+ AddressSanitizer works with non-instrumented code although it will impede its
36+ ability to detect some bugs.  It is not expected to produce false positive
37+ reports.
38+ 
39+ ## Examples  
2640
2741Stack buffer overflow:
2842
29- ``` shell 
30- $ cat a.rs
43+ ``` rust 
3144fn  main () {
3245    let  xs  =  [0 , 1 , 2 , 3 ];
3346    let  _y  =  unsafe  { * xs . as_ptr (). offset (4 ) };
3447}
35- $ rustc -Zsanitizer=address a.rs
36- $ ./a
37- =================================================================
38- ==10029==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcc15f43d0 at pc 0x55f77dc015c5 bp 0x7ffcc15f4390 sp 0x7ffcc15f4388
39- READ of size 4 at 0x7ffcc15f43d0 thread T0
40-     # 0 0x55f77dc015c4 in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa5c4)
41-     # 1 0x55f77dc01cdb in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::haa8c76d1faa7b7ca (/tmp/a+0xacdb)
42-     # 2 0x55f77dc90f02 in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::hfeb9a1aef9ac820d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:48:12
43-     # 3 0x55f77dc90f02 in std::panicking::try::do_call::h12f0919717b8e0a6 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:288:39
44-     # 4 0x55f77dc926c9 in __rust_maybe_catch_panic /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libpanic_unwind/lib.rs:80:7
45-     # 5 0x55f77dc9197c in std::panicking::try::h413b21cdcd6cfd86 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:267:12
46-     # 6 0x55f77dc9197c in std::panic::catch_unwind::hc5cc8ef2fd73424d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panic.rs:396:8
47-     # 7 0x55f77dc9197c in std::rt::lang_start_internal::h2039f418ab92218f /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:47:24
48-     # 8 0x55f77dc01c61 in std::rt::lang_start::ha905d28f6b61d691 (/tmp/a+0xac61)
49-     # 9 0x55f77dc0163a in main (/tmp/a+0xa63a)
50-     # 10 0x7f9b3cf5bbba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba)
51-     # 11 0x55f77dc01289 in _start (/tmp/a+0xa289)
52- 
53- Address 0x7ffcc15f43d0 is located in  stack of thread T0 at offset 48 in  frame
54-     # 0 0x55f77dc0135f in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa35f)
48+ ``` 
49+ 
50+ ``` shell 
51+ $ export  RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
52+ $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
53+ ==37882==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe400e6250 at pc 0x5609a841fb20 bp 0x7ffe400e6210 sp 0x7ffe400e6208
54+ READ of size 4 at 0x7ffe400e6250 thread T0
55+     # 0 0x5609a841fb1f in example::main::h628ffc6626ed85b2 /.../src/main.rs:3:23
56+     ...
57+ 
58+ Address 0x7ffe400e6250 is located in  stack of thread T0 at offset 48 in  frame
59+     # 0 0x5609a841f8af in example::main::h628ffc6626ed85b2 /.../src/main.rs:1
5560
5661  This frame has 1 object(s):
57-     [32, 48) ' xs'   <==  Memory access at offset 48 overflows this variable
62+     [32, 48) ' xs'   (line 2)  <==  Memory access at offset 48 overflows this variable
5863HINT: this may be a false  positive if  your program uses some custom stack unwind mechanism, swapcontext or vfork
5964      (longjmp and C++ exceptions * are*  supported)
60- SUMMARY: AddressSanitizer: stack-buffer-overflow (/tmp/a+0xa5c4)  in  a ::main::hab3bd2a745c2d0ac 
65+ SUMMARY: AddressSanitizer: stack-buffer-overflow /.../src/main.rs:3:23  in  example ::main::h628ffc6626ed85b2 
6166Shadow bytes around the buggy address:
62-   0x1000182b6820 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
63-   0x1000182b6830 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
64-   0x1000182b6840 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
65-   0x1000182b6850 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
66-   0x1000182b6860 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
67- => 0x1000182b6870 : 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
68-   0x1000182b6880 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
69-   0x1000182b6890 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70-   0x1000182b68a0: 00 00 00 00  00 00 00 00  00 00 00 00 00 00 00 00
71-   0x1000182b68b0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
72-   0x1000182b68c0 : 00 00 00 00  00 00 00 00 00 00 00 00 00 00 00 00
67+   0x100048014bf0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
68+   0x100048014c00 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
69+   0x100048014c10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70+   0x100048014c20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
71+   0x100048014c30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
72+ => 0x100048014c40 : 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
73+   0x100048014c50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
74+   0x100048014c60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
75+   0x100048014c70: f1 f1 f1 f1  00 00 f3 f3  00 00 00 00 00 00 00 00
76+   0x100048014c80 : 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 
77+   0x100048014c90 : 00 00 f3 f3  00 00 00 00 00 00 00 00 00 00 00 00
7378Shadow byte legend (one shadow byte represents 8 application bytes):
7479  Addressable:           00
75-   Partially addressable: 01 02 03 04 05 06 07  
80+   Partially addressable: 01 02 03 04 05 06 07
7681  Heap left redzone:       fa
7782  Freed heap region:       fd
7883  Stack left redzone:      f1
@@ -90,13 +95,12 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
9095  Left alloca redzone:     ca
9196  Right alloca redzone:    cb
9297  Shadow gap:              cc
93- ==10029 ==ABORTING
98+ ==37882 ==ABORTING
9499` ` ` 
95100
96101Use of a stack object after its scope has already ended: 
97102
98- ` ` `  shell
99- $ cat b.rs
103+ ` ` `  rust
100104static mut P: * mut usize = std::ptr::null_mut ();
101105
102106fn main () {
@@ -108,42 +112,38 @@ fn main() {
108112        std::ptr::write_volatile(P, 123); 
109113    }
110114}
111- $ rustc -Zsanitizer=address b.rs
112- $./b
115+ ` ` ` 
116+ 
117+ ` ` `  shell
118+ $ export  RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
119+ $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
113120=================================================================
114- ==424427==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7fff67be6be0 at pc 0x5647a3ea4658 bp 0x7fff67be6b90 sp 0x7fff67be6b88
115- WRITE of size 8 at 0x7fff67be6be0 thread T0
116-     # 0 0x5647a3ea4657 in core::ptr::write_volatile::h4b04601757d0376d (/tmp/b+0xb8657)
117-     # 1 0x5647a3ea4432 in b::main::h5574a756e615c9cf (/tmp/b+0xb8432)
118-     # 2 0x5647a3ea480b in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd57e7ee01866077e (/tmp/b+0xb880b)
119-     # 3 0x5647a3eab412 in std::panicking::try::do_call::he0421ca82dd11ba3 (.llvm.8083791802951296215) (/tmp/b+0xbf412)
120-     # 4 0x5647a3eacb26 in __rust_maybe_catch_panic (/tmp/b+0xc0b26)
121-     # 5 0x5647a3ea5b66 in std::rt::lang_start_internal::h19bc96b28f670a64 (/tmp/b+0xb9b66)
122-     # 6 0x5647a3ea4788 in std::rt::lang_start::h642d10b4b6965fb8 (/tmp/b+0xb8788)
123-     # 7 0x5647a3ea449a in main (/tmp/b+0xb849a)
124-     # 8 0x7fd1d18b3bba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba)
125-     # 9 0x5647a3df7299 in _start (/tmp/b+0xb299)
126- 
127- Address 0x7fff67be6be0 is located in  stack of thread T0 at offset 32 in  frame
128-     # 0 0x5647a3ea433f in b::main::h5574a756e615c9cf (/tmp/b+0xb833f)
121+ ==39249==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffc7ed3e1a0 at pc 0x55c98b262a8e bp 0x7ffc7ed3e050 sp 0x7ffc7ed3e048
122+ WRITE of size 8 at 0x7ffc7ed3e1a0 thread T0
123+     # 0 0x55c98b262a8d in core::ptr::write_volatile::he21f1df5a82f329a /.../src/rust/src/libcore/ptr/mod.rs:1048:5
124+     # 1 0x55c98b262cd2 in example::main::h628ffc6626ed85b2 /.../src/main.rs:9:9
125+     ...
126+ 
127+ Address 0x7ffc7ed3e1a0 is located in  stack of thread T0 at offset 32 in  frame
128+     # 0 0x55c98b262bdf in example::main::h628ffc6626ed85b2 /.../src/main.rs:3
129129
130130  This frame has 1 object(s):
131-     [32, 40) ' x'   <==  Memory access at offset 32 is inside this variable
131+     [32, 40) ' x'   (line 6)  <==  Memory access at offset 32 is inside this variable
132132HINT: this may be a false  positive if  your program uses some custom stack unwind mechanism, swapcontext or vfork
133133      (longjmp and C++ exceptions * are*  supported)
134- SUMMARY: AddressSanitizer: stack-use-after-scope (/tmp/b+0xb8657)  in  core::ptr::write_volatile::h4b04601757d0376d 
134+ SUMMARY: AddressSanitizer: stack-use-after-scope /.../src/rust/src/libcore/ptr/mod.rs:1048:5  in  core::ptr::write_volatile::he21f1df5a82f329a 
135135Shadow bytes around the buggy address:
136-   0x10006cf74d20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
137-   0x10006cf74d30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
138-   0x10006cf74d40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
139-   0x10006cf74d50: 00 00 00 00  00 00 00 00 00 00 00 00 00 00 00 00
140-   0x10006cf74d60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
141- => 0x10006cf74d70: 00 00 00 00 00 00 00 00  f1 f1 f1 f1[f8]f3 f3 f3
142-   0x10006cf74d80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
143-   0x10006cf74d90 : 00 00 00 00  00 00 00 00 00 00 00 00 00 00 00 00
144-   0x10006cf74da0 : 00 00 00 00 00 00 00 00 00 00 00 00  00 00 00 00 
145-   0x10006cf74db0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
146-   0x10006cf74dc0:  f1 f1 f1 f1 00 f3  f3 f3 00 00 00 00  00 00 00 00
136+   0x10000fd9fbe0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
137+   0x10000fd9fbf0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
138+   0x10000fd9fc00 : 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 
139+   0x10000fd9fc10: f8 f8 f3 f3  00 00 00 00 00 00 00 00 00 00 00 00
140+   0x10000fd9fc20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
141+ => 0x10000fd9fc30:  f1 f1 f1 f1[f8]f3 f3 f3 00 00 00 00 00 00 00 00 
142+   0x10000fd9fc40 : 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 
143+   0x10000fd9fc50 : 00 00 f3 f3  00 00 00 00 00 00 00 00 00 00 00 00
144+   0x10000fd9fc60 : 00 00 00 00 00 00 00 00 f1 f1 f1 f1  00 00 f3 f3 
145+   0x10000fd9fc70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
146+   0x10000fd9fc80: 00 00 00 00  f1 f1 f1 f1 00 00  f3 f3 00 00 00 00
147147Shadow byte legend (one shadow byte represents 8 application bytes):
148148  Addressable:           00
149149  Partially addressable: 01 02 03 04 05 06 07
@@ -164,17 +164,26 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
164164  Left alloca redzone:     ca
165165  Right alloca redzone:    cb
166166  Shadow gap:              cc
167- ==424427 ==ABORTING
167+ ==39249 ==ABORTING
168168` ` ` 
169169
170- # # MemorySanitizer
170+ #  MemorySanitizer
171+ 
172+ MemorySanitizer is detector of uninitialized reads. It is only supported on the 
173+ `  x86_64-unknown-linux-gnu`  target.
174+ 
175+ MemorySanitizer requires all program code to be instrumented. C/C++ dependencies 
176+ need to be recompiled using Clang with `  -fsanitize=memory`  option. Failing to
177+ achieve that will result in  false  positive reports. 
178+ 
179+ # # Example
171180
172- Use of uninitialized memory. Note that we are using `  -Zbuild-std`  to instrument
173- the standard library, and passing `  -Zsanitizer-track-origins`  to track the
181+ Detecting the use of uninitialized memory. The `  -Zbuild-std`  flag rebuilds and
182+ instruments the standard library, and is strictly necessary for  the correct 
183+ operation of the tool. The `  -Zsanitizer-track-origins`  enables tracking of the
174184origins of uninitialized memory: 
175185
176- ` ` `  shell
177- $ cat src/main.rs
186+ ` ` `  rust
178187use std::mem::MaybeUninit; 
179188
180189fn main () {
@@ -184,7 +193,9 @@ fn main() {
184193        println! (" {}"  , a[2]); 
185194    }
186195}
196+ ` ` ` 
187197
198+ ` ` `  shell
188199$ export  \
189200  CC= clang \
190201  CXX= clang++ \
@@ -193,7 +204,7 @@ $ export \
193204  RUSTFLAGS= ' -Zsanitizer=memory -Zsanitizer-memory-track-origins'   \
194205  RUSTDOCFLAGS= ' -Zsanitizer=memory -Zsanitizer-memory-track-origins' 
195206$ cargo clean
196- $ cargo -Zbuild-std run  --target x86_64-unknown-linux-gnu
207+ $ cargo run  -Zbuild-std --target x86_64-unknown-linux-gnu
197208== 9416== WARNING: MemorySanitizer: use-of-uninitialized-value
198209    # 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
199210...
@@ -205,6 +216,55 @@ $ cargo -Zbuild-std run --target x86_64-unknown-linux-gnu
205216    # 0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
206217` ` ` 
207218
219+ #  ThreadSanitizer
220+ 
221+ ThreadSanitizer is a data race detection tool. It is supported on the following 
222+ targets: 
223+ 
224+ *  `  x86_64-apple-darwin` 
225+ *  `  x86_64-unknown-linux-gnu` 
226+ 
227+ To work correctly ThreadSanitizer needs to be " aware"   of all synchronization 
228+ operations in  a program. It generally achieves that through combination of 
229+ library interception (for example synchronization performed through 
230+ ` pthread_mutex_lock`   / ` pthread_mutex_unlock`  ) and compile time  instrumentation
231+ (e.g. atomic operations). Using it without instrumenting all the program code 
232+ can lead to false  positive reports. 
233+ 
234+ ThreadSanitizer does not support atomic fences `  std::sync::atomic::fence` ,
235+ nor synchronization performed using inline assembly code. 
236+ 
237+ # # Example
238+ 
239+ ` ` `  rust
240+ static mut A: usize =  0; 
241+ 
242+ fn main () {
243+     let  t = std::thread::spawn(||  {
244+         unsafe { A += 1 }; 
245+     }); 
246+     unsafe { A += 1 }; 
247+ 
248+     t.join().unwrap ();
249+ }
250+ ` ` ` 
251+ 
252+ ` ` `  shell
253+ $ export  RUSTFLAGS=-Zsanitizer=thread RUSTDOCFLAGS=-Zsanitizer=thread
254+ $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
255+ ==================
256+ WARNING: ThreadSanitizer: data race (pid=10574)
257+   Read of size 8 at 0x5632dfe3d030 by thread T1:
258+     # 0 example::main::_$u7b$$u7b$closure$u7d$$u7d$::h23f64b0b2f8c9484 ../src/main.rs:5:18 (example+0x86cec)
259+     ...
260+ 
261+   Previous write of size 8 at 0x5632dfe3d030 by main thread:
262+     # 0 example::main::h628ffc6626ed85b2 /.../src/main.rs:7:14 (example+0x868c8)
263+     ...
264+     # 11 main <null> (example+0x86a1a)
265+ 
266+   Location is global ' example::A::h43ac149ddf992709'   of size 8 at 0x5632dfe3d030 (example+0x000000bd9030)
267+ ` ` ` 
208268
209269#  Instrumentation of external dependencies and std
210270
@@ -231,6 +291,10 @@ In more practical terms when using cargo always remember to pass `--target`
231291flag, so that rustflags will not be applied to build scripts and procedural 
232292macros. 
233293
294+ # Symbolizing the Reports 
295+ 
296+ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PATH`. 
297+ 
234298# Additional Information 
235299
236300* [Sanitizers project page](https://github.com/google/sanitizers/wiki/) 
0 commit comments