]> git.lizzy.rs Git - rust.git/commitdiff
readdir: return error instead of failing on invalid UTF-16
authorPeter Atashian <retep998@gmail.com>
Sat, 6 Sep 2014 16:51:42 +0000 (12:51 -0400)
committerPeter Atashian <retep998@gmail.com>
Sat, 6 Sep 2014 16:51:42 +0000 (12:51 -0400)
Fixes #15279

Signed-off-by: Peter Atashian <retep998@gmail.com>
src/liblibc/lib.rs
src/libnative/io/file_windows.rs
src/rt/rust_builtin.c

index bbccdf0acf9d29b1d7d6fc9cbf7bddabab190b0e..35b05a672b28dc8720e3e7d40e998665812d75c2 100644 (file)
 #[cfg(windows)] pub use types::os::arch::extra::{LARGE_INTEGER, LPVOID, LONG};
 #[cfg(windows)] pub use types::os::arch::extra::{time64_t, OVERLAPPED, LPCWSTR};
 #[cfg(windows)] pub use types::os::arch::extra::{LPOVERLAPPED, SIZE_T, LPDWORD};
-#[cfg(windows)] pub use types::os::arch::extra::{SECURITY_ATTRIBUTES};
+#[cfg(windows)] pub use types::os::arch::extra::{SECURITY_ATTRIBUTES, WIN32_FIND_DATAW};
 #[cfg(windows)] pub use funcs::c95::string::{wcslen};
 #[cfg(windows)] pub use funcs::posix88::stat_::{wstat, wutime, wchmod, wrmdir};
 #[cfg(windows)] pub use funcs::bsd43::{closesocket};
@@ -1638,6 +1638,22 @@ pub struct WSAPROTOCOL_INFO {
                 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
 
                 pub type GROUP = c_uint;
+
+                #[repr(C)]
+                pub struct WIN32_FIND_DATAW {
+                    pub dwFileAttributes: DWORD,
+                    pub ftCreationTime: FILETIME,
+                    pub ftLastAccessTime: FILETIME,
+                    pub ftLastWriteTime: FILETIME,
+                    pub nFileSizeHigh: DWORD,
+                    pub nFileSizeLow: DWORD,
+                    pub dwReserved0: DWORD,
+                    pub dwReserved1: DWORD,
+                    pub cFileName: [wchar_t, ..260], // #define MAX_PATH 260
+                    pub cAlternateFileName: [wchar_t, ..14],
+                }
+
+                pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
             }
         }
     }
@@ -4763,7 +4779,7 @@ pub mod kernel32 {
                                                LPMEMORY_BASIC_INFORMATION,
                                                LPSYSTEM_INFO, HANDLE, LPHANDLE,
                                                LARGE_INTEGER, PLARGE_INTEGER,
-                                               LPFILETIME};
+                                               LPFILETIME, LPWIN32_FIND_DATAW};
 
             extern "system" {
                 pub fn GetEnvironmentVariableW(n: LPCWSTR,
@@ -4793,9 +4809,9 @@ pub fn GetCurrentDirectoryW(nBufferLength: DWORD,
                                             -> DWORD;
                 pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
                 pub fn GetLastError() -> DWORD;
-                pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: HANDLE)
+                pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW)
                                       -> HANDLE;
-                pub fn FindNextFileW(findFile: HANDLE, findFileData: HANDLE)
+                pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW)
                                      -> BOOL;
                 pub fn FindClose(findFile: HANDLE) -> BOOL;
                 pub fn DuplicateHandle(hSourceProcessHandle: HANDLE,
index cb1d79b8397face0ab6dbba21f148ff37084eef7..adc97c6bede70d5a1d0f23396ad7179218e97812 100644 (file)
@@ -11,8 +11,7 @@
 //! Blocking Windows-based file I/O
 
 use alloc::arc::Arc;
-use libc::{c_int, c_void};
-use libc;
+use libc::{mod, c_int};
 use std::c_str::CString;
 use std::mem;
 use std::os::windows::fill_utf16_buf_and_decode;
@@ -20,7 +19,6 @@
 use std::rt::rtio;
 use std::rt::rtio::{IoResult, IoError};
 use std::str;
-use std::vec;
 
 pub type fd_t = libc::c_int;
 
@@ -344,8 +342,6 @@ pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
 }
 
 pub fn readdir(p: &CString) -> IoResult<Vec<CString>> {
-    use std::rt::libc_heap::malloc_raw;
-
     fn prune(root: &CString, dirs: Vec<Path>) -> Vec<CString> {
         let root = unsafe { CString::new(root.as_ptr(), false) };
         let root = Path::new(root);
@@ -355,38 +351,35 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<CString> {
         }).map(|path| root.join(path).to_c_str()).collect()
     }
 
