Skip to content

Commit 4d81c02

Browse files
committed
Error when paths contain NUL characters
On Windows: Previously these paths were silently truncated at these NUL characters, now they fail with `ErrorKind::InvalidInput`.
1 parent 3e48b0e commit 4d81c02

File tree

1 file changed

+24
-19
lines changed
  • src/libstd/sys/windows

1 file changed

+24
-19
lines changed

src/libstd/sys/windows/fs.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl File {
226226
}
227227

228228
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
229-
let path = to_utf16(path);
229+
let path = try!(to_u16s(path));
230230
let handle = unsafe {
231231
c::CreateFileW(path.as_ptr(),
232232
opts.get_desired_access(),
@@ -377,8 +377,13 @@ impl fmt::Debug for File {
377377
}
378378
}
379379

380-
pub fn to_utf16(s: &Path) -> Vec<u16> {
381-
s.as_os_str().encode_wide().chain(Some(0)).collect()
380+
pub fn to_u16s(s: &Path) -> io::Result<Vec<u16>> {
381+
let mut maybe_result = s.as_os_str().encode_wide().collect();
382+
if maybe_result.iter().any(|&u| u == 0) {
383+
return Err(io::Error::new(io::ErrorKind::InvalidInput, "paths cannot contain NULs"));
384+
}
385+
maybe_result.push(0);
386+
Ok(maybe_result)
382387
}
383388

384389
impl FileAttr {
@@ -449,7 +454,7 @@ impl DirBuilder {
449454
pub fn new() -> DirBuilder { DirBuilder }
450455

451456
pub fn mkdir(&self, p: &Path) -> io::Result<()> {
452-
let p = to_utf16(p);
457+
let p = try!(to_u16s(p));
453458
try!(cvt(unsafe {
454459
c::CreateDirectoryW(p.as_ptr(), ptr::null_mut())
455460
}));
@@ -460,7 +465,7 @@ impl DirBuilder {
460465
pub fn readdir(p: &Path) -> io::Result<ReadDir> {
461466
let root = p.to_path_buf();
462467
let star = p.join("*");
463-
let path = to_utf16(&star);
468+
let path = try!(to_u16s(&star));
464469

465470
unsafe {
466471
let mut wfd = mem::zeroed();
@@ -478,22 +483,22 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
478483
}
479484

480485
pub fn unlink(p: &Path) -> io::Result<()> {
481-
let p_utf16 = to_utf16(p);
482-
try!(cvt(unsafe { c::DeleteFileW(p_utf16.as_ptr()) }));
486+
let p_u16s = try!(to_u16s(p));
487+
try!(cvt(unsafe { c::DeleteFileW(p_u16s.as_ptr()) }));
483488
Ok(())
484489
}
485490

486491
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
487-
let old = to_utf16(old);
488-
let new = to_utf16(new);
492+
let old = try!(to_u16s(old));
493+
let new = try!(to_u16s(new));
489494
try!(cvt(unsafe {
490495
c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING)
491496
}));
492497
Ok(())
493498
}
494499

495500
pub fn rmdir(p: &Path) -> io::Result<()> {
496-
let p = to_utf16(p);
501+
let p = try!(to_u16s(p));
497502
try!(cvt(unsafe { c::RemoveDirectoryW(p.as_ptr()) }));
498503
Ok(())
499504
}
@@ -508,8 +513,8 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
508513
}
509514

510515
pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
511-
let src = to_utf16(src);
512-
let dst = to_utf16(dst);
516+
let src = try!(to_u16s(src));
517+
let dst = try!(to_u16s(dst));
513518
let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 };
514519
try!(cvt(unsafe {
515520
c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL
@@ -518,8 +523,8 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
518523
}
519524

520525
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
521-
let src = to_utf16(src);
522-
let dst = to_utf16(dst);
526+
let src = try!(to_u16s(src));
527+
let dst = try!(to_u16s(dst));
523528
try!(cvt(unsafe {
524529
c::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::null_mut())
525530
}));
@@ -545,10 +550,10 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
545550
}
546551

547552
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
548-
let utf16 = to_utf16(p);
553+
let u16s = try!(to_u16s(p));
549554
unsafe {
550555
let mut attr: FileAttr = mem::zeroed();
551-
try!(cvt(c::GetFileAttributesExW(utf16.as_ptr(),
556+
try!(cvt(c::GetFileAttributesExW(u16s.as_ptr(),
552557
c::GetFileExInfoStandard,
553558
&mut attr.data as *mut _ as *mut _)));
554559
if attr.is_reparse_point() {
@@ -562,7 +567,7 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
562567
}
563568

564569
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
565-
let p = to_utf16(p);
570+
let p = try!(to_u16s(p));
566571
unsafe {
567572
try!(cvt(c::SetFileAttributesW(p.as_ptr(), perm.attrs)));
568573
Ok(())
@@ -602,8 +607,8 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
602607
*(lpData as *mut i64) = TotalBytesTransferred;
603608
c::PROGRESS_CONTINUE
604609
}
605-
let pfrom = to_utf16(from);
606-
let pto = to_utf16(to);
610+
let pfrom = try!(to_u16s(from));
611+
let pto = try!(to_u16s(to));
607612
let mut size = 0i64;
608613
try!(cvt(unsafe {
609614
c::CopyFileExW(pfrom.as_ptr(), pto.as_ptr(), Some(callback),

0 commit comments

Comments
 (0)