about summary refs log tree commit diff
path: root/src/libnative
diff options
context:
space:
mode:
authorPeter Atashian <retep998@gmail.com>2014-09-06 12:51:42 -0400
committerPeter Atashian <retep998@gmail.com>2014-09-06 12:51:42 -0400
commitd3ec0674bbf031008a5b741d04edc9ebdc466264 (patch)
treee8ccb6bf56d87d32a931f7989aa17742fc6587ea /src/libnative
parent82c052794d4234752f0154c150d0b40779240db4 (diff)
downloadrust-d3ec0674bbf031008a5b741d04edc9ebdc466264.tar.gz
rust-d3ec0674bbf031008a5b741d04edc9ebdc466264.zip
readdir: return error instead of failing on invalid UTF-16
Fixes #15279

Signed-off-by: Peter Atashian <retep998@gmail.com>
Diffstat (limited to 'src/libnative')
-rw-r--r--src/libnative/io/file_windows.rs45
1 files changed, 19 insertions, 26 deletions
diff --git a/src/libnative/io/file_windows.rs b/src/libnative/io/file_windows.rs
index cb1d79b8397..adc97c6bede 100644
--- a/src/libnative/io/file_windows.rs
+++ b/src/libnative/io/file_windows.rs
@@ -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::ptr;
 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 @@ pub fn readdir(p: &CString) -> IoResult<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())