From 0be081b3ff6aa0077d6f320461c3885832094387 Mon Sep 17 00:00:00 2001
From: Tristan Su <sooqing@gmail.com>
Date: Mon, 9 Nov 2020 14:01:55 +0800
Subject: [PATCH] fix(tsi): close series id iterator after merging

This use-after-free bug may lead to segfault. The iterators that have
reference to the underlying index files were closed too early while
the bitmaps were still used afterwards. If a compaction occurs
concurrently and removes the index files, it would result in accessing
unmap'd memory address.
---
 tsdb/index.go | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/tsdb/index.go b/tsdb/index.go
index f5c5f823b49..f760f767051 100644
--- a/tsdb/index.go
+++ b/tsdb/index.go
@@ -557,9 +557,10 @@ func IntersectSeriesIDIterators(itr0, itr1 SeriesIDIterator) SeriesIDIterator {
 
 	// Create series id set, if available.
 	if a := NewSeriesIDSetIterators([]SeriesIDIterator{itr0, itr1}); a != nil {
+		ss := a[0].SeriesIDSet().And(a[1].SeriesIDSet())
 		itr0.Close()
 		itr1.Close()
-		return NewSeriesIDSetIterator(a[0].SeriesIDSet().And(a[1].SeriesIDSet()))
+		return NewSeriesIDSetIterator(ss)
 	}
 
 	return &seriesIDIntersectIterator{itrs: [2]SeriesIDIterator{itr0, itr1}}
@@ -646,10 +647,10 @@ func UnionSeriesIDIterators(itr0, itr1 SeriesIDIterator) SeriesIDIterator {
 
 	// Create series id set, if available.
 	if a := NewSeriesIDSetIterators([]SeriesIDIterator{itr0, itr1}); a != nil {
-		itr0.Close()
-		itr1.Close()
 		ss := NewSeriesIDSet()
 		ss.Merge(a[0].SeriesIDSet(), a[1].SeriesIDSet())
+		itr0.Close()
+		itr1.Close()
 		return NewSeriesIDSetIterator(ss)
 	}
 
@@ -733,9 +734,10 @@ func DifferenceSeriesIDIterators(itr0, itr1 SeriesIDIterator) SeriesIDIterator {
 
 	// Create series id set, if available.
 	if a := NewSeriesIDSetIterators([]SeriesIDIterator{itr0, itr1}); a != nil {
+		ss := a[0].SeriesIDSet().AndNot(a[1].SeriesIDSet())
 		itr0.Close()
 		itr1.Close()
-		return NewSeriesIDSetIterator(a[0].SeriesIDSet().AndNot(a[1].SeriesIDSet()))
+		return NewSeriesIDSetIterator(ss)
 	}
 
 	return &seriesIDDifferenceIterator{itrs: [2]SeriesIDIterator{itr0, itr1}}