Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lazy_static triggers AddressSanitizer errors #87

Open
dwrensha opened this issue Mar 19, 2017 · 11 comments
Open

lazy_static triggers AddressSanitizer errors #87

dwrensha opened this issue Mar 19, 2017 · 11 comments
Labels

Comments

@dwrensha
Copy link

In BurntSushi/rust-snappy#5, it looks like the error is coming from Lazy::get().

This possibly has the same root cause as #81, but I don't know enough about how lazy_static works to be able to say for sure.

@dwrensha
Copy link
Author

# Cargo.toml
[package]
name = "lazy_static_asan"
version = "0.0.0"

[dependencies]
lazy_static = "0.2.4"
libfuzzer-sys = {git = "https://github.com/rust-fuzz/libfuzzer-sys.git"}

[[bin]]
name = "read_lazy_static"
path = "read_lazy_static.rs"
// read_lazy_static.rs

#![no_main]

#[macro_use]
extern crate libfuzzer_sys;

#[macro_use]
extern crate lazy_static;

lazy_static! {
    static ref FOO: usize = 100;
}

fuzz_target!(|_data| {
    *FOO;
});
$ RUSTFLAGS=" -Cpasses=sancov -C llvm-args=-sanitizer-coverage-level=3 -Z sanitizer=address" ASAN_OPTIONS=detect_odr_violation=0 cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/read_lazy_static`
INFO: Seed: 2346919122
INFO: Loaded 0 modules (0 guards): 
INFO: -max_len is not provided, using 64
INFO: A corpus is not provided, starting from an empty corpus
#0      READ units: 1
=================================================================
==29177==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd05da7e48 at pc 0x562a48d2c797 bp 0x7ffd05da7e10 sp 0x7ffd05da7e08
ACCESS of size 0 at 0x7ffd05da7e48 thread T0
    #0 0x562a48d2c796 in lazy_static::lazy::{{impl}}::get<usize,fn() -> usize> /home/dwrensha/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-0.2.4/src/lazy.rs:15
    #1 0x562a48d2c796 in read_lazy_static::{{impl}}::deref::__stability /home/dwrensha/Desktop/test-standalone-lazy-static/<__lazy_static_internal macros>:21
    #2 0x562a48d2c796 in _$LT$read_lazy_static..FOO$u20$as$u20$core..ops..Deref$GT$::deref::hef6f026c6ae9fad2 /home/dwrensha/Desktop/test-standalone-lazy-static/<__lazy_static_internal macros>:22
    #3 0x562a48d2cc11 in rust_fuzzer_test_input /home/dwrensha/Desktop/test-standalone-lazy-static/read_lazy_static.rs:16
    #4 0x562a48d5554a in libfuzzer_sys::test_input_wrap::_$u7b$$u7b$closure$u7d$$u7d$::h01afe675cf6a0c88 /home/dwrensha/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/src/lib.rs:13
    #5 0x562a48d534bf in std::panicking::try::do_call::hfeac5113da58e53b /checkout/src/libstd/panicking.rs:454
    #6 0x562a48d7aa3a in __rust_maybe_catch_panic /checkout/src/libpanic_unwind/lib.rs:98
    #7 0x562a48d52b4b in std::panicking::try::h6164876e479a9388 /checkout/src/libstd/panicking.rs:433
    #8 0x562a48d525ec in std::panic::catch_unwind::h696c6b58c620fbac /checkout/src/libstd/panic.rs:361
    #9 0x562a48d5500b in LLVMFuzzerTestOneInput /home/dwrensha/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/src/lib.rs:11
    #10 0x562a48d4af44 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/dwrensha/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/llvm/lib/Fuzzer/FuzzerLoop.cpp:550
    #11 0x562a48d4a942 in fuzzer::Fuzzer::ShuffleAndMinimize(std::vector<std::vector<unsigned char, std::allocator<unsigned char> >, std::allocator<std::vector<unsigned char, std::allocator<unsigned char> > > >*) /home/dwrensha/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/llvm/lib/Fuzzer/FuzzerLoop.cpp:477
    #12 0x562a48d3138b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/dwrensha/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/llvm/lib/Fuzzer/FuzzerDriver.cpp:565
    #13 0x562a48d2cfae in main /home/dwrensha/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/llvm/lib/Fuzzer/FuzzerMain.cpp:20
    #14 0x7fcaba6ba400 in __libc_start_main (/lib64/libc.so.6+0x20400)
    #15 0x562a48d28e19 in _start (/home/dwrensha/Desktop/test-standalone-lazy-static/target/debug/read_lazy_static+0xee19)

Address 0x7ffd05da7e48 is located in stack of thread T0 at offset 40 in frame
    #0 0x562a48d2a7df in _$LT$lazy_static..lazy..Lazy$LT$T$GT$$GT$::get::hddf7c5d5397fb854 /home/dwrensha/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-0.2.4/src/lazy.rs:10

  This frame has 3 object(s):
    [32, 40) 'arg' <== Memory access at offset 40 is inside this variable
    [64, 72) '_8'
    [96, 104) 'r'
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 /home/dwrensha/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-0.2.4/src/lazy.rs:15 in lazy_static::lazy::{{impl}}::get<usize,fn() -> usize>
Shadow bytes around the buggy address:
  0x100020bacf70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020bacf80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020bacf90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020bacfa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020bacfb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100020bacfc0: 00 00 00 00 f1 f1 f1 f1 00[f2]f2 f2 00 f2 f2 f2
  0x100020bacfd0: 00 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020bacfe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020bacff0: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
  0x100020bad000: 00 00 f2 f2 00 00 f3 f3 00 00 00 00 00 00 00 00
  0x100020bad010: 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
==29177==ABORTING
MS: 0 ; base unit: 0000000000000000000000000000000000000000


artifact_prefix='./'; Test unit written to ./crash-da39a3ee5e6b4b0d3255bfef95601890afd80709
Base64: 

@shepmaster
Copy link

@Manishearth has anyone reported the zero-sized issue upstream to LLVM?

@nagisa
Copy link
Member

nagisa commented Apr 29, 2017

We would need a minimized test case in form of LLVM-IR or C if we want to report it upstream.

@shepmaster
Copy link

in form of LLVM-IR

I'm mildly comfortable with LLVM IR; but always in very constrained environments like microcontrollers. Any suggestions on how to take a piece of IR and and run it through ASan?

@shepmaster
Copy link

Interestingly, running the fuzzer with optimizations on (cargo fuzz run --release fuzzer_script_1) appears to avoid the first few cases of this that I've run into (presumably the zero-sized loads disappear)

@nagisa
Copy link
Member

nagisa commented Apr 30, 2017

No idea, sorry. I guess you’d start by finding a minimal rust program which results in the issue when fuzzed/sanitised. Taking LLVM-IR of that and running it through opt and/or llc with instrumentation pass enabled would produce instrumented LLVM-IR/object file which then could be used to reproduce the issue.

@shepmaster
Copy link

a minimal rust program which results in the issue when fuzzed/sanitised

Minimal is the tricky part. I can get the IR corresponding to the example here compiled with via the fuzzer options (so it's pre-instrumented), but that wants to link against the Rust standard library (and the fuzzer dylib). As-is, that's ~300k of LLVM IR, which isn't really minimal.

@emberian
Copy link

emberian commented May 2, 2017

@shepmaster maybe you can use bugpoint?

@emberian
Copy link

emberian commented May 2, 2017

FWIW, in my program that just hit this, running fuzzing the --release build indeed avoids the problem.

@shepmaster
Copy link

@cmr perhaps! I've only used bugpoint to debug issues earlier in the LLVM pipeline (transforming LLVM IR to machine code) so that having an actual runnable program was never a concern :-)

The other issue is that I'm guessing part of the error occurs due to code in the standard library (lazy_static uses atomics and InitOnce, IIRC), which is unlikely to show up in the resulting IR. All that said, it's worth a try.

Any idea if the LLVM folk would accept a testcase that is "please link against Rust's stdlib"?

@whitequark
Copy link
Member

Any idea if the LLVM folk would accept a testcase that is "please link against Rust's stdlib"?

Unlikely.

@whitequark whitequark added the bug label Oct 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants