diff --git a/crates/wasi-c2/cap-std-sync/src/file.rs b/crates/wasi-c2/cap-std-sync/src/file.rs index 0672455a33..00a43dd3eb 100644 --- a/crates/wasi-c2/cap-std-sync/src/file.rs +++ b/crates/wasi-c2/cap-std-sync/src/file.rs @@ -38,7 +38,7 @@ impl WasiFile for File { // XXX get_fdflags is not implemented but lets lie rather than panic: Ok(FdFlags::empty()) } - fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { + unsafe fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { todo!("reopen_with_fdflags is not implemented") } fn get_filestat(&self) -> Result { diff --git a/crates/wasi-c2/cap-std-sync/src/stdio.rs b/crates/wasi-c2/cap-std-sync/src/stdio.rs index 4847c40c68..13026e5b70 100644 --- a/crates/wasi-c2/cap-std-sync/src/stdio.rs +++ b/crates/wasi-c2/cap-std-sync/src/stdio.rs @@ -39,7 +39,7 @@ impl WasiFile for Stdin { // XXX get_fdflags is not implemented but lets lie rather than panic: Ok(FdFlags::empty()) } - fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { + unsafe fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { Err(Error::Badf) } fn get_filestat(&self) -> Result { @@ -128,7 +128,10 @@ macro_rules! wasi_file_write_impl { // XXX get_fdflags is not implemented but lets lie rather than panic: Ok(FdFlags::empty()) } - fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { + unsafe fn reopen_with_fdflags( + &self, + _fdflags: FdFlags, + ) -> Result, Error> { Err(Error::Badf) } fn get_filestat(&self) -> Result { diff --git a/crates/wasi-c2/src/file.rs b/crates/wasi-c2/src/file.rs index 3db073e096..a034d09770 100644 --- a/crates/wasi-c2/src/file.rs +++ b/crates/wasi-c2/src/file.rs @@ -10,7 +10,9 @@ pub trait WasiFile { fn sync(&self) -> Result<(), Error>; // file op fn get_filetype(&self) -> Result; // file op fn get_fdflags(&self) -> Result; // file op - fn reopen_with_fdflags(&self, flags: FdFlags) -> Result, Error>; // file op + /// This method takes a `&self` so that it can be called on a `&dyn WasiFile`. However, + /// the caller makes the additional guarantee to drop `self` after the call is successful. + unsafe fn reopen_with_fdflags(&self, flags: FdFlags) -> Result, Error>; // file op fn get_filestat(&self) -> Result; // split out get_length as a read & write op, rest is a file op fn set_filestat_size(&self, _size: u64) -> Result<(), Error>; // write op fn advise( diff --git a/crates/wasi-c2/src/pipe.rs b/crates/wasi-c2/src/pipe.rs index f83e24c992..f434e8fb0b 100644 --- a/crates/wasi-c2/src/pipe.rs +++ b/crates/wasi-c2/src/pipe.rs @@ -114,7 +114,7 @@ impl WasiFile for ReadPipe { fn get_fdflags(&self) -> Result { Ok(FdFlags::empty()) } - fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { + unsafe fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { Err(Error::Badf) } fn get_filestat(&self) -> Result { @@ -250,7 +250,7 @@ impl WasiFile for WritePipe { fn get_fdflags(&self) -> Result { Ok(FdFlags::APPEND) } - fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { + unsafe fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result, Error> { Err(Error::Badf) } fn get_filestat(&self) -> Result { diff --git a/crates/wasi-c2/src/snapshots/preview_1.rs b/crates/wasi-c2/src/snapshots/preview_1.rs index e01de4f220..d5bd655713 100644 --- a/crates/wasi-c2/src/snapshots/preview_1.rs +++ b/crates/wasi-c2/src/snapshots/preview_1.rs @@ -276,7 +276,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let fd = u32::from(fd); let table_check = table.get_file(fd)?.get_cap(FileCaps::FDSTAT_SET_FLAGS)?; drop(table_check); - table.update_file_in_place(fd, |f| f.reopen_with_fdflags(FdFlags::from(&flags))) + table.update_file_in_place(fd, |f| unsafe { + // Safety: update_file_in_place will drop `f` after this call. + f.reopen_with_fdflags(FdFlags::from(&flags)) + }) } fn fd_fdstat_set_rights(