How-to: Sanitize your Rust code!

Overview

rust-san

How-to: Sanitize your Rust code!

Intro

As of nightly-2017-02-15, rustc ships with experimental support for the following sanitizers:

Note that sanitizer support is available on x86_64 Linux and on x86_64 macOS (ASan and TSan only).

How to use the sanitizers?

You have to compile your crate and all its dependencies with the -Z sanitizer flag. Setting RUSTFLAGS does the trick:

# if you have a binary crate (an application) or want to sanitize an example, use `cargo run`
$ RUSTFLAGS="-Z sanitizer=$SAN" cargo run --target x86_64-unknown-linux-gnu

# if you have a library crate, use `cargo test` to sanitize your unit tests
$ RUSTFLAGS="-Z sanitizer=$SAN" cargo test --target x86_64-unknown-linux-gnu

Where $SAN is one of address, leak, memory or thread.

Be sure to always pass --target x86_64-unknown-linux-gnu to Cargo or else you'll end up sanitizing the build scripts that Cargo runs or run into compilation error if your crate depends on a dylib.

Examples

This section shows what kind of issues can be detected with the sanitizers through some examples that you can find in this repository

AddressSanitizer

This sanitizer can detect, among other things, out of bounds accesses and uses of freed memory.

Out of bounds access

asan/examples/out-of-bounds.rs

fn main() {
    let xs = [0, 1, 2, 3];
    let y = unsafe { *xs.as_ptr().offset(4) };
}
$ ( cd asan && \
    RUSTFLAGS="-Z sanitizer=address" cargo run --target x86_64-unknown-linux-gnu --example out-of-bounds )
     Running `target/x86_64-unknown-linux-gnu/debug/examples/out-of-bounds`
=================================================================
==821==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe9808e5f0 at pc 0x56500e096f7e bp 0x7ffe9808e5b0 sp 0x7ffe9808e5a8
READ of size 4 at 0x7ffe9808e5f0 thread T0
    #0 0x56500e096f7d in out_of_bounds::main::h86e0ef2cff62a67d $PWD/examples/out-of-bounds.rs:3
    #1 0x56500e18b536 in __rust_maybe_catch_panic ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/out-of-bounds+0xfe536)
    #2 0x56500e183ee9 in std::rt::lang_start::h6954771f55df116b ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/out-of-bounds+0xf6ee9)
    #3 0x56500e097002 in main ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/out-of-bounds+0xa002)
    #4 0x7f9e21a46290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
    #5 0x56500e096719 in _start ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/out-of-bounds+0x9719)

Address 0x7ffe9808e5f0 is located in stack of thread T0 at offset 48 in frame
    #0 0x56500e096d5f in out_of_bounds::main::h86e0ef2cff62a67d $PWD/examples/out-of-bounds.rs:1

  This frame has 1 object(s):
    [32, 48) 'xs' <== Memory access at offset 48 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow $PWD/examples/out-of-bounds.rs:3 in out_of_bounds::main::h86e0ef2cff62a67d
Shadow bytes around the buggy address:
  0x100053009c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100053009c70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100053009c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100053009c90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100053009ca0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100053009cb0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3
  0x100053009cc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100053009cd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100053009ce0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100053009cf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100053009d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==821==ABORTING

Use after free

asan/examples/use-after-free.rs

fn main() {
    let xs = vec![0, 1, 2, 3];
    let y = xs.as_ptr();
    drop(xs);
    let z = unsafe { *y };
}
$ ( cd asan && \
    RUSTFLAGS="-Z sanitizer=address" cargo run --target x86_64-unknown-linux-gnu --example use-after-free )
     Running `target/x86_64-unknown-linux-gnu/debug/examples/use-after-free`
=================================================================
==8768==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200000efb0 at pc 0x55b0dfb2da24 bp 0x7ffccf297230 sp 0x7ffccf297228
READ of size 4 at 0x60200000efb0 thread T0
    #0 0x55b0dfb2da23 in use_after_free::main::hd24e5b31a91cd260 $PWD/examples/use-after-free.rs:5
    #1 0x55b0dfc22046 in __rust_maybe_catch_panic ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0x103046)
    #2 0x55b0dfc1a9f9 in std::rt::lang_start::h6954771f55df116b ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0xfb9f9)
    #3 0x55b0dfb2db12 in main ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0xeb12)
    #4 0x7fb186053290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
    #5 0x55b0dfb28869 in _start ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0x9869)

0x60200000efb0 is located 0 bytes inside of 16-byte region [0x60200000efb0,0x60200000efc0)
freed by thread T0 here:
    #0 0x55b0dfbe0290 in __interceptor_cfree.localalias.0 $RUST_SRC/src/compiler-rt/lib/asan/asan_malloc_linux.cc:54
    #1 0x55b0dfb2c05c in alloc::heap::deallocate::hfc4464969f6c2d6d $RUST_SRC/src/liballoc/heap.rs:113
    #2 0x55b0dfb2d584 in _$LT$alloc..raw_vec..RawVec$LT$T$GT$$u20$as$u20$core..ops..Drop$GT$::drop::h379e52d625f89e1f $RUST_SRC/src/liballoc/raw_vec.rs:551
    #3 0x55b0dfb2b780 in drop::h7608d0590516eb20 ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0xc780)
    #4 0x55b0dfb29988 in drop_contents::ha8e051e1000be907 ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0xa988)
    #5 0x55b0dfb2b7e6 in drop::ha8e051e1000be907 ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0xc7e6)
    #6 0x55b0dfb2ac38 in core::mem::drop::h1c3f8290e9a15dc0 $RUST_SRC/src/libcore/mem.rs:614
    #7 0x55b0dfb2d9e3 in use_after_free::main::hd24e5b31a91cd260 $PWD/examples/use-after-free.rs:4
    #8 0x55b0dfc22046 in __rust_maybe_catch_panic ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0x103046)

previously allocated by thread T0 here:
    #0 0x55b0dfbe0448 in malloc $RUST_SRC/src/compiler-rt/lib/asan/asan_malloc_linux.cc:64
    #1 0x55b0dfb2d0af in alloc::heap::allocate::hada3930d4dfed51a $RUST_SRC/src/liballoc/heap.rs:59
    #2 0x55b0dfb2c0b0 in alloc::heap::exchange_malloc::h1ae17faa3583b58c $RUST_SRC/src/liballoc/heap.rs:138
    #3 0x55b0dfb2d816 in use_after_free::main::hd24e5b31a91cd260 $PWD/examples/use-after-free.rs:2
    #4 0x55b0dfc22046 in __rust_maybe_catch_panic ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/use-after-free+0x103046)

SUMMARY: AddressSanitizer: heap-use-after-free $PWD/examples/use-after-free.rs:5 in use_after_free::main::hd24e5b31a91cd260
Shadow bytes around the buggy address:
  0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff9df0: fa fa fa fa fa fa[fd]fd fa fa 05 fa fa fa fd fa
  0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==8768==ABORTING

LeakSanitizer

This sanitizer can detect memory leaks.

Memory leak

lsan/examples/memory-leak.rs

use std::mem;

fn main() {
    let xs = vec![0, 1, 2, 3];
    mem::forget(xs);
}
$ ( cd lsan && \
    RUSTFLAGS="-Z sanitizer=leak" cargo run --target x86_64-unknown-linux-gnu --example memory-leak )
     Running `target/x86_64-unknown-linux-gnu/debug/examples/memory-leak`

