From f4711e4db9e9a1d3887343acb72b2bbfc2f686f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 29 Jan 2019 22:50:16 +0100 Subject: [PATCH] Fix missing bounds checking in UnionFile.Readdir It will now return io.EOF at the end of the directory view. Fixes #194 --- composite_test.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++ unionFile.go | 11 ++++++++ 2 files changed, 81 insertions(+) diff --git a/composite_test.go b/composite_test.go index 2a20440e..eb4a104e 100644 --- a/composite_test.go +++ b/composite_test.go @@ -3,6 +3,7 @@ package afero import ( "bytes" "fmt" + "io" "io/ioutil" "os" "testing" @@ -401,3 +402,72 @@ func TestCacheOnReadFsNotInLayer(t *testing.T) { } fh.Close() } + +// #194 +func TestUniontFileReaddirEmpty(t *testing.T) { + osFs := NewOsFs() + + base := NewMemMapFs() + overlay := NewMemMapFs() + ufs := &CopyOnWriteFs{base: base, layer: overlay} + mem := NewMemMapFs() + + // The OS file will return io.EOF on end of directory. + for _, fs := range []Fs{osFs, ufs, mem} { + baseDir, err := TempDir(fs, "", "empty-dir") + if err != nil { + t.Fatal(err) + } + + f, err := fs.Open(baseDir) + if err != nil { + t.Fatal(err) + } + + names, err := f.Readdirnames(1) + if err != io.EOF { + t.Fatal(err) + } + + if len(names) != 0 { + t.Fatal("should be empty") + } + + f.Close() + + fs.RemoveAll(baseDir) + } +} + +func TestUniontFileReaddirAskForTooMany(t *testing.T) { + base := &MemMapFs{} + overlay := &MemMapFs{} + + for i := 0; i < 5; i++ { + WriteFile(base, fmt.Sprintf("file%d.txt", i), []byte("afero"), 0777) + } + + ufs := &CopyOnWriteFs{base: base, layer: overlay} + + f, err := ufs.Open("") + if err != nil { + t.Fatal(err) + } + + defer f.Close() + + names, err := f.Readdirnames(6) + if err != nil { + t.Fatal(err) + } + + if len(names) != 5 { + t.Fatal(names) + } + + // End of directory + _, err = f.Readdirnames(3) + if err != io.EOF { + t.Fatal(err) + } +} diff --git a/unionFile.go b/unionFile.go index 1e78f7d1..abcf12d3 100644 --- a/unionFile.go +++ b/unionFile.go @@ -156,6 +156,7 @@ var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, err // Readdir will weave the two directories together and // return a single view of the overlayed directories +// At the end of the directory view, the error is io.EOF. func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { var merge DirsMerger = f.Merger if merge == nil { @@ -185,9 +186,19 @@ func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { } f.files = append(f.files, merged...) } + + if f.off >= len(f.files) { + return nil, io.EOF + } + if c == -1 { return f.files[f.off:], nil } + + if c > len(f.files) { + c = len(f.files) + } + defer func() { f.off += c }() return f.files[f.off:c], nil }