-    extern {
-        fn rust_list_dir_wfd_size() -> libc::size_t;
-        fn rust_list_dir_wfd_fp_buf(wfd: *mut libc::c_void) -> *const u16;
-    }
     let star = Path::new(unsafe {
         CString::new(p.as_ptr(), false)
     }).join("*");
     let path = try!(to_utf16(&star.to_c_str()));
 
     unsafe {
-        let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
-        let find_handle = libc::FindFirstFileW(path.as_ptr(),
-                                               wfd_ptr as libc::HANDLE);
+        let mut wfd = mem::zeroed();
+        let find_handle = libc::FindFirstFileW(path.as_ptr(), &mut wfd);
         if find_handle != libc::INVALID_HANDLE_VALUE {
-            let mut paths = vec!();
-            let mut more_files = 1 as libc::c_int;
+            let mut paths = vec![];
+            let mut more_files = 1 as libc::BOOL;
             while more_files != 0 {
-                let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr as *mut c_void);
-                if fp_buf as uint == 0 {
-                    fail!("os::list_dir() failure: got null ptr from wfd");
-                } else {
-                    let fp_vec = vec::raw::from_buf(fp_buf, libc::wcslen(fp_buf) as uint);
-                    let fp_trimmed = str::truncate_utf16_at_nul(fp_vec.as_slice());
-                    let fp_str = String::from_utf16(fp_trimmed)
-                            .expect("rust_list_dir_wfd_fp_buf returned invalid UTF-16");
-                    paths.push(Path::new(fp_str));
+                {
+                    let filename = str::truncate_utf16_at_nul(wfd.cFileName);
+                    match String::from_utf16(filename) {
+                        Some(filename) => paths.push(Path::new(filename)),
+                        None => {
+                            assert!(libc::FindClose(find_handle) != 0);
+                            return Err(IoError {
+                                code: super::c::ERROR_ILLEGAL_CHARACTER as uint,
+                                extra: 0,
+                                detail: Some(format!("path was not valid UTF-16: {}", filename)),
+                            })
+                        }, // FIXME #12056: Convert the UCS-2 to invalid utf-8 instead of erroring
+                    }
                 }
-                more_files = libc::FindNextFileW(find_handle,
-                                                 wfd_ptr as libc::HANDLE);
+                more_files = libc::FindNextFileW(find_handle, &mut wfd);
             }
             assert!(libc::FindClose(find_handle) != 0);
-            libc::free(wfd_ptr as *mut c_void);
             Ok(prune(p, paths))
         } else {
             Err(super::last_error())
index ba20f2c6f27f9fca7b9404cb90564be862331cdd..5dc07f859aed02817cd3457a6a62be973de6e9dd 100644 (file)
@@ -100,33 +100,6 @@ rust_list_dir_val(struct dirent* entry_ptr) {
 }
 #endif
 
-size_t
-#if defined(__WIN32__)
-rust_list_dir_wfd_size() {
-    return sizeof(WIN32_FIND_DATAW);
-}
-#else
-rust_list_dir_wfd_size() {
-    return 0;
-}
-#endif
-
-void*
-#if defined(__WIN32__)
-rust_list_dir_wfd_fp_buf(WIN32_FIND_DATAW* wfd) {
-    if(wfd == NULL) {
-        return 0;
-    }
-    else {
-        return wfd->cFileName;
-    }
-}
-#else
-rust_list_dir_wfd_fp_buf(void* wfd) {
-    return 0;
-}
-#endif
-
 typedef struct {
     int32_t tm_sec;
     int32_t tm_min;