=================================================================
==16341==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x56322c0acb1f in __interceptor_malloc $RUST_SRC/src/compiler-rt/lib/lsan/lsan_interceptors.cc:55
    #1 0x56322c0a7aaa in alloc::heap::exchange_malloc::h1ae17faa3583b58c $RUST_SRC/src/liballoc/heap.rs:138
    #2 0x56322c0a7afc in memory_leak::main::h0003a08cbe34b70c $PWD/examples/memory-leak.rs:4
    #3 0x56322c0df896 in __rust_maybe_catch_panic ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/memory-leak+0x3d896)

SUMMARY: LeakSanitizer: 16 byte(s) leaked in 1 allocation(s).

Rc cycle

lsan/examples/rc-cycle.rs

use std::cell::RefCell;
use std::rc::Rc;

#[derive(Clone)]
struct Cycle {
    cell: RefCell<Option<Rc<Cycle>>>,
}

impl Drop for Cycle {
    fn drop(&mut self) {
        println!("freed");
    }
}

fn main() {
    let cycle = Rc::new(Cycle { cell: RefCell::new(None)});
    *cycle.cell.borrow_mut() = Some(cycle.clone());
}
$ ( cd lsan && \
    RUSTFLAGS="-Z sanitizer=leak" cargo run --target x86_64-unknown-linux-gnu --example rc-cycle )
    Finished dev [optimized + debuginfo] target(s) in 0.0 secs
     Running `target/x86_64-unknown-linux-gnu/debug/examples/rc-cycle`

=================================================================
==16344==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x556812c577ca in __interceptor_malloc $RUST_SRC/src/compiler-rt/lib/lsan/lsan_interceptors.cc:55
    #1 0x556812c52c3a in alloc::heap::exchange_malloc::h55adee8e9fba9338 $RUST_SRC/src/liballoc/heap.rs:138
    #2 0x556812c5254e in _$LT$alloc..rc..Rc$LT$T$GT$$GT$::new::h63d403f2e66d1e71 $RUST_SRC/src/liballoc/rc.rs:293
    #3 0x556812c52d44 in rc_cycle::main::hee2857f96ac2db92 $PWD/examples/rc-cycle.rs:16
    #4 0x556812c8614a in __rust_maybe_catch_panic $RUST_SRC/src/libpanic_unwind/lib.rs:98
    #5 0x556812c7ed06 in std::panicking::try<(),fn()> $RUST_SRC/src/libstd/panicking.rs:436
    #6 0x556812c7ed06 in std::panic::catch_unwind<fn(),()> $RUST_SRC/src/libstd/panic.rs:361
    #7 0x556812c7ed06 in std::rt::lang_start::hb7fc7ec87b663023 $RUST_SRC/src/libstd/rt.rs:57
    #8 0x7f9a53e0f290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)

SUMMARY: LeakSanitizer: 32 byte(s) leaked in 1 allocation(s).

MemorySanitizer

This sanitizer can detect reads of uninitialized memory.

Uninitialized read

msan/examples/uninitialized-read.rs

use std::mem;

fn main() {
    let xs: [u8; 4] = unsafe { mem::uninitialized() };
    let y = xs[0] + xs[1];
}
$ ( cd msan && \
    RUSTFLAGS="-Z sanitizer=memory" cargo run --target x86_64-unknown-linux-gnu --example uninitialized-read )
     Running `target/x86_64-unknown-linux-gnu/debug/examples/uninitialized-read`
==21418==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x56107230e7da in uninitialized_read::main::h0c073cea3836efc1 $PWD/examples/uninitialized-read.rs:5
    #1 0x56107238b446 in __rust_maybe_catch_panic ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/uninitialized-read+0x87446)
    #2 0x561072383df9 in std::rt::lang_start::h6954771f55df116b ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/uninitialized-read+0x7fdf9)
    #3 0x56107230e8a9 in main ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/uninitialized-read+0xa8a9)
    #4 0x7f32de0b7290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
    #5 0x56107230e4f9 in _start ($PWD/target/x86_64-unknown-linux-gnu/debug/examples/uninitialized-read+0xa4f9)

SUMMARY: MemorySanitizer: use-of-uninitialized-value $PWD/examples/uninitialized-read.rs:5 in uninitialized_read::main::h0c073cea3836efc1
Exiting

ThreadSanitizer

This sanitizer can detect data races.

Data race

tsan/examples/data-race.rs

use std::thread;

static mut ANSWER: i32 = 0;

fn main() {
    let t1 = thread::spawn(|| unsafe { ANSWER = 42 });
    unsafe {
        ANSWER = 24;
    }
    t1.join().ok();
}
$ ( cd tsan && \
    RUSTFLAGS="-Z sanitizer=thread" cargo run --target x86_64-unknown-linux-gnu --example data-race )
     Running `target/x86_64-unknown-linux-gnu/debug/examples/data-race`
==================
WARNING: ThreadSanitizer: data race (pid=26481)
  Write of size 4 at 0x55662b8b2bb4 by thread T1:
    #0 data_race::main::_$u7b$$u7b$closure$u7d$$u7d$::hee96c0dbd110538f $PWD/examples/data-race.rs:6 (data-race+0x000000010e3f)
    #1 _$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce$LT$$LP$$RP$$GT$$GT$::call_once::h325b4408e33222b1 $RUST_SRC/src/libstd/panic.rs:296 (data-race+0x000000010cc5)
    #2 std::panicking::try::do_call::hce66d861a72cf7ad $RUST_SRC/src/libstd/panicking.rs:460 (data-race+0x00000000c942)
    #3 __rust_maybe_catch_panic <null> (data-race+0x0000000b4ee6)
    #4 std::panic::catch_unwind::h8bcbba7f3956edf8 $RUST_SRC/src/libstd/panic.rs:361 (data-race+0x00000000b567)
    #5 std::thread::Builder::spawn::_$u7b$$u7b$closure$u7d$$u7d$::h59119aee2f2d06bf $RUST_SRC/src/libstd/thread/mod.rs:357 (data-race+0x00000000c276)
    #6 _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::hd916ceba2ff03dbf $RUST_SRC/src/liballoc/boxed.rs:614 (data-race+0x00000000f2ce)
    #7 std::sys::imp::thread::Thread::new::thread_start::h6a0d1a011a706f06 <null> (data-race+0x0000000abdd0)

  Previous write of size 4 at 0x55662b8b2bb4 by main thread:
    #0 data_race::main::h14a8ec63b6689873 $PWD/examples/data-race.rs:8 (data-race+0x000000010d7c)
    #1 __rust_maybe_catch_panic <null> (data-race+0x0000000b4ee6)
    #2 __libc_start_main <null> (libc.so.6+0x000000020290)

  Location is global 'data_race::ANSWER::hcde8cae2a80d1e5d' of size 4 at 0x55662b8b2bb4 (data-race+0x0000002f8bb4)

  Thread T1 (tid=26574, running) created by main thread at:
    #0 pthread_create $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:902 (data-race+0x00000001aedb)
    #1 std::sys::imp::thread::Thread::new::h1a8b710ff34ac90e <null> (data-race+0x0000000aba3e)
    #2 std::thread::spawn::hef27947e8b208e27 $RUST_SRC/src/libstd/thread/mod.rs:412 (data-race+0x00000000b5fa)
    #3 data_race::main::h14a8ec63b6689873 $PWD/examples/data-race.rs:6 (data-race+0x000000010d5c)
    #4 __rust_maybe_catch_panic <null> (data-race+0x0000000b4ee6)
    #5 __libc_start_main <null> (libc.so.6+0x000000020290)

