Skip to content

Commit 15535fa

Browse files
committed
Change dynamic_library::open_external to take ToCStr
`std::unstable::dynamic_library::open_external` currently takes a `Path`, but because `Paths` produce normalized strings, this can change the semantics of lookups in a given environment. This patch generalizes the function to take a `ToCStr`-bounded type, which includes both `Path`s and `str`s. Closes #11650.
1 parent e2cc5b4 commit 15535fa

File tree

1 file changed

+23
-8
lines changed

1 file changed

+23
-8
lines changed

src/libstd/unstable/dynamic_lib.rs

+23-8
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,22 @@ impl Drop for DynamicLibrary {
4545
}
4646

4747
impl DynamicLibrary {
48+
// FIXME (#12938): Until DST lands, we cannot decompose &str into
49+
// & and str, so we cannot usefully take ToCStr arguments by
50+
// reference (without forcing an additional & around &str). So we
51+
// are instead temporarily adding an instance for &Path, so that
52+
// we can take ToCStr as owned. When DST lands, the &Path instance
53+
// should be removed, and arguments bound by ToCStr should be
54+
// passed by reference. (Here: in the `open` method.)
55+
4856
/// Lazily open a dynamic library. When passed None it gives a
4957
/// handle to the calling process
50-
pub fn open(filename: Option<&path::Path>) -> Result<DynamicLibrary, ~str> {
58+
pub fn open<T: ToCStr>(filename: Option<T>)
59+
-> Result<DynamicLibrary, ~str> {
5160
unsafe {
61+
let mut filename = filename;
5262
let maybe_library = dl::check_for_errors_in(|| {
53-
match filename {
63+
match filename.take() {
5464
Some(name) => dl::open_external(name),
5565
None => dl::open_internal()
5666
}
@@ -114,7 +124,8 @@ mod test {
114124
fn test_loading_cosine() {
115125
// The math library does not need to be loaded since it is already
116126
// statically linked in
117-
let libm = match DynamicLibrary::open(None) {
127+
let none: Option<Path> = None; // appease the typechecker
128+
let libm = match DynamicLibrary::open(none) {
118129
Err(error) => fail!("Could not load self as module: {}", error),
119130
Ok(libm) => libm
120131
};
@@ -142,7 +153,7 @@ mod test {
142153
fn test_errors_do_not_crash() {
143154
// Open /dev/null as a library to get an error, and make sure
144155
// that only causes an error, and not a crash.
145-
let path = GenericPath::new("/dev/null");
156+
let path = Path::new("/dev/null");
146157
match DynamicLibrary::open(Some(&path)) {
147158
Err(_) => {}
148159
Ok(_) => fail!("Successfully opened the empty library.")
@@ -157,12 +168,11 @@ mod test {
157168
pub mod dl {
158169
use c_str::ToCStr;
159170
use libc;
160-
use path;
161171
use ptr;
162172
use str;
163173
use result::*;
164174

165-
pub unsafe fn open_external(filename: &path::Path) -> *u8 {
175+
pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
166176
filename.with_c_str(|raw_name| {
167177
dlopen(raw_name, Lazy as libc::c_int) as *u8
168178
})
@@ -223,9 +233,14 @@ pub mod dl {
223233
use os;
224234
use ptr;
225235
use result::{Ok, Err, Result};
236+
use str;
237+
use c_str::ToCStr;
226238

227-
pub unsafe fn open_external(filename: &path::Path) -> *u8 {
228-
os::win32::as_utf16_p(filename.as_str().unwrap(), |raw_name| {
239+
pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
240+
// Windows expects Unicode data
241+
let filename_cstr = filename.to_c_str();
242+
let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
243+
os::win32::as_utf16_p(filename_str, |raw_name| {
229244
LoadLibraryW(raw_name as *libc::c_void) as *u8
230245
})
231246
}

0 commit comments

Comments
 (0)