Skip to content

Commit

Permalink
readdir: return error instead of failing on invalid UTF-16
Browse files Browse the repository at this point in the history
Fixes #15279

Signed-off-by: Peter Atashian <retep998@gmail.com>
  • Loading branch information
retep998 committed Sep 6, 2014
1 parent 82c0527 commit d3ec067
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 57 deletions.
24 changes: 20 additions & 4 deletions src/liblibc/lib.rs
Expand Up @@ -249,7 +249,7 @@ pub use funcs::bsd43::{shutdown};
#[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};
Expand Down Expand Up @@ -1638,6 +1638,22 @@ pub mod types {
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;
}
}
}
Expand Down Expand Up @@ -4763,7 +4779,7 @@ pub mod funcs {
LPMEMORY_BASIC_INFORMATION,
LPSYSTEM_INFO, HANDLE, LPHANDLE,
LARGE_INTEGER, PLARGE_INTEGER,
LPFILETIME};
LPFILETIME, LPWIN32_FIND_DATAW};

extern "system" {
pub fn GetEnvironmentVariableW(n: LPCWSTR,
Expand Down Expand Up @@ -4793,9 +4809,9 @@ pub mod funcs {
-> 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,
Expand Down
45 changes: 19 additions & 26 deletions src/libnative/io/file_windows.rs
Expand Up @@ -11,16 +11,14 @@
//! 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;
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;

Expand Down Expand Up @@ -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);
Expand All @@ -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())
Expand Down
27 changes: 0 additions & 27 deletions src/rt/rust_builtin.c
Expand Up @@ -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;
Expand Down

5 comments on commit d3ec067

@bors
Copy link
Contributor

@bors bors commented on d3ec067 Sep 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at retep998@d3ec067

@bors
Copy link
Contributor

@bors bors commented on d3ec067 Sep 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging retep998/rust/glob-fix = d3ec067 into auto

@bors
Copy link
Contributor

@bors bors commented on d3ec067 Sep 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

retep998/rust/glob-fix = d3ec067 merged ok, testing candidate = 4067252d

@bors
Copy link
Contributor

@bors bors commented on d3ec067 Sep 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 4067252d

Please sign in to comment.