SUMMARY: ThreadSanitizer: data race $PWD/examples/data-race.rs:6 in data_race::main::_$u7b$$u7b$closure$u7d$$u7d$::hee96c0dbd110538f
==================
ThreadSanitizer: reported 1 warnings

Better backtraces

You can get even more complete backtraces if you recompile the std facade with -Z sanitizer. To do that, you can use Xargo:

# install Xargo and its dependency, the rust-src component
$ cargo install xargo

$ rustup component add rust-src

# add this file to the root of your Cargo project
$ edit Xargo.toml && cat $_
[dependencies.std]
features = ["panic-unwind", "asan", "lsan", "msan", "tsan"]

# if using `cargo test`
[dependencies.test]
stage = 1
# Xargo has to rebuild the sanitizer runtimes and that requires `llvm-config`
# (in a future Xargo version, this will not be necessary)
$ export LLVM_CONFIG=$(which llvm-config)

# then you can `xargo test` or `xargo run`
$ RUSTFLAGS="-Z sanitizer=address" xargo test --target x86_64-unknown-linux-gnu

To make the above command work, you'll likely have to modify your rust-src component, which should be in (rustc --print sysroot)/lib/rustlib/src/rust, like this:

diff --git a/src/libgetopts/Cargo.toml b/src/libgetopts/Cargo.toml
index 99e3b89285..07593229af 100644
--- a/src/libgetopts/Cargo.toml
+++ b/src/libgetopts/Cargo.toml
@@ -6,4 +6,4 @@ version = "0.0.0"
 [lib]
 name = "getopts"
 path = "lib.rs"
-crate-type = ["dylib", "rlib"]
+# crate-type = ["dylib", "rlib"]
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 8146e7fb1e..c013995255 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -7,7 +7,7 @@ build = "build.rs"
 [lib]
 name = "std"
 path = "lib.rs"
-crate-type = ["dylib", "rlib"]
+# crate-type = ["dylib", "rlib"]

 [dependencies]
 alloc = { path = "../liballoc" }
diff --git a/src/libterm/Cargo.toml b/src/libterm/Cargo.toml
index 8021e814c0..6891e0b912 100644
--- a/src/libterm/Cargo.toml
+++ b/src/libterm/Cargo.toml
@@ -6,4 +6,4 @@ version = "0.0.0"
 [lib]
 name = "term"
 path = "lib.rs"
-crate-type = ["dylib", "rlib"]
+# crate-type = ["dylib", "rlib"]
diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml
index ecbd5a9c0f..553150cdd1 100644
--- a/src/libtest/Cargo.toml
+++ b/src/libtest/Cargo.toml
@@ -6,7 +6,7 @@ version = "0.0.0"
 [lib]
 name = "test"
 path = "lib.rs"
-crate-type = ["dylib", "rlib"]
+# crate-type = ["dylib", "rlib"]

 [dependencies]
 getopts = { path = "../libgetopts" }

Caveats / known bugs

Unrealiable LeakSanitizer

I have found that LeakSanitizer not always catches memory leaks unless you have compiled your code with -C opt-level=1 or better. You can change the optimization level of the dev profile in your Cargo.toml like this:

# Cargo.toml
[profile.dev]
opt-level = 1

CARGO_INCREMENTAL

rust-lang/rust#39611

If you have set CARGO_INCREMENTAL=1 in your environment to use / test incremental compilation then you'll have to remove it as incremental compilation breaks sanitizer support.

MemorySanitizer: Use of uninitialized value in the test runner

rust-lang/rust#39610

This effectively means you can't really cargo test your crate with MemorySanitizer as you'll always get errors.

src/lib.rs

#[test]
fn foo() {}
$ RUSTFLAGS="-Z sanitizer=memory" cargo test --target x86_64-unknown-linux-gnu
     Running target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235
Uninitialized bytes in __interceptor_memchr at offset 13 inside [0x70400000ef60, 23)
==6915==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x55aec536a8b5 in std::ffi::c_str::CString::_new::h1600b539eb5d8b8c ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xc58b5)
    #1 0x55aec537399a in std::sys::imp::fs::stat::h72120555244bec39 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xce99a)
    #2 0x55aec5355b18 in std::fs::metadata::h4ae9b0fd118f3836 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xb0b18)
    #3 0x55aec535bea8 in term::terminfo::searcher::get_dbpath_for_term::hc53288f466988180 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xb6ea8)
    #4 0x55aec535b3f1 in term::terminfo::TermInfo::from_name::hb95f189f4c99eccf ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xb63f1)
    #5 0x55aec535b1a2 in term::terminfo::TermInfo::from_env::h45b8e5476a2a09d7 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xb61a2)
    #6 0x55aec5365c70 in term::stdout::h84d7912730b73cf4 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xc0c70)
    #7 0x55aec52d28bd in _$LT$test..ConsoleTestState$LT$T$GT$$GT$::new::h937954646ef1f1d9 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0x2d8bd)
    #8 0x55aec52d481a in test::run_tests_console::h7b41f829f623d5c0 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0x2f81a)
    #9 0x55aec52cfdb8 in test::test_main::hae140f91361b0544 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0x2adb8)
    #10 0x55aec52d06ce in test::test_main_static::h9b2aae5d6f64eac6 ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0x2b6ce)
    #11 0x55aec52be9a3 in test_runner::__test::main::h164d7dfa966cbb3f $PWD/src/lib.rs:1
    #12 0x55aec537d5d6 in __rust_maybe_catch_panic ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xd85d6)
    #13 0x55aec5376bc9 in std::rt::lang_start::h6954771f55df116b ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xd1bc9)
    #14 0x55aec52bea19 in main ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0x19a19)
    #15 0x7fc24cf2f290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
    #16 0x55aec52be839 in _start ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0x19839)

SUMMARY: MemorySanitizer: use-of-uninitialized-value ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/test_runner-d861d6557762b235+0xc58b5) in std::ffi::c_str::CString::_new::h1600b539eb5d8b8c
Exiting
error: test failed

ThreadSanitizer: Data race in the test runner

rust-lang/rust#39608

Using ThreadSanitizer to test any library crate with more that one unit test results in data race reports unrelated to the tests themselves.

src/lib.rs

#[test]
fn foo() {}

#[test]
fn bar() {}
$ RUSTFLAGS="-Z sanitizer=thread" cargo test --target x86_64-unknown-linux-gnu
     Running target/x86_64-unknown-linux-gnu/debug/deps/foo-aacd724200d968b7

