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
A cryptographically verifiable code review system for the cargo (Rust) package manager.

image credit cargo-crev A cryptographically verifiable code review system for the cargo (Rust) package manager. Introduction Crev is a language and ec

crev - Code REView system 1.8k Jan 5, 2023
Secure sandboxing system for untrusted code execution

Godbox Secure sandboxing system for untrusted code execution. It uses isolate which uses specific functionnalities of the Linux kernel, thus godbox no

Nathanael Demacon 19 Dec 14, 2022
Using fibers to run in-memory code in a different and stealthy way.

Description A fiber is a unit of execution that must be manually scheduled by the application rather than rely on the priority-based scheduling mechan

Kurosh Dabbagh Escalante 121 Apr 20, 2023
A library for building tools to determine if vulnerabilities are reachable in a code base.

Overview Vuln Reach is a library for developing tools that determine if a given vulnerability is reachable. Provided to the open source community by P

Phylum 3 May 5, 2023
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 Jan 6, 2023
A simple menu to keep all your most used one-liners and scripts in one place

Dama Desktop Agnostic Menu Aggregate This program aims to be a hackable, easy to use menu that can be paired to lightweight window managers in order t

null 47 Jul 23, 2022
spy on the DNS queries your computer is making

dnspeep dnspeep lets you spy on the DNS queries your computer is making. Here's some example output: $ sudo dnspeep query name

Julia Evans 1.2k Dec 29, 2022
Checks your files for existence of Unicode BIDI characters which can be misused for supply chain attacks. See CVE-2021-42574

BIDI Character Detector This tool checks your files for existence of Unicode BIDI characters which can be misused for supply chain attacks to mitigate

null 5 Aug 26, 2022
ripgrep recursively searches directories for a regex pattern while respecting your gitignore

ripgrep (rg) ripgrep is a line-oriented search tool that recursively searches the current directory for a regex pattern. By default, ripgrep will resp

Andrew Gallant 35k Dec 31, 2022
A tiny program that locates and extracts public save files from Windows to your local directory!

Save Game Extractor | Download Save Game Extractor is a tool that automatically locates and copies save files for Windows games in public directories.

popcar2 6 Dec 23, 2021
Cover your tracks during Linux Exploitation by leaving zero traces on system logs and filesystem timestamps. 👻🐚

moonwalk Cover your tracks during Linux Exploitation / Penetration Testing by leaving zero traces on system logs and filesystem timestamps. ?? Table o

Mufeed VH 1.1k Jan 6, 2023
Adds zero-cost stack overflow protection to your embedded programs

flip-link adds zero-cost stack overflow protection to your embedded programs The problem Bare metal Rust programs may not be memory safe in presence o

Knurling 151 Dec 29, 2022
Cyg will help you to secure files in your repository directly using PGP encryption

cyg: Secure files in your repository Cyg will help you to secure files in your repository directly using PGP encryption. The name "cyg" was inspired b

Hisam Fahri 2 Aug 31, 2022
Detects usage of unsafe Rust in a Rust crate and its dependencies.

cargo-geiger ☢️ Looking for maintainer: https://github.com/rust-secure-code/cargo-geiger/issues/210 A program that lists statistics related to the usa

Rust Secure Code Working Group 1.1k Jan 4, 2023
An esoteric language/compiler written with Rust and Rust LLVM bindings

MeidoLang (メイドラング) A not so useful and esoteric language. The goal of this project was to contain some quirky or novel syntax in a stack-style program

null 0 Dec 24, 2021
Rust-verification-tools - RVT is a collection of tools/libraries to support both static and dynamic verification of Rust programs.

Rust verification tools This is a collection of tools/libraries to support both static and dynamic verification of Rust programs. We see static verifi

null 253 Dec 31, 2022
Rust bindings for libinjection

libinjection-rs Rust bindings for libinjection. How to use Add libinjection to dependencies of Cargo.toml: libinjection = "0.2" Import crate: extern c

ArvanCloud 35 Sep 24, 2022
A simple password manager written in Rust

ripasso A simple password manager written in Rust. The root crate ripasso is a library for accessing and decrypting passwords stored in pass format (G

Joakim Lundborg 548 Dec 26, 2022
tcp connection hijacker, rust rewrite of shijack

rshijack tcp connection hijacker, rust rewrite of shijack from 2001. This was written for TAMUctf 2018, brick house 100. The target was a telnet serve

null 377 Jan 1, 2023