Ensure nil is accepted as FS config (#1182)

In previous releases, passing a `nil` value as an FS config
did not cause any error. However, in 1.0.0-rc.1 this leads
to the creation of an invalid `adapter{fs: nil}`, which
eventually leads to a panic (nil):

    (f *FileEntry) Stat(st *platform.Stat_t) =>
        (r *lazyDir) file() =>
            r.fs.OpenFile(".", os.O_RDONLY, 0)

with fs == nil

The backwards-compatible fix is to make Adapt()
return UnimplementedFS, and ensuring `nil` is a valid value
that config is able to handle.

However, we may want to consider returning an error somewhere,
because configuring a nil FS may be unintended.

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
This commit is contained in:
Edoardo Vacchi
2023-03-03 03:01:31 +01:00
committed by GitHub
parent 4043d58287
commit f36d30b82d
5 changed files with 37 additions and 1 deletions

View File

@@ -667,7 +667,11 @@ func (c *moduleConfig) WithEnv(key, value string) ModuleConfig {
// WithFS implements ModuleConfig.WithFS // WithFS implements ModuleConfig.WithFS
func (c *moduleConfig) WithFS(fs fs.FS) ModuleConfig { func (c *moduleConfig) WithFS(fs fs.FS) ModuleConfig {
return c.WithFSConfig(NewFSConfig().WithFSMount(fs, "")) var config FSConfig
if fs != nil {
config = NewFSConfig().WithFSMount(fs, "")
}
return c.WithFSConfig(config)
} }
// WithFSConfig implements ModuleConfig.WithFSConfig // WithFSConfig implements ModuleConfig.WithFSConfig

View File

@@ -360,6 +360,24 @@ func TestModuleConfig_toSysContext(t *testing.T) {
sysfs.Adapt(testFS2), // fs sysfs.Adapt(testFS2), // fs
), ),
}, },
{
name: "WithFS nil",
input: base.WithFS(nil),
expected: requireSysContext(t,
math.MaxUint32, // max
nil, // args
nil, // environ
nil, // stdin
nil, // stdout
nil, // stderr
nil, // randSource
&wt, 1, // walltime, walltimeResolution
&nt, 1, // nanotime, nanotimeResolution
nil, // nanosleep
nil, // osyield
nil, // fs
),
},
{ {
name: "WithRandSource", name: "WithRandSource",
input: base.WithRandSource(rand.Reader), input: base.WithRandSource(rand.Reader),

View File

@@ -35,6 +35,11 @@ func TestFSConfig(t *testing.T) {
input: base.WithFSMount(testFS, "/").WithFSMount(testFS2, "/"), input: base.WithFSMount(testFS, "/").WithFSMount(testFS2, "/"),
expected: sysfs.Adapt(testFS2), expected: sysfs.Adapt(testFS2),
}, },
{
name: "WithFsMount nil",
input: base.WithFSMount(nil, "/"),
expected: sysfs.UnimplementedFS{},
},
{ {
name: "WithDirMount overwrites", name: "WithDirMount overwrites",
input: base.WithFSMount(testFS, "/").WithDirMount(".", "/"), input: base.WithFSMount(testFS, "/").WithDirMount(".", "/"),

View File

@@ -19,6 +19,9 @@ import (
// documentation does not require the file to be present. In summary, we can't // documentation does not require the file to be present. In summary, we can't
// enforce flag behavior. // enforce flag behavior.
func Adapt(fs fs.FS) FS { func Adapt(fs fs.FS) FS {
if fs == nil {
return UnimplementedFS{}
}
if sys, ok := fs.(FS); ok { if sys, ok := fs.(FS); ok {
return sys return sys
} }

View File

@@ -14,6 +14,12 @@ import (
"github.com/tetratelabs/wazero/internal/testing/require" "github.com/tetratelabs/wazero/internal/testing/require"
) )
func TestAdapt_nil(t *testing.T) {
testFS := Adapt(nil)
_, ok := testFS.(UnimplementedFS)
require.True(t, ok)
}
func TestAdapt_String(t *testing.T) { func TestAdapt_String(t *testing.T) {
testFS := Adapt(os.DirFS(".")) testFS := Adapt(os.DirFS("."))
require.Equal(t, ".", testFS.String()) require.Equal(t, ".", testFS.String())