running 2 tests
==================
WARNING: ThreadSanitizer: data race (pid=3733)
  Read of size 8 at 0x7c7800006f28 by main thread:
    #0 memcpy $RUST_SRC/src/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:598 (foo-aacd724200d968b7+0x000000056009)
    #1 memcpy $RUST_SRC/src/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:590 (foo-aacd724200d968b7+0x000000056009)
    #2 core::mem::swap<core::option::Option<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)>> $RUST_SRC/src/libcore/mem.rs:454 (foo-aacd724200d968b7+0x00000001adfe)
    #3 core::mem::replace<core::option::Option<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)>> $RUST_SRC/src/libcore/mem.rs:518 (foo-aacd724200d968b7+0x00000001adfe)
    #4 core::option::{{impl}}::take<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libcore/option.rs:725 (foo-aacd724200d968b7+0x00000001adfe)
    #5 _$LT$std..sync..mpsc..mpsc_queue..Queue$LT$T$GT$$GT$::pop::hd044437806ca7d86 $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:126 (foo-aacd724200d968b7+0x00000001adfe)
    #6 __rust_maybe_catch_panic $RUST_SRC/src/libpanic_unwind/lib.rs:98 (foo-aacd724200d968b7+0x0000000d8b0a)
    #7 __libc_start_main <null> (libc.so.6+0x000000020290)

  Previous write of size 8 at 0x7c7800006f28 by thread T1:
    #0 malloc $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:591 (foo-aacd724200d968b7+0x000000061e1f)
    #1 alloc::heap::allocate $RUST_SRC/src/liballoc/heap.rs:59 (foo-aacd724200d968b7+0x000000014bb2)
    #2 alloc::heap::exchange_malloc $RUST_SRC/src/liballoc/heap.rs:138 (foo-aacd724200d968b7+0x000000014bb2)
    #3 std::sync::mpsc::mpsc_queue::{{impl}}::new<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:80 (foo-aacd724200d968b7+0x000000014bb2)
    #4 std::sync::mpsc::mpsc_queue::{{impl}}::push<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:101 (foo-aacd724200d968b7+0x000000014bb2)
    #5 std::sync::mpsc::shared::{{impl}}::send<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/shared.rs:171 (foo-aacd724200d968b7+0x000000014bb2)
    #6 _$LT$std..sync..mpsc..Sender$LT$T$GT$$GT$::send::h1f83562f10dffde2 $RUST_SRC/src/libstd/sync/mpsc/mod.rs:607 (foo-aacd724200d968b7+0x000000014bb2)

  Location is heap block of size 224 at 0x7c7800006f20 allocated by thread T1:
    #0 malloc $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:591 (foo-aacd724200d968b7+0x000000061e1f)
    #1 alloc::heap::allocate $RUST_SRC/src/liballoc/heap.rs:59 (foo-aacd724200d968b7+0x000000014bb2)
    #2 alloc::heap::exchange_malloc $RUST_SRC/src/liballoc/heap.rs:138 (foo-aacd724200d968b7+0x000000014bb2)
    #3 std::sync::mpsc::mpsc_queue::{{impl}}::new<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:80 (foo-aacd724200d968b7+0x000000014bb2)
    #4 std::sync::mpsc::mpsc_queue::{{impl}}::push<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:101 (foo-aacd724200d968b7+0x000000014bb2)
    #5 std::sync::mpsc::shared::{{impl}}::send<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/shared.rs:171 (foo-aacd724200d968b7+0x000000014bb2)
    #6 _$LT$std..sync..mpsc..Sender$LT$T$GT$$GT$::send::h1f83562f10dffde2 $RUST_SRC/src/libstd/sync/mpsc/mod.rs:607 (foo-aacd724200d968b7+0x000000014bb2)

  Thread T1 'bar' (tid=3735, finished) created by main thread at:
    #0 pthread_create $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:902 (foo-aacd724200d968b7+0x00000003b9a7)
    #1 std::sys::imp::thread::Thread::new::h13e24a45e97a3e79 $RUST_SRC/src/libstd/sys/unix/thread.rs:72 (foo-aacd724200d968b7+0x0000000d0765)
    #2 __rust_maybe_catch_panic $RUST_SRC/src/libpanic_unwind/lib.rs:98 (foo-aacd724200d968b7+0x0000000d8b0a)
    #3 __libc_start_main <null> (libc.so.6+0x000000020290)

SUMMARY: ThreadSanitizer: data race $RUST_SRC/src/libcore/mem.rs:454 in core::mem::swap<core::option::Option<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)>>
==================
test bar ... ok
==================
WARNING: ThreadSanitizer: data race (pid=3733)
  Write of size 8 at 0x7c7800006f20 by main thread:
    #0 free $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:634 (foo-aacd724200d968b7+0x00000003cf06)
    #1 free $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:628 (foo-aacd724200d968b7+0x00000003cf06)
    #2 _$LT$std..sync..mpsc..mpsc_queue..Queue$LT$T$GT$$GT$::pop::hd044437806ca7d86 $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:127 (foo-aacd724200d968b7+0x00000001ae56)
    #3 __rust_maybe_catch_panic $RUST_SRC/src/libpanic_unwind/lib.rs:98 (foo-aacd724200d968b7+0x0000000d8b0a)
    #4 __libc_start_main <null> (libc.so.6+0x000000020290)

  Previous write of size 8 at 0x7c7800006f20 by thread T1:
    #0 malloc $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:591 (foo-aacd724200d968b7+0x000000061e1f)
    #1 alloc::heap::allocate $RUST_SRC/src/liballoc/heap.rs:59 (foo-aacd724200d968b7+0x000000014bb2)
    #2 alloc::heap::exchange_malloc $RUST_SRC/src/liballoc/heap.rs:138 (foo-aacd724200d968b7+0x000000014bb2)
    #3 std::sync::mpsc::mpsc_queue::{{impl}}::new<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:80 (foo-aacd724200d968b7+0x000000014bb2)
    #4 std::sync::mpsc::mpsc_queue::{{impl}}::push<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:101 (foo-aacd724200d968b7+0x000000014bb2)
    #5 std::sync::mpsc::shared::{{impl}}::send<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/shared.rs:171 (foo-aacd724200d968b7+0x000000014bb2)
    #6 _$LT$std..sync..mpsc..Sender$LT$T$GT$$GT$::send::h1f83562f10dffde2 $RUST_SRC/src/libstd/sync/mpsc/mod.rs:607 (foo-aacd724200d968b7+0x000000014bb2)

  Thread T1 'bar' (tid=3735, finished) created by main thread at:
    #0 pthread_create $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:902 (foo-aacd724200d968b7+0x00000003b9a7)
    #1 std::sys::imp::thread::Thread::new::h13e24a45e97a3e79 $RUST_SRC/src/libstd/sys/unix/thread.rs:72 (foo-aacd724200d968b7+0x0000000d0765)
    #2 __rust_maybe_catch_panic $RUST_SRC/src/libpanic_unwind/lib.rs:98 (foo-aacd724200d968b7+0x0000000d8b0a)
    #3 __libc_start_main <null> (libc.so.6+0x000000020290)

