From ae1c52a23871c317364bbfce6dcab2d4c88e8b22 Mon Sep 17 00:00:00 2001 From: Nick Pillitteri <56quarters@users.noreply.github.com> Date: Tue, 31 Jan 2023 06:26:56 -0500 Subject: [PATCH] Add defensive copy of objects in InMemBucket (#42) Add locking and return a copy of the internally stored objects in InMemBucket. This fixes a race condition that can be triggered if the result of `.Objects()` is read while another goroutine modifies the objects (such as uploading a new file). Noticed in grafana/mimir#4021 Signed-off-by: Nick Pillitteri Co-authored-by: Matej Gera <38492574+matej-g@users.noreply.github.com> --- inmem.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/inmem.go b/inmem.go index 1b0a6439..ac36e7f4 100644 --- a/inmem.go +++ b/inmem.go @@ -34,10 +34,18 @@ func NewInMemBucket() *InMemBucket { } } -// Objects returns internally stored objects. +// Objects returns a copy of the internally stored objects. // NOTE: For assert purposes. func (b *InMemBucket) Objects() map[string][]byte { - return b.objects + b.mtx.RLock() + defer b.mtx.RUnlock() + + objs := make(map[string][]byte) + for k, v := range b.objects { + objs[k] = v + } + + return objs } // Iter calls f for each entry in the given directory. The argument to f is the full