Change:
panics on some Windows version when calling due to a newly introduced . This code: I expected to see this happen: It removes everything or reports an error. Instead, this happened: It panics with . (Crashes on Windows, but we're just using upstream 1.65.0 there). Full Firefox crash report: https://crash- Firefox bug: Last commit that changed that: PR: File: We saw that on 3 Windows 10 versions: 10.0., 10.0. and 10.0.. Though I haven't checked the latest crashes, it might be more now. cc
Oof, this sucks! I don't know why this wouldn't be unaligned. As the comment there states, . While we could use an unaligned read for the various fields, this would only reduce the alignment requirement to 2bytes. There's not much we can do for the filename array, since we need to provide a to the caller. Hopefully that's enough... I'll do this after work. CC who may have some ideas.
This is concerning to me, for more than just Rust. These structs should really be aligned as documented. Do you happen to have any more context for the crashes? My best guess is this may ultimately be caused by a bad filesystem driver (e.g. certain VM shared drives and RAM drives are particularly notorious). If it's the OS itself then that's a bigger issue. Also I'm assuming the crashes are on actual Windows and not WINE or other emulation? In any case, yeah we'll need to weaken our assumption here which is unfortunate.
I went through the other places I asserted alignment in , and they should be fine -- those are entirely under our control (unlike this where I relied on the system behaving as documented), so I don't think there's any need to remove them too.
From all I see in the Firefox crash reports these are actual machines. It's definitely buggy behavior compared to the docs, but I don't know where that bug is (Windows bug, driver bug, broken memory/disk, ...)
According to . We might have a workaround there (avoiding that specific codepath overall), it should land with the next nightly, so I will know more after the weekend.
Looking at the report in OP there are at least 2 DLLs that could have caused the issue: SuRun () that restricts programs permissions and Sandboxie () which is a some kind of a sandbox. I have never used either of them but given their functionality it sounds they could be the reason of this misalignment (I think it's even UB to misalign pointer that is documented as aligned...).
It being a top crasher is worrying (even if Firefox can work around it, Firefox is not the only Rust application on Windows). That said, if this only impacts sandboxed processes it'd be less of a concern.
Would anyone be willing to report this to sandboxie?
I took a look and it looks like their issue tracker has template that seems pretty annoying to fill out. I think someone at Mozilla might have sufficient info to file the report, so I'm inclined to punt it to them. I haven't looked very closely but much of the code in doesn't seem to be handling alignment, which might be the issue. That said it might be something else, this is just from a really quick skim. This probably makes this issue a lot less high priority, if it's just a bug in the sandboxing library Firefox is using.
Sandboxie is not used by Firefox itself. That would be something random people install on their own.
(but indeed, there's a 100% correlation on the presence of (if you look at the correlations tab on the crash report))
Either way I think we should keep the alignment-insensitive code I've in , since I do believe it could happen for other similar kinds of things to sandboxie, or even buggy drivers. I think it's probably relatively low priority though, unless I'm misunderstanding the avenues with which this gets installed. IOW, I'm surprised if its just some random thing that enough users would have it to be a top crasher. Maybe it's artificially high because of people downloading the latest firefox nightly for automation and running things in a sandbox for automation purposes, perhaps? Who knows. (I suppose I don't really know what kind of volume "firefox nightly top crasher" implies, though)
It's also of Firefox beta crashes on Windows, FWIW.
Do those sandboxes intercept the calls as kernel drivers? Maybe microsoft could add some checks on their end to ensure that drivers uphold documented guarantees for userspace.
It's probably possible but tricky, I'm not an expert on windows kernel internals though, perhaps this isn't how it works. Even if it is possible, I don't think they'd do this though -- it would break programs relying on it not being checked, sadly...
Looks like this is filed upstream already, though with less information, so cross-linking them here:

Discussion:
use crate::os::windows::prelude::*; <ins> use crate::borrow::Cow; </ins> use crate::ffi::OsString; use crate::fmt; use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};

} } impl<'a> Iterator for DirBuffIter<'a> { <del> type Item = (&'a [u16], bool); </del> <ins> type Item = (Cow<'a, [u16]>, bool); </ins> fn next(&mut self) -> Option<Self::Item> { use crate::mem::size_of; let buffer = &self.buffer?[self.cursor..];

//   `FileNameLength` bytes) let (name, is_directory, next_entry) = unsafe { let info = buffer.as_ptr().cast::<c::FILE_ID_BOTH_DIR_INFO>(); <del> // Guaranteed to be aligned in documentation for </del> <ins> // While this is guaranteed to be aligned in documentation for </ins> // https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_id_both_dir_info <del> assert!(info.is_aligned()); let next_entry = (*info).NextEntryOffset as usize; let name = crate::slice::from_raw_parts( </del> <ins> // it does not seem that reality is so kind, and assuming this // caused crashes in some cases (https://github.com/rust-lang/rust/issues/104530) // presumably, this can be blamed on buggy filesystem drivers, but who knows. let next_entry = ptr::addr_of!((*info).NextEntryOffset).read_unaligned() as usize; let length = ptr::addr_of!((*info).FileNameLength).read_unaligned() as usize; let attrs = ptr::addr_of!((*info).FileAttributes).read_unaligned(); let name = from_maybe_unaligned( </ins> ptr::addr_of!((*info).FileName).cast::<u16>(), <del> (*info).FileNameLength as usize / size_of::<u16>(), </del> <ins> length / size_of::<u16>(), </ins> ); <del> let is_directory = ((*info).FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) != 0; </del> <ins> let is_directory = (attrs & c::FILE_ATTRIBUTE_DIRECTORY) != 0; </ins> (name, is_directory, next_entry) };

// Skip `.` and `..` pseudo entries. const DOT: u16 = b'.' as u16; <del> match name { </del> <ins> match &name[..] { </ins> [DOT] | [DOT, DOT] => self.next(), _ => Some((name, is_directory)), } } } <ins> unsafe fn from_maybe_unaligned<'a>(p: *const u16, len: usize) -> Cow<'a, [u16]> { if p.is_aligned() { Cow::Borrowed(crate::slice::from_raw_parts(p, len)) } else { Cow::Owned((0..len).map(|i| p.add(i).read_unaligned()).collect()) } } </ins> /// Open a link relative to the parent directory, ensure no symlinks are followed. fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result<File> { // This is implemented using the lower level `NtCreateFile` function as

if is_directory { let child_dir = open_link_no_reparse( &dir, <del> name, </del> <ins> &name, </ins> c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY, )?; dirlist.push(child_dir); } else { for i in 1..=MAX_RETRIES { <del> let result = open_link_no_reparse(&dir, name, c::SYNCHRONIZE | c::DELETE); </del> <ins> let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE); </ins> match result { Ok(f) => delete(&f)?, // Already deleted, so skip.