SUMMARY: ThreadSanitizer: data race $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:127 in _$LT$std..sync..mpsc..mpsc_queue..Queue$LT$T$GT$$GT$::pop::hd044437806ca7d86
==================
test foo ... ok
==================
WARNING: ThreadSanitizer: data race (pid=3733)
  Write of size 8 at 0x7c7800006e40 by main thread:
    #0 free $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:634 (foo-aacd724200d968b7+0x00000003cf06)
    #1 free $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:628 (foo-aacd724200d968b7+0x00000003cf06)
    #2 drop::hf0d57a221ac19123 <null> (foo-aacd724200d968b7+0x000000019fb1)
    #3 __rust_maybe_catch_panic $RUST_SRC/src/libpanic_unwind/lib.rs:98 (foo-aacd724200d968b7+0x0000000d8b0a)
    #4 __libc_start_main <null> (libc.so.6+0x000000020290)

  Previous write of size 8 at 0x7c7800006e40 by thread T2:
    #0 malloc $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:591 (foo-aacd724200d968b7+0x000000061e1f)
    #1 alloc::heap::allocate $RUST_SRC/src/liballoc/heap.rs:59 (foo-aacd724200d968b7+0x000000014bb2)
    #2 alloc::heap::exchange_malloc $RUST_SRC/src/liballoc/heap.rs:138 (foo-aacd724200d968b7+0x000000014bb2)
    #3 std::sync::mpsc::mpsc_queue::{{impl}}::new<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:80 (foo-aacd724200d968b7+0x000000014bb2)
    #4 std::sync::mpsc::mpsc_queue::{{impl}}::push<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/mpsc_queue.rs:101 (foo-aacd724200d968b7+0x000000014bb2)
    #5 std::sync::mpsc::shared::{{impl}}::send<(test::TestDesc, test::TestResult, collections::vec::Vec<u8>)> $RUST_SRC/src/libstd/sync/mpsc/shared.rs:171 (foo-aacd724200d968b7+0x000000014bb2)
    #6 _$LT$std..sync..mpsc..Sender$LT$T$GT$$GT$::send::h1f83562f10dffde2 $RUST_SRC/src/libstd/sync/mpsc/mod.rs:607 (foo-aacd724200d968b7+0x000000014bb2)

  Thread T2 'foo' (tid=3736, finished) created by main thread at:
    #0 pthread_create $RUST_SRC/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:902 (foo-aacd724200d968b7+0x00000003b9a7)
    #1 std::sys::imp::thread::Thread::new::h13e24a45e97a3e79 $RUST_SRC/src/libstd/sys/unix/thread.rs:72 (foo-aacd724200d968b7+0x0000000d0765)
    #2 __rust_maybe_catch_panic $RUST_SRC/src/libpanic_unwind/lib.rs:98 (foo-aacd724200d968b7+0x0000000d8b0a)
    #3 __libc_start_main <null> (libc.so.6+0x000000020290)

SUMMARY: ThreadSanitizer: data race ($PWD/target/x86_64-unknown-linux-gnu/debug/deps/foo-aacd724200d968b7+0x19fb1) in drop::hf0d57a221ac19123
==================

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured

ThreadSanitizer: reported 3 warnings
error: test failed

Workaround: export RUST_TEST_THREADS=1 to run your test suite sequentially.

Suppression of False Positives

There are some cases where the sanitizers will generate false positives, such as reporting data races in code that uses std::sync::atomic::fence, or unsafe pointer usage while relying on the ordering semantics of adjacent barriers. This can generate a ton of noise, as popular libraries like lazy_static can trigger this.

WARNING: ThreadSanitizer: data race (pid=30975)                                                                                      
  Read of size 8 at 0x55ddb40e5418 by thread T2:                                                                                                                         
    #0 _$LT$lazy_static..lazy..Lazy$LT$T$GT$$GT$::get::hb947a249eaade5b0 /home/t/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-0.2.8/src/lazy.rs:26 (stress+0x279323)
    #1 rayon_core::log::{{impl}}::deref::__stability /home/t/src/rsdb/<__lazy_static_internal macros>:20 (stress+0x2a8520)
    #2 _$LT$rayon_core..log..LOG_ENV$u20$as$u20$core..ops..deref..Deref$GT$::deref::h995f5b423216fc8c /home/t/src/rsdb/<__lazy_static_internal macros>:21 (stress+0x2a8520)                      
    #3 rayon_core::registry::WorkerThread::wait_until::h14e38df285736ca7 /home/t/src/rsdb/rayon/rayon-core/src/registry.rs:434 (stress+0x2a0ac1)
    #4 rayon_core::registry::WorkerThread::wait_until::h14e38df285736ca7 /home/t/src/rsdb/rayon/rayon-core/src/registry.rs:434 (stress+0x2a0ac1)                                                      
    #5 rayon_core::registry::main_loop::h120d26ee2b06f3e1 /home/t/src/rsdb/rayon/rayon-core/src/registry.rs:559 (stress+0x2a2ba3)
    #6 rayon_core::registry::Registry::new::_$u7b$$u7b$closure$u7d$$u7d$::h73e776a16b1aafcd /home/t/src/rsdb/rayon/rayon-core/src/registry.rs:145 (stress+0x2a87fa)
    #7 std::sys_common::backtrace::__rust_begin_short_backtrace::h70e0fa277eccaded /checkout/src/libstd/sys_common/backtrace.rs:136 (stress+0x274b63)
    #8 std::thread::Builder::spawn::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h73f1afe39e3f5d92 /checkout/src/libstd/thread/mod.rs:364 (stress+0x2772e9)
    #9 _$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$$LP$$RP$$GT$$GT$::call_once::h0fef211ea8e53025 /checkout/src/libstd/panic.rs:296 (stress+0x269582)
    #10 std::panicking::try::do_call::h0164d0443475d14d /checkout/src/libstd/panicking.rs:479 (stress+0x277ab3)                                      
    #11 __rust_maybe_catch_panic /checkout/src/libpanic_unwind/lib.rs:98 (stress+0x30999c)                                                                                
    #12 std::panic::catch_unwind::h0f7a13324f48e132 /checkout/src/libstd/panic.rs:361 (stress+0x2761bb)                                                                                       
    #13 std::thread::Builder::spawn::_$u7b$$u7b$closure$u7d$$u7d$::h8fabb47bf4134341 /checkout/src/libstd/thread/mod.rs:363 (stress+0x277091)                                                         
    #14 _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::h34535139aa115aa0 /checkout/src/liballoc/boxed.rs:652 (stress+0x29081f)
    #15 alloc::boxed::{{impl}}::call_once<(),()> /checkout/src/liballoc/boxed.rs:662 (stress+0x30169b)      
    #16 std::sys_common::thread::start_thread /checkout/src/libstd/sys_common/thread.rs:21 (stress+0x30169b)                                    
    #17 std::sys::imp::thread::Thread::new::thread_start::h3eac17b79d7b9487 /checkout/src/libstd/sys/unix/thread.rs:84 (stress+0x30169b)     
                                                                                                                                                                   
  Previous write of size 8 at 0x55ddb40e5418 by thread T1:                                                                                           
    #0 _$LT$lazy_static..lazy..Lazy$LT$T$GT$$GT$::get::_$u7b$$u7b$closure$u7d$$u7d$::he4e15a492cb08e5f /home/t/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-0.2.8/src/lazy.rs:23 (stress+0x27946f)
    #1 std::sync::once::Once::call_once::_$u7b$$u7b$closure$u7d$$u7d$::hecb03b941ecc49ae /checkout/src/libstd/sync/once.rs:227 (stress+0x2755f3)                                              
    #2 std::sync::once::Once::call_inner::h7a6867e4a5c8eee6 /checkout/src/libstd/sync/once.rs:307 (stress+0x2fbe2c)
    #3 _$LT$lazy_static..lazy..Lazy$LT$T$GT$$GT$::get::hb947a249eaade5b0 /home/t/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-0.2.8/src/lazy.rs:22 (stress+0x27930e)
    #4 rayon_core::log::{{impl}}::deref::__stability /home/t/src/rsdb/<__lazy_static_internal macros>:20 (stress+0x2a8520)
    #5 _$LT$rayon_core..log..LOG_ENV$u20$as$u20$core..ops..deref..Deref$GT$::deref::h995f5b423216fc8c /home/t/src/rsdb/<__lazy_static_internal macros>:21 (stress+0x2a8520)
    #6 rayon_core::registry::WorkerThread::wait_until::h14e38df285736ca7 /home/t/src/rsdb/rayon/rayon-core/src/registry.rs:434 (stress+0x2a0ac1)
    #7 rayon_core::registry::WorkerThread::wait_until::h14e38df285736ca7 /home/t/src/rsdb/rayon/rayon-core/src/registry.rs:434 (stress+0x2a0ac1)
    #8 rayon_core::registry::main_loop::h120d26ee2b06f3e1 /home/t/src/rsdb/rayon/rayon-core/src/registry.rs:559 (stress+0x2a2ba3)
    #9 rayon_core::registry::Registry::new::_$u7b$$u7b$closure$u7d$$u7d$::h73e776a16b1aafcd /home/t/src/rsdb/rayon/rayon-core/src/registry.rs:145 (stress+0x2a87fa)
    #10 std::sys_common::backtrace::__rust_begin_short_backtrace::h70e0fa277eccaded /checkout/src/libstd/sys_common/backtrace.rs:136 (stress+0x274b63)
    #11 std::thread::Builder::spawn::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h73f1afe39e3f5d92 /checkout/src/libstd/thread/mod.rs:364 (stress+0x2772e9)
    #12 _$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$$LP$$RP$$GT$$GT$::call_once::h0fef211ea8e53025 /checkout/src/libstd/panic.rs:296 (stress+0x269582)
    #13 std::panicking::try::do_call::h0164d0443475d14d /checkout/src/libstd/panicking.rs:479 (stress+0x277ab3)
    #14 __rust_maybe_catch_panic /checkout/src/libpanic_unwind/lib.rs:98 (stress+0x30999c)
    #15 std::panic::catch_unwind::h0f7a13324f48e132 /checkout/src/libstd/panic.rs:361 (stress+0x2761bb)
    #16 std::thread::Builder::spawn::_$u7b$$u7b$closure$u7d$$u7d$::h8fabb47bf4134341 /checkout/src/libstd/thread/mod.rs:363 (stress+0x277091)
    #17 _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::h34535139aa115aa0 /checkout/src/liballoc/boxed.rs:652 (stress+0x29081f)
    #18 alloc::boxed::{{impl}}::call_once<(),()> /checkout/src/liballoc/boxed.rs:662 (stress+0x30169b)
    #19 std::sys_common::thread::start_thread /checkout/src/libstd/sys_common/thread.rs:21 (stress+0x30169b)
    #20 std::sys::imp::thread::Thread::new::thread_start::h3eac17b79d7b9487 /checkout/src/libstd/sys/unix/thread.rs:84 (stress+0x30169b)

  Location is global '_$LT$rayon_core..log..LOG_ENV$u20$as$u20$core..ops..deref..Deref$GT$::deref::__stability::LAZY::h79a6f8f41963a1dd' of size 16 at 0x55ddb40e5418 (stress+0x0000013d5418)

