Fix missing bounds checking in UnionFile.Readdir

It will now return io.EOF at the end of the directory view.

Fixes #194
This commit is contained in:
Bjørn Erik Pedersen 2019-01-29 22:50:16 +01:00
parent a5d6946387
commit f4711e4db9
2 changed files with 81 additions and 0 deletions

View File

@ -3,6 +3,7 @@ package afero
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
@ -401,3 +402,72 @@ func TestCacheOnReadFsNotInLayer(t *testing.T) {
} }
fh.Close() 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)
}
}

View File

@ -156,6 +156,7 @@ var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, err
// Readdir will weave the two directories together and // Readdir will weave the two directories together and
// return a single view of the overlayed directories // 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) { func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
var merge DirsMerger = f.Merger var merge DirsMerger = f.Merger
if merge == nil { if merge == nil {
@ -185,9 +186,19 @@ func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
} }
f.files = append(f.files, merged...) f.files = append(f.files, merged...)
} }
if f.off >= len(f.files) {
return nil, io.EOF
}
if c == -1 { if c == -1 {
return f.files[f.off:], nil return f.files[f.off:], nil
} }
if c > len(f.files) {
c = len(f.files)
}
defer func() { f.off += c }() defer func() { f.off += c }()
return f.files[f.off:c], nil return f.files[f.off:c], nil
} }