From 5df6ce6f54a9f4edb472ab829d11bf10eb7eece1 Mon Sep 17 00:00:00 2001 From: Yage Hu Date: Mon, 11 Dec 2023 20:37:30 -0800 Subject: [PATCH] Fix `fd_fdstat_set_flags` truncating with O_TRUNC This commit fixes a buf when `fd_fdstat_set_flags` would erroneously truncate an open file if it is opened with the O_TRUNC flag. This happens because the O_TRUNC flag causes the file to be truncated when it is opened. Signed-off-by: Yage Hu --- imports/wasi_snapshot_preview1/fs_test.go | 36 +++++++++++++++++++++++ internal/sysfs/osfile.go | 3 ++ 2 files changed, 39 insertions(+) diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go index fc23e897536..1ef0f7e0a9c 100644 --- a/imports/wasi_snapshot_preview1/fs_test.go +++ b/imports/wasi_snapshot_preview1/fs_test.go @@ -480,6 +480,42 @@ func Test_fdFdstatGet_StdioNonblock(t *testing.T) { } } +func Test_fdFdstatSetFlagsWithTrunc(t *testing.T) { + tmpDir := t.TempDir() + fileName := "test" + + mod, r, log := requireProxyModule(t, wazero.NewModuleConfig(). + WithFSConfig(wazero.NewFSConfig().WithDirMount(tmpDir, "/"))) + defer r.Close(testCtx) + + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + preopen := fsc.RootFS() + + fd, errno := fsc.OpenFile(preopen, fileName, experimentalsys.O_RDWR|experimentalsys.O_CREAT|experimentalsys.O_EXCL|experimentalsys.O_TRUNC, 0o600) + require.EqualErrno(t, 0, errno) + + // Write the initial text to the file. + f, ok := fsc.LookupFile(fd) + require.True(t, ok) + n, errno := f.File.Write([]byte("abc")) + require.Equal(t, n, 3) + + buf, err := os.ReadFile(joinPath(tmpDir, fileName)) + require.NoError(t, err) + require.Equal(t, "abc", string(buf)) + + requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdFdstatSetFlagsName, uint64(fd), uint64(0)) + require.Equal(t, ` +==> wasi_snapshot_preview1.fd_fdstat_set_flags(fd=4,flags=) +<== errno=ESUCCESS +`, "\n"+log.String()) + log.Reset() + + buf, err = os.ReadFile(joinPath(tmpDir, fileName)) + require.NoError(t, err) + require.Equal(t, "abc", string(buf)) +} + func Test_fdFdstatSetFlags(t *testing.T) { tmpDir := t.TempDir() // open before loop to ensure no locking problems. diff --git a/internal/sysfs/osfile.go b/internal/sysfs/osfile.go index 13bd418f242..40df119a009 100644 --- a/internal/sysfs/osfile.go +++ b/internal/sysfs/osfile.go @@ -86,6 +86,9 @@ func (f *osFile) SetAppend(enable bool) (errno experimentalsys.Errno) { // Clear any create flag, as we are re-opening, not re-creating. f.flag &= ^experimentalsys.O_CREAT + // Clear trunc flag, as we are re-opening. + f.flag &= ^experimentalsys.O_TRUNC + // appendMode (bool) cannot be changed later, so we have to re-open the // file. https://github.com/golang/go/blob/go1.20/src/os/file_unix.go#L60 return fileError(f, f.closed, f.reopen())