These errors can be suppressed by setting the TSAN_OPTIONS environment variable, and providing a suppressions configuration file:

export TSAN_OPTIONS="suppressions=blacklist.txt"

Where the configuration file looks something like this:

# Library foobar is full of races.
# Filed bug 123, but do not want to deal with it now.
race:foobar

# The function turns to be racy. Bug 345.
race:NuclearRocket::Launch

# The race is introduced in patch 456. Bug 567.
race:src/surgery/laser_scalpel.cc

# Global var global_var is racy. Bug 568.
race:global_var

# short() function is racy, but not match any other functions containing "short". Bug 569.
race:^short$

# The following thread leaks. Bug 678.
thread:MonitoringThread

# Uninstrumented library.
called_from_lib:libzmq.so

You can find additional documentation for the LLVM suppression file here.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • No line numbers in backtrace

    No line numbers in backtrace

    Hi. When I use the address sanitizer with a rust project compiled in debug mode, I don't get the line numbers in the backtrace:

    ASAN:DEADLYSIGNAL
    =================================================================
    ==2468==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x55c30a73e6f1 bp 0x7ffe9349b380 sp 0x7ffe9349b360 T0)
    ==2468==The signal is caused by a WRITE memory access.
    ==2468==Hint: address points to the zero page.
        #0 0x55c30a73e6f0  (/tmp/san-test/target/debug/san-test+0x96f0)
        #1 0x55c30a73e698  (/tmp/san-test/target/debug/san-test+0x9698)
        #2 0x55c30a73ebd4  (/tmp/san-test/target/debug/san-test+0x9bd4)
        #3 0x55c30a83da87  (/tmp/san-test/target/debug/san-test+0x108a87)
        #4 0x55c30a84453e  (/tmp/san-test/target/debug/san-test+0x10f53e)
        #5 0x55c30a831363  (/tmp/san-test/target/debug/san-test+0xfc363)
        #6 0x55c30a73eb52  (/tmp/san-test/target/debug/san-test+0x9b52)
        #7 0x55c30a73e72d  (/tmp/san-test/target/debug/san-test+0x972d)
        #8 0x7f62b43edf49  (/usr/lib/libc.so.6+0x20f49)
        #9 0x55c30a73e5a9  (/tmp/san-test/target/debug/san-test+0x95a9)
    
    AddressSanitizer can not provide additional info.
    SUMMARY: AddressSanitizer: SEGV (/tmp/san-test/target/debug/san-test+0x96f0) 
    ==2468==ABORTING
    

    What am I doing wrong? I use this version of Rust:

    rustc 1.25.0-nightly (90eb44a58 2018-01-29)
    

    Thanks.

    opened by antoyo 6
  • Any way to make ASAN work on macOS?

    Any way to make ASAN work on macOS?

    According to https://clang.llvm.org/docs/AddressSanitizer.html ASAN works on macOS and I've successfully tried it with C. It doesn't work with Rust though. Is there any way to make it work? What'd need to be done to port it?

    opened by Kixunil 3
  • Example of leak sanitizer shows no debug information (so did applying sanitizer in my own project)

    Example of leak sanitizer shows no debug information (so did applying sanitizer in my own project)

    What I ran and what I got:

    @bruno:lsan% RUSTFLAGS='-Z sanitizer=leak' cargo run --example rc-cycle --target x86_64-unknown-linux-gnu
       Compiling lsan v0.1.0 (file:///home/bruno/prog/rust/rust-san/lsan)                                                                                                    
        Finished dev [optimized + debuginfo] target(s) in 0.58s
         Running `target/x86_64-unknown-linux-gnu/debug/examples/rc-cycle`
    
    =================================================================
    ==29114==ERROR: LeakSanitizer: detected memory leaks
    
    Direct leak of 32 byte(s) in 1 object(s) allocated from:
        #0 0x55669bd75236  (/home/bruno/prog/rust/rust-san/lsan/target/x86_64-unknown-linux-gnu/debug/examples/rc-cycle+0xa236)
        #1 0x55669bd70fc5  (/home/bruno/prog/rust/rust-san/lsan/target/x86_64-unknown-linux-gnu/debug/examples/rc-cycle+0x5fc5)
    
    SUMMARY: LeakSanitizer: 32 byte(s) leaked in 1 allocation(s).
    

    Rust version:

    @bruno:lsan% rustc --version
    rustc 1.30.0-nightly (9395f0af7 2018-09-02)
    
    opened by brunoczim 2
  • serde: Only executables and rlibs can be compiled with `-Z sanitizer`

    serde: Only executables and rlibs can be compiled with `-Z sanitizer`

    I'm not able to use the sanitizer with one of my program since it uses serde and serde_derive won't build using -Z sanitizer. I'm able to reproduce with:

    #[macro_use]
    extern crate serde_derive;
    
    extern crate serde_json;
    
    #[derive(Serialize, Deserialize, Debug)]
    struct Point {
        x: i32,
        y: i32,
    }
    
    fn main() {
        let point = Point { x: 1, y: 2 };
    
        // Convert the Point to a JSON string.
        let serialized = serde_json::to_string(&point).unwrap();
    
        // Prints serialized = {"x":1,"y":2}
        println!("serialized = {}", serialized);
    
        // Convert the JSON string back to a Point.
        let deserialized: Point = serde_json::from_str(&serialized).unwrap();
    
        // Prints deserialized = Point { x: 1, y: 2 }
        println!("deserialized = {:?}", deserialized);
    }
    

    rustc 1.17.0-nightly (0e7727795 2017-02-19)

    $ RUSTFLAGS="-Z sanitizer=thread" cargo run
       Compiling dtoa v0.4.1
       Compiling itoa v0.3.1
       Compiling quote v0.3.13
       Compiling unicode-xid v0.0.4
       Compiling serde v0.9.7
       Compiling num-traits v0.1.36
       Compiling synom v0.11.0
       Compiling syn v0.11.6
       Compiling serde_json v0.9.7
       Compiling serde_codegen_internals v0.13.0
       Compiling serde_derive v0.9.7
    error: Only executables and rlibs can be compiled with `-Z sanitizer`
    
    error: aborting due to previous error
    
    error: Could not compile `serde_derive`.
    
    opened by bbigras 2
  • staticlibs cannot be compiled -Z sanitize

    staticlibs cannot be compiled -Z sanitize

    I'm trying to fuzz a C API backed by a Rust implementation. The Rust coded exposes the API over FFI and is compiled as a staticlib, but this makes it not compatible with -Z sanitize.

    Can this be fixed?

    opened by metajack 0
  • How to get sanitize process not running using

    How to get sanitize process not running using "cargo run"?

    I'm building my library with the following command: RUSTFLAGS="-Z sanitizer=address" cargo build --examples --target x86_64-unknown-linux-gnu

    The result is an x.so file which is loaded by another application, how can I get the sanitizer report?

    opened by gkorland 0
  • Asan doesn't report invalid write

    Asan doesn't report invalid write

    I have a test that perform an invalid write inside unsafe code. However, this program just crashes with a segfault when asan is enabled. No backtrace, or error message besides "Segmentation Fault" is output, and GDB crashes instead of breaking on the error. The only way I was able to get a valid backtrace was with valgrind.

    In my experience with asan for C++, this error would definitely have been caught. Is this a bug in the Rust asan integration? I am happy to help gather more debug information about what is happening here.

    Valgrind trace:

    jeremysalwen@jeremysalwen-glaptop:~/fun/extended-collections-rs$ valgrind /home/jeremysalwen/fun/extended-collections-rs/target/debug/deps/extended_collections-4040d7db4dc997da --test skiplist::tsplist --test-threads=1
    ==169673== Memcheck, a memory error detector
    ==169673== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==169673== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==169673== Command: /home/jeremysalwen/fun/extended-collections-rs/target/debug/deps/extended_collections-4040d7db4dc997da --test skiplist::tsplist --test-threads=1
    ==169673== 
    
    running 13 tests
    test skiplist::tsplist::tests::test_add ... ==169673== Invalid write of size 8
    ==169673==    at 0x1F0C05: extended_collections::skiplist::tsplist::link (tsplist.rs:76)
    ==169673==    by 0x1F1D1E: <extended_collections::skiplist::tsplist::TspList<T, A>>::insert (tsplist.rs:199)
    ==169673==    by 0x274CD2: extended_collections::skiplist::tsplist::tests::test_add (tsplist.rs:853)
    ==169673==    by 0x225649: extended_collections::skiplist::tsplist::tests::test_add::{{closure}} (tsplist.rs:851)
    ==169673==    by 0x1635CD: core::ops::function::FnOnce::call_once (function.rs:231)
    ==169673==    by 0x3347BE: {{closure}} (lib.rs:1473)
    ==169673==    by 0x3347BE: call_once<closure,()> (function.rs:231)
    ==169673==    by 0x3347BE: <F as alloc::boxed::FnBox<A>>::call_box (boxed.rs:724)
    ==169673==    by 0x390AD9: __rust_maybe_catch_panic (lib.rs:92)
    ==169673==    by 0x351E37: try<(),std::panic::AssertUnwindSafe<alloc::boxed::Box<FnBox<()>>>> (panicking.rs:276)
    ==169673==    by 0x351E37: catch_unwind<std::panic::AssertUnwindSafe<alloc::boxed::Box<FnBox<()>>>,()> (panic.rs:388)
    ==169673==    by 0x351E37: test::run_test::run_test_inner::{{closure}} (lib.rs:1428)
    ==169673==    by 0x35175C: test::run_test::run_test_inner (lib.rs:1450)
    ==169673==    by 0x34FEDB: test::run_test (lib.rs:1469)
    ==169673==    by 0x3489CC: run_tests<closure> (lib.rs:1149)
    ==169673==    by 0x3489CC: test::run_tests_console (lib.rs:956)
    ==169673==    by 0x3404A3: test::test_main (lib.rs:289)
    ==169673==  Address 0x20 is not stack'd, malloc'd or (recently) free'd
    ==169673== 
    ==169673== 
    ==169673== Process terminating with default action of signal 11 (SIGSEGV)
    ==169673==  Access not within mapped region at address 0x20
    ==169673==    at 0x1F0C05: extended_collections::skiplist::tsplist::link (tsplist.rs:76)
    ==169673==    by 0x1F1D1E: <extended_collections::skiplist::tsplist::TspList<T, A>>::insert (tsplist.rs:199)
    ==169673==    by 0x274CD2: extended_collections::skiplist::tsplist::tests::test_add (tsplist.rs:853)
    ==169673==    by 0x225649: extended_collections::skiplist::tsplist::tests::test_add::{{closure}} (tsplist.rs:851)
    ==169673==    by 0x1635CD: core::ops::function::FnOnce::call_once (function.rs:231)
    ==169673==    by 0x3347BE: {{closure}} (lib.rs:1473)
    ==169673==    by 0x3347BE: call_once<closure,()> (function.rs:231)
    ==169673==    by 0x3347BE: <F as alloc::boxed::FnBox<A>>::call_box (boxed.rs:724)
    ==169673==    by 0x390AD9: __rust_maybe_catch_panic (lib.rs:92)
    ==169673==    by 0x351E37: try<(),std::panic::AssertUnwindSafe<alloc::boxed::Box<FnBox<()>>>> (panicking.rs:276)
    ==169673==    by 0x351E37: catch_unwind<std::panic::AssertUnwindSafe<alloc::boxed::Box<FnBox<()>>>,()> (panic.rs:388)
    ==169673==    by 0x351E37: test::run_test::run_test_inner::{{closure}} (lib.rs:1428)
    ==169673==    by 0x35175C: test::run_test::run_test_inner (lib.rs:1450)
    ==169673==    by 0x34FEDB: test::run_test (lib.rs:1469)
    ==169673==    by 0x3489CC: run_tests<closure> (lib.rs:1149)
    ==169673==    by 0x3489CC: test::run_tests_console (lib.rs:956)
    ==169673==    by 0x3404A3: test::test_main (lib.rs:289)
    ==169673==  If you believe this happened as a result of a stack
    ==169673==  overflow in your program's main thread (unlikely but
    ==169673==  possible), you can try to increase the size of the
    ==169673==  main thread stack using the --main-stacksize= flag.
    ==169673==  The main thread stack size used in this run was 8388608.
    ==169673== 
    ==169673== HEAP SUMMARY:
    ==169673==     in use at exit: 25,083 bytes in 395 blocks
    ==169673==   total heap usage: 594 allocs, 199 frees, 90,729 bytes allocated
    ==169673== 
    ==169673== LEAK SUMMARY:
    ==169673==    definitely lost: 0 bytes in 0 blocks
    ==169673==    indirectly lost: 0 bytes in 0 blocks
    ==169673==      possibly lost: 0 bytes in 0 blocks
    ==169673==    still reachable: 25,083 bytes in 395 blocks
    ==169673==         suppressed: 0 bytes in 0 blocks
    ==169673== Rerun with --leak-check=full to see details of leaked memory
    ==169673== 
    ==169673== For counts of detected and suppressed errors, rerun with: -v
    ==169673== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)
    Segmentation fault
    
    opened by jeremysalwen 0
  •  asan sample code is not working

    asan sample code is not working

    Problem

    I tried to run asan following README, but an error was outputted.

    error: could not exec the linker cc.

    Could you tell me how to deal with the problem?

    Environment

    • Ubuntu 16.04
    • rustc 1.32.0-nightly (ca79ecd69 2018-11-11)
    opened by kenta7777 0
  • LeakSanitizer has encountered a fatal error.

    LeakSanitizer has encountered a fatal error.

    We're seeing this error on the completion of cargo test on Linux. It seems to happen for every project, but only on Linux and not OSX. We've seen this same error in CI and docker so far.

    ==9196==LeakSanitizer has encountered a fatal error.
    ==9196==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
    ==9196==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
    

    https://travis-ci.org/maidsafe/parsec/jobs/415533268#L885

    opened by mrcnski 1
