Skip to content

Commit

Permalink
fs: Don't copy d_name from struct dirent
Browse files Browse the repository at this point in the history
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 rust-lang#93384.
  • Loading branch information
tavianator committed Jan 29, 2022
1 parent ca43894 commit f8f4c40
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions library/std/src/sys/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,10 +489,18 @@ impl Iterator for ReadDir {
};
}

// Only d_reclen bytes of *entry_ptr are valid, so we can't just copy the
// whole thing (#93384). Instead, copy everything except the name.
let entry_bytes = entry_ptr as *const u8;
let entry_name = ptr::addr_of!((*entry_ptr).d_name) as *const u8;
let name_offset = entry_name.offset_from(entry_bytes) as usize;
let mut entry: dirent64 = mem::zeroed();
ptr::copy_nonoverlapping(entry_bytes, &mut entry as *mut _ as *mut u8, name_offset);

let ret = DirEntry {
entry: *entry_ptr,
entry,
// d_name is guaranteed to be null-terminated.
name: CStr::from_ptr((*entry_ptr).d_name.as_ptr()).to_owned(),
name: CStr::from_ptr(entry_name as *const _).to_owned(),
dir: Arc::clone(&self.inner),
};
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
Expand Down

0 comments on commit f8f4c40

Please sign in to comment.