Skip to content

Commit 3da66f0

Browse files
authored
Rollup merge of #101236 - thomcc:winfs-nozero, r=ChrisDenton
Avoid needless buffer zeroing in `std::sys::windows::fs` Followup to #101171 and #101193. This finishes up avoiding buffer zeroing pointed out in #100729 (comment) (thanks!) r? `@ChrisDenton`
2 parents 0620f6e + 14dd33b commit 3da66f0

File tree

1 file changed

+24
-14
lines changed
  • library/std/src/sys/windows

1 file changed

+24
-14
lines changed

library/std/src/sys/windows/fs.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::os::windows::prelude::*;
33
use crate::ffi::OsString;
44
use crate::fmt;
55
use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
6-
use crate::mem;
6+
use crate::mem::{self, MaybeUninit};
77
use crate::os::windows::io::{AsHandle, BorrowedHandle};
88
use crate::path::{Path, PathBuf};
99
use crate::ptr;
@@ -326,7 +326,8 @@ impl File {
326326
cvt(c::GetFileInformationByHandle(self.handle.as_raw_handle(), &mut info))?;
327327
let mut reparse_tag = 0;
328328
if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
329-
let mut b = Align8([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
329+
let mut b =
330+
Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
330331
if let Ok((_, buf)) = self.reparse_point(&mut b) {
331332
reparse_tag = (*buf).ReparseTag;
332333
}
@@ -389,7 +390,8 @@ impl File {
389390
attr.file_size = info.AllocationSize as u64;
390391
attr.number_of_links = Some(info.NumberOfLinks);
391392
if attr.file_type().is_reparse_point() {
392-
let mut b = Align8([0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
393+
let mut b =
394+
Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
393395
if let Ok((_, buf)) = self.reparse_point(&mut b) {
394396
attr.reparse_tag = (*buf).ReparseTag;
395397
}
@@ -463,7 +465,7 @@ impl File {
463465
// avoid narrowing provenance to the actual `REPARSE_DATA_BUFFER`.
464466
fn reparse_point(
465467
&self,
466-
space: &mut Align8<[u8]>,
468+
space: &mut Align8<[MaybeUninit<u8>]>,
467469
) -> io::Result<(c::DWORD, *const c::REPARSE_DATA_BUFFER)> {
468470
unsafe {
469471
let mut bytes = 0;
@@ -488,7 +490,7 @@ impl File {
488490
}
489491

490492
fn readlink(&self) -> io::Result<PathBuf> {
491-
let mut space = Align8([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
493+
let mut space = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
492494
let (_bytes, buf) = self.reparse_point(&mut space)?;
493495
unsafe {
494496
let (path_buffer, subst_off, subst_len, relative) = match (*buf).ReparseTag {
@@ -658,12 +660,16 @@ impl File {
658660

659661
/// A buffer for holding directory entries.
660662
struct DirBuff {
661-
buffer: Box<Align8<[u8; Self::BUFFER_SIZE]>>,
663+
buffer: Box<Align8<[MaybeUninit<u8>; Self::BUFFER_SIZE]>>,
662664
}
663665
impl DirBuff {
664666
const BUFFER_SIZE: usize = 1024;
665667
fn new() -> Self {
666-
Self { buffer: Box::new(Align8([0u8; Self::BUFFER_SIZE])) }
668+
Self {
669+
// Safety: `Align8<[MaybeUninit<u8>; N]>` does not need
670+
// initialization.
671+
buffer: unsafe { Box::new_uninit().assume_init() },
672+
}
667673
}
668674
fn capacity(&self) -> usize {
669675
self.buffer.0.len()
@@ -676,8 +682,8 @@ impl DirBuff {
676682
DirBuffIter::new(self)
677683
}
678684
}
679-
impl AsRef<[u8]> for DirBuff {
680-
fn as_ref(&self) -> &[u8] {
685+
impl AsRef<[MaybeUninit<u8>]> for DirBuff {
686+
fn as_ref(&self) -> &[MaybeUninit<u8>] {
681687
&self.buffer.0
682688
}
683689
}
@@ -686,7 +692,7 @@ impl AsRef<[u8]> for DirBuff {
686692
///
687693
/// Currently only returns file names (UTF-16 encoded).
688694
struct DirBuffIter<'a> {
689-
buffer: Option<&'a [u8]>,
695+
buffer: Option<&'a [MaybeUninit<u8>]>,
690696
cursor: usize,
691697
}
692698
impl<'a> DirBuffIter<'a> {
@@ -701,9 +707,13 @@ impl<'a> Iterator for DirBuffIter<'a> {
701707
let buffer = &self.buffer?[self.cursor..];
702708

703709
// Get the name and next entry from the buffer.
704-
// SAFETY: The buffer contains a `FILE_ID_BOTH_DIR_INFO` struct but the
705-
// last field (the file name) is unsized. So an offset has to be
706-
// used to get the file name slice.
710+
// SAFETY:
711+
// - The buffer contains a `FILE_ID_BOTH_DIR_INFO` struct but the last
712+
// field (the file name) is unsized. So an offset has to be used to
713+
// get the file name slice.
714+
// - The OS has guaranteed initialization of the fields of
715+
// `FILE_ID_BOTH_DIR_INFO` and the trailing filename (for at least
716+
// `FileNameLength` bytes)
707717
let (name, is_directory, next_entry) = unsafe {
708718
let info = buffer.as_ptr().cast::<c::FILE_ID_BOTH_DIR_INFO>();
709719
// Guaranteed to be aligned in documentation for
@@ -1349,7 +1359,7 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
13491359
let h = f.as_inner().as_raw_handle();
13501360

13511361
unsafe {
1352-
let mut data = Align8([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
1362+
let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
13531363
let data_ptr = data.0.as_mut_ptr();
13541364
let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>();
13551365
let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();

0 commit comments

Comments
 (0)