Owner
Jorge Aparicio
@ferrous-systems engineer. @rust-embedded WG core member. He|they
Jorge Aparicio
🐇 Fuzzing Rust code with American Fuzzy Lop

afl.rs Fuzzing Rust code with AFLplusplus What is it? Fuzz testing is a software testing technique used to find security and stability issues by provi

Rust Fuzzing Authority 1.3k Jan 5, 2023
Code for comparing CDN speeds!

How to run speed test. the image to use The image you should probably use is: cf_219kb.png cf_219kb.png is an image that won't be compressed by Jetpac

Speed Test Demon 26 Nov 10, 2022
Travis CI and AppVeyor template to test your Rust crate on 5 architectures and publish binary releases of it for Linux, macOS and Windows

trust Travis CI and AppVeyor template to test your Rust crate on 5 architectures and publish binary releases of it for Linux, macOS and Windows Featur

Jorge Aparicio 1.2k Dec 30, 2022
Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...

LibAFL, the fuzzer library. Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust. LibAFL is written and main

Advanced Fuzzing League ++ 1.2k Dec 29, 2022
TestDrive automatically scrapes input/output data from BOJ(Baekjoon Online Judge) and runs tests for your executable binary file!

?? TestDrive What does it do? TestDrive automatically scrapes input/output data from BOJ(Baekjoon Online Judge) and runs tests for your executable bin

