Skip to content

Commit f8f4c40

Browse files
committed
fs: Don't copy d_name from struct dirent
The dirent returned from readdir() is only guaranteed to be valid for d_reclen bytes on common platforms. Since we copy the name separately anyway, we can copy everything except d_name into DirEntry::entry. Fixes #93384.
1 parent ca43894 commit f8f4c40

File tree

1 file changed

+10
-2
lines changed
  • library/std/src/sys/unix

1 file changed

+10
-2
lines changed

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -489,10 +489,18 @@ impl Iterator for ReadDir {
489489
};
490490
}
491491

492+
// Only d_reclen bytes of *entry_ptr are valid, so we can't just copy the
493+
// whole thing (#93384). Instead, copy everything except the name.
494+
let entry_bytes = entry_ptr as *const u8;
495+
let entry_name = ptr::addr_of!((*entry_ptr).d_name) as *const u8;
496+
let name_offset = entry_name.offset_from(entry_bytes) as usize;
497+
let mut entry: dirent64 = mem::zeroed();
498+
ptr::copy_nonoverlapping(entry_bytes, &mut entry as *mut _ as *mut u8, name_offset);
499+
492500
let ret = DirEntry {
493-
entry: *entry_ptr,
501+
entry,
494502
// d_name is guaranteed to be null-terminated.
495-
name: CStr::from_ptr((*entry_ptr).d_name.as_ptr()).to_owned(),
503+
name: CStr::from_ptr(entry_name as *const _).to_owned(),
496504
dir: Arc::clone(&self.inner),
497505
};
498506
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {

0 commit comments

Comments
 (0)