|
1 | 1 | use super::super::super::windows_sys::*;
|
2 | 2 | use super::mystd::ffi::OsString;
|
| 3 | +#[cfg(windows)] |
| 4 | +use super::mystd::os::windows::prelude::*; |
3 | 5 | use super::{coff, mmap, Library, LibrarySegment};
|
4 | 6 | use alloc::vec;
|
5 | 7 | use alloc::vec::Vec;
|
@@ -42,43 +44,64 @@ unsafe fn add_loaded_images(ret: &mut Vec<Library>) {
|
42 | 44 | }
|
43 | 45 | }
|
44 | 46 |
|
45 |
| -unsafe fn load_library(me: &MODULEENTRY32W) -> Option<Library> { |
46 |
| - let pos = me |
47 |
| - .szExePath |
48 |
| - .iter() |
49 |
| - .position(|i| *i == 0) |
50 |
| - .unwrap_or(me.szExePath.len()); |
| 47 | +// Safety: long_path should be null-terminated |
| 48 | +#[cfg(target_os = "cygwin")] |
| 49 | +unsafe fn get_posix_path(long_path: &[u16]) -> Option<OsString> { |
| 50 | + use std::os::unix::ffi::OsStringExt; |
| 51 | + |
| 52 | + unsafe extern "C" { |
| 53 | + fn cygwin_conv_path( |
| 54 | + what: libc::c_uint, |
| 55 | + from: *const libc::c_void, |
| 56 | + to: *mut libc::c_void, |
| 57 | + size: libc::size_t, |
| 58 | + ) -> libc::ssize_t; |
| 59 | + } |
| 60 | + const CCP_WIN_W_TO_POSIX: libc::c_uint = 3; |
| 61 | + |
51 | 62 | let name_len = unsafe {
|
52 |
| - WideCharToMultiByte( |
53 |
| - CP_UTF8, |
54 |
| - 0, |
55 |
| - me.szExePath.as_ptr(), |
56 |
| - pos as i32, |
| 63 | + cygwin_conv_path( |
| 64 | + CCP_WIN_W_TO_POSIX, |
| 65 | + long_path.as_ptr().cast(), |
57 | 66 | core::ptr::null_mut(),
|
58 | 67 | 0,
|
59 |
| - core::ptr::null_mut(), |
60 |
| - core::ptr::null_mut(), |
61 |
| - ) as usize |
| 68 | + ) |
62 | 69 | };
|
| 70 | + // Expect at least 1 for null terminator. |
| 71 | + if name_len < 1 { |
| 72 | + return None; |
| 73 | + } |
| 74 | + let name_len = name_len as usize; |
63 | 75 | let mut name_buffer = vec![0_u8; name_len];
|
64 |
| - let name_len = unsafe { |
65 |
| - WideCharToMultiByte( |
66 |
| - CP_UTF8, |
67 |
| - 0, |
68 |
| - me.szExePath.as_ptr(), |
69 |
| - pos as i32, |
70 |
| - name_buffer.as_mut_ptr(), |
71 |
| - name_buffer.len() as i32, |
72 |
| - core::ptr::null_mut(), |
73 |
| - core::ptr::null_mut(), |
74 |
| - ) as usize |
| 76 | + let res = unsafe { |
| 77 | + cygwin_conv_path( |
| 78 | + CCP_WIN_W_TO_POSIX, |
| 79 | + long_path.as_ptr().cast(), |
| 80 | + name_buffer.as_mut_ptr().cast(), |
| 81 | + name_buffer.len(), |
| 82 | + ) |
75 | 83 | };
|
76 |
| - if name_len == 0 || name_len > name_buffer.len() { |
77 |
| - // This can't happen. |
| 84 | + if res != 0 { |
78 | 85 | return None;
|
79 | 86 | }
|
80 |
| - unsafe { name_buffer.set_len(name_len) }; |
81 |
| - let name = unsafe { OsString::from_encoded_bytes_unchecked(name_buffer) }; |
| 87 | + // Ignore null terminator. |
| 88 | + unsafe { name_buffer.set_len(name_len - 1) }; |
| 89 | + let name = OsString::from_vec(name_buffer); |
| 90 | + Some(name) |
| 91 | +} |
| 92 | + |
| 93 | +unsafe fn load_library(me: &MODULEENTRY32W) -> Option<Library> { |
| 94 | + let pos = me |
| 95 | + .szExePath |
| 96 | + .iter() |
| 97 | + .position(|i| *i == 0) |
| 98 | + .unwrap_or(me.szExePath.len()); |
| 99 | + #[cfg(windows)] |
| 100 | + let name = OsString::from_wide(&me.szExePath[..pos]); |
| 101 | + #[cfg(target_os = "cygwin")] |
| 102 | + // Safety: the path with max length MAX_PATH always contains a null |
| 103 | + // terminator |
| 104 | + let name = unsafe { get_posix_path(&me.szExePath[..pos])? }; |
82 | 105 |
|
83 | 106 | // MinGW libraries currently don't support ASLR
|
84 | 107 | // (rust-lang/rust#16514), but DLLs can still be relocated around in
|
|
0 commit comments