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

Add support for dylibs with Address Sanitizer #42711

Merged
merged 1 commit into from
Jul 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,21 +856,48 @@ impl<'a> CrateLoader<'a> {
return
}

if !self.sess.crate_types.borrow().iter().all(|ct| {
match *ct {
// Link the runtime
config::CrateTypeExecutable => true,
// This crate will be compiled with the required
// instrumentation pass
config::CrateTypeRlib => false,
_ => {
self.sess.err(&format!("Only executables and rlibs can be \
compiled with `-Z sanitizer`"));
false
// firstyear 2017 - during testing I was unable to access an OSX machine
// to make this work on different crate types. As a result, today I have
// only been able to test and support linux as a target.
if self.sess.target.target.llvm_target == "x86_64-unknown-linux-gnu" {
if !self.sess.crate_types.borrow().iter().all(|ct| {
match *ct {
// Link the runtime
config::CrateTypeStaticlib |
config::CrateTypeExecutable => true,
// This crate will be compiled with the required
// instrumentation pass
config::CrateTypeRlib |
config::CrateTypeDylib |
config::CrateTypeCdylib =>
false,
_ => {
self.sess.err(&format!("Only executables, staticlibs, \
cdylibs, dylibs and rlibs can be compiled with \
`-Z sanitizer`"));
false
}
}
}) {
return
}
} else {
if !self.sess.crate_types.borrow().iter().all(|ct| {
match *ct {
// Link the runtime
config::CrateTypeExecutable => true,
// This crate will be compiled with the required
// instrumentation pass
config::CrateTypeRlib => false,
_ => {
self.sess.err(&format!("Only executables and rlibs can be \
compiled with `-Z sanitizer`"));
false
}
}
}) {
return
}
}) {
return
}

let mut uses_std = false;
Expand All @@ -890,7 +917,7 @@ impl<'a> CrateLoader<'a> {
info!("loading sanitizer: {}", name);

let symbol = Symbol::intern(name);
let dep_kind = DepKind::Implicit;
let dep_kind = DepKind::Explicit;
let (_, data) =
self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
PathKind::Crate, dep_kind);
Expand All @@ -900,6 +927,8 @@ impl<'a> CrateLoader<'a> {
self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
name));
}
} else {
self.sess.err(&format!("Must link std to be compiled with `-Z sanitizer`"));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/run-make/sanitizer-address/overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@

fn main() {
let xs = [0, 1, 2, 3];
let y = unsafe { *xs.as_ptr().offset(4) };
let _y = unsafe { *xs.as_ptr().offset(4) };
}
19 changes: 19 additions & 0 deletions src/test/run-make/sanitizer-cdylib-link/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-include ../tools.mk

# This test builds a shared object, then an executable that links it as a native
# rust library (constrast to an rlib). The shared library and executable both
# are compiled with address sanitizer, and we assert that a fault in the cdylib
# is correctly detected.

ifeq ($(TARGET),x86_64-unknown-linux-gnu)
ASAN_SUPPORT=$(SANITIZER_SUPPORT)
EXTRA_RUSTFLAG=
endif

all:
ifeq ($(ASAN_SUPPORT),1)
$(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) library.rs
$(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs
LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow
endif

15 changes: 15 additions & 0 deletions src/test/run-make/sanitizer-cdylib-link/library.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[no_mangle]
pub extern fn overflow() {
let xs = [0, 1, 2, 3];
let _y = unsafe { *xs.as_ptr().offset(4) };
}
17 changes: 17 additions & 0 deletions src/test/run-make/sanitizer-cdylib-link/program.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern {
fn overflow();
}

fn main() {
unsafe { overflow() }
}
19 changes: 19 additions & 0 deletions src/test/run-make/sanitizer-dylib-link/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-include ../tools.mk

# This test builds a shared object, then an executable that links it as a native
# rust library (constrast to an rlib). The shared library and executable both
# are compiled with address sanitizer, and we assert that a fault in the dylib
# is correctly detected.

ifeq ($(TARGET),x86_64-unknown-linux-gnu)
ASAN_SUPPORT=$(SANITIZER_SUPPORT)
EXTRA_RUSTFLAG=
endif

all:
ifeq ($(ASAN_SUPPORT),1)
$(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) library.rs
$(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs
LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow
endif

15 changes: 15 additions & 0 deletions src/test/run-make/sanitizer-dylib-link/library.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[no_mangle]
pub extern fn overflow() {
let xs = [0, 1, 2, 3];
let _y = unsafe { *xs.as_ptr().offset(4) };
}
17 changes: 17 additions & 0 deletions src/test/run-make/sanitizer-dylib-link/program.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern {
fn overflow();
}

fn main() {
unsafe { overflow() }
}
8 changes: 0 additions & 8 deletions src/test/run-make/sanitizer-dylib/Makefile

This file was deleted.

18 changes: 18 additions & 0 deletions src/test/run-make/sanitizer-invalid-cratetype/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-include ../tools.mk

# NOTE the address sanitizer only supports x86_64 linux and macOS

ifeq ($(TARGET),x86_64-apple-darwin)
ASAN_SUPPORT=$(SANITIZER_SUPPORT)
EXTRA_RUSTFLAG=-C rpath
else
ifeq ($(TARGET),x86_64-unknown-linux-gnu)
ASAN_SUPPORT=$(SANITIZER_SUPPORT)
EXTRA_RUSTFLAG=
endif
endif

all:
ifeq ($(ASAN_SUPPORT),1)
$(RUSTC) -Z sanitizer=address --crate-type proc-macro --target $(TARGET) hello.rs 2>&1 | grep -q -- '-Z sanitizer'
endif
18 changes: 18 additions & 0 deletions src/test/run-make/sanitizer-staticlib-link/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-include ../tools.mk

# This test builds a staticlib, then an executable that links to it.
# The staticlib and executable both are compiled with address sanitizer,
# and we assert that a fault in the staticlib is correctly detected.

ifeq ($(TARGET),x86_64-unknown-linux-gnu)
ASAN_SUPPORT=$(SANITIZER_SUPPORT)
EXTRA_RUSTFLAG=
endif

all:
ifeq ($(ASAN_SUPPORT),1)
$(RUSTC) -g -Z sanitizer=address --crate-type staticlib --target $(TARGET) library.rs
$(CC) program.c $(call STATICLIB,library) $(call OUT_EXE,program) $(EXTRACFLAGS) $(EXTRACXXFLAGS)
LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | grep -q stack-buffer-overflow
endif

15 changes: 15 additions & 0 deletions src/test/run-make/sanitizer-staticlib-link/library.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[no_mangle]
pub extern fn overflow() {
let xs = [0, 1, 2, 3];
let _y = unsafe { *xs.as_ptr().offset(4) };
}
8 changes: 8 additions & 0 deletions src/test/run-make/sanitizer-staticlib-link/program.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// ignore-license
void overflow();

int main() {
overflow();
return 0;
}