Fix WASI fd_readdir on big-endian (#3016)

This code assumes that the Dirent structure has the same memory
layout on the host (Rust code) as in wasm code.  This is not true
if the host is big-endian, as wasm is always little-endian.

Fixed by always byte-swapping Dirent fields to little-endian
before passing them on to wasm code.
This commit is contained in:
Ulrich Weigand
2021-06-22 17:39:38 +02:00
committed by GitHub
parent acdb388580
commit 1a865fb0f5

View File

@@ -1548,13 +1548,24 @@ fn dirent_bytes(dirent: types::Dirent) -> Vec<u8> {
std::mem::size_of::<types::Dirent>() as _, std::mem::size_of::<types::Dirent>() as _,
"Dirent guest repr and host repr should match" "Dirent guest repr and host repr should match"
); );
assert_eq!(
1,
std::mem::size_of_val(&dirent.d_type),
"Dirent member d_type should be endian-invariant"
);
let size = types::Dirent::guest_size() let size = types::Dirent::guest_size()
.try_into() .try_into()
.expect("Dirent is smaller than 2^32"); .expect("Dirent is smaller than 2^32");
let mut bytes = Vec::with_capacity(size); let mut bytes = Vec::with_capacity(size);
bytes.resize(size, 0); bytes.resize(size, 0);
let ptr = bytes.as_mut_ptr() as *mut types::Dirent; let ptr = bytes.as_mut_ptr() as *mut types::Dirent;
unsafe { ptr.write_unaligned(dirent) }; let guest_dirent = types::Dirent {
d_ino: dirent.d_ino.to_le(),
d_namlen: dirent.d_namlen.to_le(),
d_type: dirent.d_type, // endian-invariant
d_next: dirent.d_next.to_le(),
};
unsafe { ptr.write_unaligned(guest_dirent) };
bytes bytes
} }