diff --git a/memfs/memory_test.go b/memfs/memory_test.go index 4f15909..be278a2 100644 --- a/memfs/memory_test.go +++ b/memfs/memory_test.go @@ -1,6 +1,7 @@ package memfs import ( + "io" "testing" "gopkg.in/src-d/go-billy.v4" @@ -29,3 +30,17 @@ func (s *MemorySuite) TestCapabilities(c *C) { caps := billy.Capabilities(s.FS) c.Assert(caps, Equals, billy.DefaultCapabilities&^billy.LockCapability) } + +func (s *MemorySuite) TestNegativeOffsets(c *C) { + f, err := s.FS.Create("negative") + c.Assert(err, IsNil) + + buf := make([]byte, 100) + _, err = f.ReadAt(buf, -100) + c.Assert(err, ErrorMatches, "readat negative: negative offset") + + _, err = f.Seek(-100, io.SeekCurrent) + c.Assert(err, IsNil) + _, err = f.Write(buf) + c.Assert(err, ErrorMatches, "writeat negative: negative offset") +} diff --git a/memfs/storage.go b/memfs/storage.go index 354c512..d3ff5a2 100644 --- a/memfs/storage.go +++ b/memfs/storage.go @@ -1,6 +1,7 @@ package memfs import ( + "errors" "fmt" "io" "os" @@ -36,9 +37,11 @@ func (s *storage) New(path string, mode os.FileMode, flag int) (*file, error) { return nil, nil } + name := filepath.Base(path) + f := &file{ - name: filepath.Base(path), - content: &content{}, + name: name, + content: &content{name: name}, mode: mode, flag: flag, } @@ -169,10 +172,19 @@ func clean(path string) string { } type content struct { + name string bytes []byte } func (c *content) WriteAt(p []byte, off int64) (int, error) { + if off < 0 { + return 0, &os.PathError{ + Op: "writeat", + Path: c.name, + Err: errors.New("negative offset"), + } + } + prev := len(c.bytes) diff := int(off) - prev @@ -189,6 +201,14 @@ func (c *content) WriteAt(p []byte, off int64) (int, error) { } func (c *content) ReadAt(b []byte, off int64) (n int, err error) { + if off < 0 { + return 0, &os.PathError{ + Op: "readat", + Path: c.name, + Err: errors.New("negative offset"), + } + } + size := int64(len(c.bytes)) if off >= size { return 0, io.EOF