From e9d0393809be173a2b28cb1a60b306468464c7fb Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Mon, 25 Feb 2019 11:42:09 +0100 Subject: [PATCH] plumbing/cache: check for empty cache list If there is wrong data in the cache it may cause the eviction code to empty the object list and cause a panic. This patch adds a check and sets the cache usage to 0 when this happens. Signed-off-by: Javi Fontan --- plumbing/cache/object_lru.go | 5 +++++ plumbing/cache/object_test.go | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/plumbing/cache/object_lru.go b/plumbing/cache/object_lru.go index 53d8b02d9..cd3712b7d 100644 --- a/plumbing/cache/object_lru.go +++ b/plumbing/cache/object_lru.go @@ -61,6 +61,11 @@ func (c *ObjectLRU) Put(obj plumbing.EncodedObject) { c.actualSize += objSize for c.actualSize > c.MaxSize { last := c.ll.Back() + if last == nil { + c.actualSize = 0 + break + } + lastObj := last.Value.(plumbing.EncodedObject) lastSize := FileSize(lastObj.Size()) diff --git a/plumbing/cache/object_test.go b/plumbing/cache/object_test.go index b3e5f7972..2e8fa7bc6 100644 --- a/plumbing/cache/object_test.go +++ b/plumbing/cache/object_test.go @@ -153,6 +153,19 @@ func (s *ObjectSuite) TestDefaultLRU(c *C) { c.Assert(defaultLRU.MaxSize, Equals, DefaultMaxSize) } +func (s *ObjectSuite) TestObjectUpdateOverflow(c *C) { + o := NewObjectLRU(9 * Byte) + + a1 := newObject(s.aObject.Hash().String(), 9*Byte) + a2 := newObject(s.aObject.Hash().String(), 1*Byte) + b := newObject(s.bObject.Hash().String(), 1*Byte) + + o.Put(a1) + a1.SetSize(-5) + o.Put(a2) + o.Put(b) +} + type dummyObject struct { hash plumbing.Hash size FileSize @@ -169,6 +182,6 @@ func (d *dummyObject) Hash() plumbing.Hash { return d.hash } func (*dummyObject) Type() plumbing.ObjectType { return plumbing.InvalidObject } func (*dummyObject) SetType(plumbing.ObjectType) {} func (d *dummyObject) Size() int64 { return int64(d.size) } -func (*dummyObject) SetSize(s int64) {} +func (d *dummyObject) SetSize(s int64) { d.size = FileSize(s) } func (*dummyObject) Reader() (io.ReadCloser, error) { return nil, nil } func (*dummyObject) Writer() (io.WriteCloser, error) { return nil, nil }