Skip to content

Commit 5cf1816

Browse files
author
Adrian Cole
committed
wasi: prohibits closing pre-opens
See WebAssembly/wasi-testsuite#50 Signed-off-by: Adrian Cole <[email protected]>
1 parent 67125fc commit 5cf1816

File tree

5 files changed

+54
-5
lines changed

5 files changed

+54
-5
lines changed

imports/wasi_snapshot_preview1/fs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var fdAllocate = stubFunction(
4848
//
4949
// The return value is ErrnoSuccess except the following error conditions:
5050
// - ErrnoBadf: the fd was not open.
51+
// - ErrnoNotsup: the fs was a pre-open
5152
//
5253
// Note: This is similar to `close` in POSIX.
5354
// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_close

imports/wasi_snapshot_preview1/fs_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ func Test_fdClose(t *testing.T) {
8080
require.Equal(t, `
8181
==> wasi_snapshot_preview1.fd_close(fd=42)
8282
<== errno=EBADF
83+
`, "\n"+log.String())
84+
})
85+
log.Reset()
86+
t.Run("ErrnoNotsup for a preopen", func(t *testing.T) {
87+
requireErrno(t, ErrnoNotsup, mod, FdCloseName, uint64(sys.FdPreopen))
88+
require.Equal(t, `
89+
==> wasi_snapshot_preview1.fd_close(fd=3)
90+
<== errno=ENOTSUP
8391
`, "\n"+log.String())
8492
})
8593
}

internal/sys/fs.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,15 +259,15 @@ func stdinReader(r io.Reader) *FileEntry {
259259
r = eofReader{}
260260
}
261261
s := stdioStat(r, noopStdinStat)
262-
return &FileEntry{IsPreopen: true, Name: noopStdinStat.Name(), File: &stdioFileReader{r: r, s: s}}
262+
return &FileEntry{Name: noopStdinStat.Name(), File: &stdioFileReader{r: r, s: s}}
263263
}
264264

265265
func stdioWriter(w io.Writer, defaultStat stdioFileInfo) *FileEntry {
266266
if w == nil {
267267
w = io.Discard
268268
}
269269
s := stdioStat(w, defaultStat)
270-
return &FileEntry{IsPreopen: true, Name: s.Name(), File: &stdioFileWriter{w: w, s: s}}
270+
return &FileEntry{Name: s.Name(), File: &stdioFileWriter{w: w, s: s}}
271271
}
272272

273273
func stdioStat(f interface{}, defaultStat stdioFileInfo) fs.FileInfo {
@@ -350,6 +350,10 @@ func (c *FSContext) CloseFile(fd uint32) error {
350350
f, ok := c.openedFiles.Lookup(fd)
351351
if !ok {
352352
return syscall.EBADF
353+
} else if f.IsPreopen {
354+
// WASI is the only user of pre-opens and wasi-testsuite disallows this
355+
// See https://github.com/WebAssembly/wasi-testsuite/issues/50
356+
return syscall.ENOTSUP
353357
}
354358
c.openedFiles.Delete(fd)
355359
return f.File.Close()

internal/sys/fs_test.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import (
2020
var testCtx = context.WithValue(context.Background(), struct{}{}, "arbitrary")
2121

2222
var (
23-
noopStdin = &FileEntry{IsPreopen: true, Name: "stdin", File: &stdioFileReader{r: eofReader{}, s: noopStdinStat}}
24-
noopStdout = &FileEntry{IsPreopen: true, Name: "stdout", File: &stdioFileWriter{w: io.Discard, s: noopStdoutStat}}
25-
noopStderr = &FileEntry{IsPreopen: true, Name: "stderr", File: &stdioFileWriter{w: io.Discard, s: noopStderrStat}}
23+
noopStdin = &FileEntry{Name: "stdin", File: &stdioFileReader{r: eofReader{}, s: noopStdinStat}}
24+
noopStdout = &FileEntry{Name: "stdout", File: &stdioFileWriter{w: io.Discard, s: noopStdoutStat}}
25+
noopStderr = &FileEntry{Name: "stderr", File: &stdioFileWriter{w: io.Discard, s: noopStderrStat}}
2626
)
2727

2828
//go:embed testdata
@@ -94,6 +94,40 @@ func TestNewFSContext(t *testing.T) {
9494
}
9595
}
9696

97+
func TestFSContext_CloseFile(t *testing.T) {
98+
embedFS, err := fs.Sub(testdata, "testdata")
99+
require.NoError(t, err)
100+
testFS := sysfs.Adapt(embedFS)
101+
102+
fsc, err := NewFSContext(nil, nil, nil, testFS)
103+
require.NoError(t, err)
104+
defer fsc.Close(testCtx)
105+
106+
fdToClose, err := fsc.OpenFile(testFS, "empty.txt", os.O_RDONLY, 0)
107+
require.NoError(t, err)
108+
109+
fdToKeep, err := fsc.OpenFile(testFS, "test.txt", os.O_RDONLY, 0)
110+
require.NoError(t, err)
111+
112+
// Close
113+
require.NoError(t, fsc.CloseFile(fdToClose))
114+
115+
// Verify fdToClose is closed and removed from the opened FDs.
116+
_, ok := fsc.LookupFile(fdToClose)
117+
require.False(t, ok)
118+
119+
// Verify fdToKeep is not closed
120+
_, ok = fsc.LookupFile(fdToKeep)
121+
require.True(t, ok)
122+
123+
t.Run("EBADF for an invalid FD", func(t *testing.T) {
124+
require.Equal(t, syscall.EBADF, fsc.CloseFile(42)) // 42 is an arbitrary invalid FD
125+
})
126+
t.Run("ENOTSUP for a preopen", func(t *testing.T) {
127+
require.Equal(t, syscall.ENOTSUP, fsc.CloseFile(FdPreopen)) // 42 is an arbitrary invalid FD
128+
})
129+
}
130+
97131
func TestUnimplementedFSContext(t *testing.T) {
98132
testFS, err := NewFSContext(nil, nil, nil, sysfs.UnimplementedFS{})
99133
require.NoError(t, err)

internal/wasi_snapshot_preview1/errno.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ func ToErrno(err error) Errno {
281281
return ErrnoNoent
282282
case errors.Is(err, syscall.ENOSYS):
283283
return ErrnoNosys
284+
case errors.Is(err, syscall.ENOTSUP):
285+
return ErrnoNotsup
284286
case errors.Is(err, syscall.ENOTDIR):
285287
return ErrnoNotdir
286288
case errors.Is(err, syscall.EPERM), errors.Is(err, fs.ErrPermission):

0 commit comments

Comments
 (0)