about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/sys/windows/fs.rs27
-rw-r--r--library/std/src/sys/windows/mod.rs27
-rw-r--r--library/std/src/sys/windows/os/tests.rs18
3 files changed, 20 insertions, 52 deletions
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 1545ba0d023..c702b8e744c 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -11,7 +11,7 @@ use crate::slice;
 use crate::sync::Arc;
 use crate::sys::handle::Handle;
 use crate::sys::time::SystemTime;
-use crate::sys::{c, cvt, AlignedAs};
+use crate::sys::{c, cvt, Align8};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::thread;
 
@@ -47,9 +47,6 @@ pub struct ReadDir {
     first: Option<c::WIN32_FIND_DATAW>,
 }
 
-type AlignedReparseBuf =
-    AlignedAs<c::REPARSE_DATA_BUFFER, [u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]>;
-
 struct FindNextFileHandle(c::HANDLE);
 
 unsafe impl Send for FindNextFileHandle {}
@@ -329,7 +326,7 @@ impl File {
             cvt(c::GetFileInformationByHandle(self.handle.as_raw_handle(), &mut info))?;
             let mut reparse_tag = 0;
             if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
-                let mut b = AlignedReparseBuf::new([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
+                let mut b = Align8([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
                 if let Ok((_, buf)) = self.reparse_point(&mut b) {
                     reparse_tag = (*buf).ReparseTag;
                 }
@@ -392,7 +389,7 @@ impl File {
             attr.file_size = info.AllocationSize as u64;
             attr.number_of_links = Some(info.NumberOfLinks);
             if attr.file_type().is_reparse_point() {
-                let mut b = AlignedReparseBuf::new([0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
+                let mut b = Align8([0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
                 if let Ok((_, buf)) = self.reparse_point(&mut b) {
                     attr.reparse_tag = (*buf).ReparseTag;
                 }
@@ -466,28 +463,32 @@ impl File {
     // avoid narrowing provenance to the actual `REPARSE_DATA_BUFFER`.
     fn reparse_point(
         &self,
-        space: &mut AlignedReparseBuf,
+        space: &mut Align8<[u8]>,
     ) -> io::Result<(c::DWORD, *const c::REPARSE_DATA_BUFFER)> {
         unsafe {
             let mut bytes = 0;
             cvt({
+                // Grab this in advance to avoid it invalidating the pointer
+                // we get from `space.0.as_mut_ptr()`.
+                let len = space.0.len();
                 c::DeviceIoControl(
                     self.handle.as_raw_handle(),
                     c::FSCTL_GET_REPARSE_POINT,
                     ptr::null_mut(),
                     0,
-                    space.value.as_mut_ptr() as *mut _,
-                    space.value.len() as c::DWORD,
+                    space.0.as_mut_ptr().cast(),
+                    len as c::DWORD,
                     &mut bytes,
                     ptr::null_mut(),
                 )
             })?;
-            Ok((bytes, space.value.as_ptr().cast::<c::REPARSE_DATA_BUFFER>()))
+            const _: () = assert!(core::mem::align_of::<c::REPARSE_DATA_BUFFER>() <= 8);
+            Ok((bytes, space.0.as_ptr().cast::<c::REPARSE_DATA_BUFFER>()))
         }
     }
 
     fn readlink(&self) -> io::Result<PathBuf> {
-        let mut space = AlignedReparseBuf::new([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
+        let mut space = Align8([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
         let (_bytes, buf) = self.reparse_point(&mut space)?;
         unsafe {
             let (path_buffer, subst_off, subst_len, relative) = match (*buf).ReparseTag {
@@ -1345,8 +1346,8 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
     let h = f.as_inner().as_raw_handle();
 
     unsafe {
-        let mut data = AlignedReparseBuf::new([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
-        let data_ptr = data.value.as_mut_ptr();
+        let mut data = Align8([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
+        let data_ptr = data.0.as_mut_ptr();
         let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>();
         let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
         let mut i = 0;
diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs
index fbbc5cb79fb..340cae4066b 100644
--- a/library/std/src/sys/windows/mod.rs
+++ b/library/std/src/sys/windows/mod.rs
@@ -330,25 +330,10 @@ pub fn abort_internal() -> ! {
     crate::intrinsics::abort();
 }
 
-/// Used for some win32 buffers which are stack allocated, for example:
-/// `AlignedAs<c::REPARSE_DATA_BUFFER, [u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]>`
-#[repr(C)]
+/// Align the inner value to 8 bytes.
+///
+/// This is enough for almost all of the buffers we're likely to work with in
+/// the Windows APIs we use.
+#[repr(C, align(8))]
 #[derive(Copy, Clone)]
-pub struct AlignedAs<Aligner, Alignee: ?Sized> {
-    /// Use `[Aligner; 0]` as a sort of `PhantomAlignNextField<Aligner>`. This
-    /// is a bit of a hack, and could break (in a way that's caught by tests) if
-    /// #81996 is fixed.
-    aligner: [Aligner; 0],
-    /// The aligned value. Public rather than exposed via accessors so that if
-    /// needed it can be used with `addr_of` and such (also, this is less code).
-    pub value: Alignee,
-}
-
-impl<Aligner, Alignee> AlignedAs<Aligner, Alignee> {
-    // This is frequently used with large stack buffers, so force-inline to
-    // try and avoid using 2x as much stack space in debug builds.
-    #[inline(always)]
-    pub const fn new(value: Alignee) -> Self {
-        Self { aligner: [], value }
-    }
-}
+pub(crate) struct Align8<T: ?Sized>(pub T);
diff --git a/library/std/src/sys/windows/os/tests.rs b/library/std/src/sys/windows/os/tests.rs
index 532be0cf083..458d6e11c20 100644
--- a/library/std/src/sys/windows/os/tests.rs
+++ b/library/std/src/sys/windows/os/tests.rs
@@ -11,21 +11,3 @@ fn ntstatus_error() {
             .contains("FormatMessageW() returned error")
     );
 }
-
-#[test]
-fn smoketest_aligned_as() {
-    use crate::{
-        mem::{align_of, size_of},
-        ptr::addr_of,
-        sys::{c, AlignedAs},
-    };
-    type AlignedReparseBuf =
-        AlignedAs<c::REPARSE_DATA_BUFFER, [u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]>;
-    assert!(size_of::<AlignedReparseBuf>() >= c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
-    assert_eq!(align_of::<AlignedReparseBuf>(), align_of::<c::REPARSE_DATA_BUFFER>());
-    let a = AlignedReparseBuf::new([0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
-    // Quick and dirty offsetof check.
-    assert_eq!(addr_of!(a).cast::<u8>(), addr_of!(a.value).cast::<u8>());
-    // Smoke check that it's actually aligned.
-    assert!(addr_of!(a.value).is_aligned_to(align_of::<c::REPARSE_DATA_BUFFER>()));
-}