Hyeonseok Jung 3 Mar 5, 2022
Handle some lichess.org/tournament load with Rust, while learning Rust

lila-http Take some of the HTTP load away from lila. WIP! Arena tournaments Clients connected to a tournament page request new data about the tourname

Lichess 22 Jan 2, 2023
HTTP mocking library for Rust.

httpmock HTTP mocking library for Rust. Documentation · Crate · Report Bug · Request Feature · Changelog Features Simple, expressive, fluent API. Many

Alexander Liesenfeld 320 Dec 21, 2022
Testing Framework for Rust

Polish Polish is Test-Driven Development done right Getting Started Installing the Package The crates.io package is kept up-to-date with all the major

Fadi Hanna Al-Kass 49 Dec 18, 2022
A library for generating fake data in Rust.

Fake A Rust library for generating fake data. Installation Default (rand is required): [dependencies] fake = "2.4" rand = "0.8" If you want to use #[d

cksac 552 Dec 25, 2022
Benchmarks for rust serialization frameworks

Rust serialization benchmark The goal of these benchmarks is to provide thorough and complete benchmarks for various rust serialization frameworks. Th

David Koloski 187 Jan 4, 2023
Playwright is a rust library to automate Chromium, Firefox and WebKit built on top of Node.js library.

?? Playwright for Rust Playwright is a rust library to automate Chromium, Firefox and WebKit built on top of Node.js library. Installation [dependenci

octaltree 132 Jan 6, 2023
ArchTest is a rule based architecture testing tool for rust

ArchTest is a rule based architecture testing tool. It applies static analyses on the specified rust project to extract use relationships.

Tom Dymel 7 Sep 26, 2021
Structure-aware, in-process, coverage-guided, evolutionary fuzzing engine for Rust functions.

fuzzcheck Fuzzcheck is a structure-aware, in-process, coverage-guided, evolutionary fuzzing engine for Rust functions. Given a function test: (T) -> b

Loïc Lecrenier 394 Dec 20, 2022
A fuzzer framework built in Rust

lain This crate provides functionality one may find useful while developing a fuzzer. A recent nightly Rust build is required for the specialization f

Microsoft 469 Dec 9, 2022
A fast Rust-based safe and thead-friendly grammar-based fuzz generator

Intro fzero is a grammar-based fuzzer that generates a Rust application inspired by the paper "Building Fast Fuzzers" by Rahul Gopinath and Andreas Ze

null 203 Nov 9, 2022
Automated property based testing for Rust (with shrinking).

quickcheck QuickCheck is a way to do property based testing using randomly generated input. This crate comes with the ability to randomly generate and

Andrew Gallant 2k Jan 2, 2023
Hypothesis-like property testing for Rust

Proptest Introduction Proptest is a property testing framework (i.e., the QuickCheck family) inspired by the Hypothesis framework for Python. It allow

Jason Lingle 1.1k Jan 1, 2023
QuickCheck bug hunting in Rust standard library data structures

BugHunt, Rust This project is aiming to provide "stateful" QuickCheck models for Rust's standard library. That is, we build up a random list of operat

Brian L. Troutwine 161 Dec 15, 2022
Simple goldenfile testing in Rust.

?? Rust Goldenfile Simple goldenfile testing in Rust. Goldenfile tests generate one or more output files as they run. At the end of the test, the gene

Calder Coalson 24 Nov 26, 2022