From 99108a1c63ab57fb29428d03910bd0fb3b56000c Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Sun, 12 Jan 2020 11:46:29 -0600 Subject: [PATCH] bit remove leaves internals corrupt on empty edge case --- fragment_internal_test.go | 44 +++++++++++++++++++++++++++++++++++++++ roaring/roaring.go | 6 +++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/fragment_internal_test.go b/fragment_internal_test.go index f101443ca..dd57635d2 100644 --- a/fragment_internal_test.go +++ b/fragment_internal_test.go @@ -3576,3 +3576,47 @@ func TestFragmentConcurrentReadWrite(t *testing.T) { t.Logf("%d", acc) } + +func TestFragment_Bug_Q2DoubleDelete(t *testing.T) { + f := mustOpenFragment("i", "f", viewStandard, 0, "") + b := []byte{60, 48, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 24, 0, 0, 0, 1, 0} + defer f.Clean(t) + err := f.importRoaringT(b, false) + if err != nil { + t.Fatalf("importing roaring: %v", err) + } + //check the bit + res := f.row(1).Columns() + if len(res) < 1 || f.row(1).Columns()[0] != 1 { + t.Fatalf("expecting 1 got: %v", res) + } + //clear the bit + changed, _ := f.clearBit(1, 1) + if !changed { + t.Fatalf("expected change got %v", changed) + } + //check missing + res = f.row(1).Columns() + if len(res) != 0 { + t.Fatalf("expected nothing got %v", res) + } + // import again + err = f.importRoaringT(b, false) + if err != nil { + t.Fatalf("importing roaring: %v", err) + } + //check + res = f.row(1).Columns() + if len(res) < 1 || f.row(1).Columns()[0] != 1 { + t.Fatalf("again expecting 1 got: %v", res) + } + changed, _ = f.clearBit(1, 1) + if !changed { + t.Fatalf("again expected change got %v", changed) + } + //check missing + res = f.row(1).Columns() + if len(res) != 0 { + t.Fatalf("expected nothing got %v", res) + } +} diff --git a/roaring/roaring.go b/roaring/roaring.go index bb0479f8f..19a671dbf 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -422,7 +422,11 @@ func (b *Bitmap) remove(v uint64) bool { c := b.Containers.Get(highbits(v)) newC, changed := c.remove(lowbits(v)) if newC != c { - b.Containers.Put(highbits(v), newC) + if newC != nil { + b.Containers.Put(highbits(v), newC) + } else { + b.Containers.Remove(highbits(v)) + } } return changed }