From 91d7dd21770c5d86649f8b627fbf3b0d02f415ef Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Thu, 18 Aug 2022 14:51:10 -0700 Subject: [PATCH 1/2] Avoid zeroing a 1kb stack buffer on every call to `std::sys::windows::fill_utf16_buf` --- std/src/sys/windows/mod.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/std/src/sys/windows/mod.rs b/std/src/sys/windows/mod.rs index b3f6d2d0a..3b0c612dd 100644 --- a/std/src/sys/windows/mod.rs +++ b/std/src/sys/windows/mod.rs @@ -2,6 +2,7 @@ use crate::ffi::{CStr, OsStr, OsString}; use crate::io::ErrorKind; +use crate::mem::MaybeUninit; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::path::PathBuf; use crate::time::Duration; @@ -204,8 +205,8 @@ where // This initial size also works around `GetFullPathNameW` returning // incorrect size hints for some short paths: // https://github.com/dylni/normpath/issues/5 - let mut stack_buf = [0u16; 512]; - let mut heap_buf = Vec::new(); + let mut stack_buf: [MaybeUninit; 512] = MaybeUninit::uninit_array(); + let mut heap_buf: Vec> = Vec::new(); unsafe { let mut n = stack_buf.len(); loop { @@ -214,6 +215,11 @@ where } else { let extra = n - heap_buf.len(); heap_buf.reserve(extra); + // We used `reserve` and not `reserve_exact`, so in theory we + // may have gotten more than requested. If so, we'd like to use + // it... so long as we won't cause overflow. + n = heap_buf.capacity().min(c::DWORD::MAX as usize); + // Safety: MaybeUninit does not need initialization heap_buf.set_len(n); &mut heap_buf[..] }; @@ -228,13 +234,13 @@ where // error" is still 0 then we interpret it as a 0 length buffer and // not an actual error. c::SetLastError(0); - let k = match f1(buf.as_mut_ptr(), n as c::DWORD) { + let k = match f1(buf.as_mut_ptr().cast::(), n as c::DWORD) { 0 if c::GetLastError() == 0 => 0, 0 => return Err(crate::io::Error::last_os_error()), n => n, } as usize; if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER { - n *= 2; + n = n.saturating_mul(2).min(c::DWORD::MAX as usize); } else if k > n { n = k; } else if k == n { @@ -244,7 +250,9 @@ where // Therefore k never equals n. unreachable!(); } else { - return Ok(f2(&buf[..k])); + // Safety: First `k` bytes are initialized. + let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]); + return Ok(f2(slice)); } } } From b3e3bf10b11b3509f8248c15fefe9c377eb34a0a Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Fri, 19 Aug 2022 08:45:21 -0700 Subject: [PATCH 2/2] Fix comment typo --- std/src/sys/windows/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/src/sys/windows/mod.rs b/std/src/sys/windows/mod.rs index 3b0c612dd..a9846a484 100644 --- a/std/src/sys/windows/mod.rs +++ b/std/src/sys/windows/mod.rs @@ -250,7 +250,7 @@ where // Therefore k never equals n. unreachable!(); } else { - // Safety: First `k` bytes are initialized. + // Safety: First `k` values are initialized. let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]); return Ok(f2(slice)); }