Skip to content

Commit a8fbe46

Browse files
authored
fix: allow access to '..' in mapfs (#7575)
Signed-off-by: nikpivkin <[email protected]>
1 parent 13ef3e7 commit a8fbe46

File tree

4 files changed

+31
-4
lines changed

4 files changed

+31
-4
lines changed

pkg/mapfs/fs.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func (m *FS) CopyFilesUnder(dir string) error {
123123

124124
// Stat returns a FileInfo describing the file.
125125
func (m *FS) Stat(name string) (fs.FileInfo, error) {
126-
if strings.HasPrefix(name, "../") && m.underlyingRoot != "" {
126+
if m.isPathAboveRoot(name) {
127127
return os.Stat(filepath.Join(m.underlyingRoot, name))
128128
}
129129

@@ -145,15 +145,15 @@ func (m *FS) Stat(name string) (fs.FileInfo, error) {
145145
// ReadDir reads the named directory
146146
// and returns a list of directory entries sorted by filename.
147147
func (m *FS) ReadDir(name string) ([]fs.DirEntry, error) {
148-
if strings.HasPrefix(name, "../") && m.underlyingRoot != "" {
148+
if m.isPathAboveRoot(name) {
149149
return os.ReadDir(filepath.Join(m.underlyingRoot, name))
150150
}
151151
return m.root.ReadDir(cleanPath(name))
152152
}
153153

154154
// Open opens the named file for reading.
155155
func (m *FS) Open(name string) (fs.File, error) {
156-
if strings.HasPrefix(name, "../") && m.underlyingRoot != "" {
156+
if m.isPathAboveRoot(name) {
157157
return os.Open(filepath.Join(m.underlyingRoot, name))
158158
}
159159
return m.root.Open(cleanPath(name))
@@ -188,7 +188,7 @@ func (m *FS) MkdirAll(path string, perm fs.FileMode) error {
188188
// The caller is permitted to modify the returned byte slice.
189189
// This method should return a copy of the underlying data.
190190
func (m *FS) ReadFile(name string) ([]byte, error) {
191-
if strings.HasPrefix(name, "../") && m.underlyingRoot != "" {
191+
if m.isPathAboveRoot(name) {
192192
return os.ReadFile(filepath.Join(m.underlyingRoot, name))
193193
}
194194

@@ -245,3 +245,7 @@ func cleanPath(path string) string {
245245
path = strings.TrimLeft(path, "/") // Remove the leading slash
246246
return path
247247
}
248+
249+
func (m *FS) isPathAboveRoot(name string) bool {
250+
return (name == ".." || strings.HasPrefix(name, "../")) && m.underlyingRoot != ""
251+
}

pkg/mapfs/fs_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -478,3 +478,26 @@ func TestFS_RemoveAll(t *testing.T) {
478478
require.ErrorIs(t, err, fs.ErrNotExist)
479479
})
480480
}
481+
482+
func TestFS_WithUnderlyingRoot(t *testing.T) {
483+
root := "testdata/subdir"
484+
fsys := mapfs.New(mapfs.WithUnderlyingRoot(root))
485+
require.NoError(t, fsys.WriteFile("foo.txt", root+"/foo.txt"))
486+
require.NoError(t, fsys.WriteFile("..foo.txt", root+"/..foo.txt"))
487+
488+
fi, err := fsys.Stat("..")
489+
require.NoError(t, err)
490+
assert.True(t, fi.IsDir())
491+
492+
fi, err = fsys.Stat("../hello.txt")
493+
require.NoError(t, err)
494+
assert.False(t, fi.IsDir())
495+
496+
fi, err = fsys.Stat("foo.txt")
497+
require.NoError(t, err)
498+
assert.False(t, fi.IsDir())
499+
500+
fi, err = fsys.Stat("..foo.txt")
501+
require.NoError(t, err)
502+
assert.False(t, fi.IsDir())
503+
}

pkg/mapfs/testdata/subdir/..foo.txt

Whitespace-only changes.

pkg/mapfs/testdata/subdir/foo.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)