From 50d31a3c830db47f253d832f0f292c935176eea3 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Fri, 10 Nov 2017 12:44:25 -0600 Subject: [PATCH 1/3] fix overflow in differenceRunBitmap --- roaring/roaring.go | 5 ++++- roaring/roaring_internal_test.go | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/roaring/roaring.go b/roaring/roaring.go index 62f87d94b..e4d75a0d2 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -2508,7 +2508,7 @@ func differenceRunArray(a, b *container) *container { // differenceRunBitmap computes the difference of an run from a bitmap. func differenceRunBitmap(a, b *container) *container { // If a is full, difference is the flip of b. - if a.runs[0].start == 0 && a.runs[0].last == 65535 { + if len(a.runs) > 0 && a.runs[0].start == 0 && a.runs[0].last == 65535 { return b.flipBitmap() } output := &container{container_type: ContainerRun} @@ -2534,6 +2534,9 @@ func differenceRunBitmap(a, b *container) *container { break } } + if bit == 65535 { //overflow + break + } } if run.start <= run.last { output.runs = append(output.runs, run) diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index bdc08b649..a4b963a13 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -1524,14 +1524,19 @@ func TestDifferenceRunBitmap(t *testing.T) { bitmap: MakeBitmap([]uint64{0x0, 0x8000000000000000}), exp: []interval16{{start: 0, last: 65}}, }, + { + runs: []interval16{{start: 1, last: 65535}}, + bitmap: MakeBitmap([]uint64{0x0000000000000001}), + exp: []interval16{{start: 1, last: 65535}}, + }, } for i, test := range tests { a.runs = test.runs - a.n = a.runCountRange(0, 100) + a.n = a.runCountRange(0, 65535) for i, v := range test.bitmap { b.bitmap[i] = v } - b.n = b.bitmapCountRange(0, 100) + b.n = b.bitmapCountRange(0, 65535) ret := differenceRunBitmap(a, b) if !reflect.DeepEqual(ret.runs, test.exp) { t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs) From 450dda7fd0760d54580c73a07d16d4ca4078b6ba Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Fri, 10 Nov 2017 17:01:25 -0600 Subject: [PATCH 2/3] overflow bug in differenceRunBitmap Part 2 --- roaring/roaring.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/roaring/roaring.go b/roaring/roaring.go index e4d75a0d2..97994c37a 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -2513,12 +2513,20 @@ func differenceRunBitmap(a, b *container) *container { } output := &container{container_type: ContainerRun} output.n = a.n + if len(a.runs) == 0 { + return output + } for j := 0; j < len(a.runs); j++ { run := a.runs[j] + add := true for bit := a.runs[j].start; bit <= a.runs[j].last; bit++ { if b.bitmapContains(bit) { output.n-- if run.start == bit { + if bit == 65535 { //overflow + add = false + } + run.start++ } else if bit == run.last { run.last-- @@ -2534,13 +2542,15 @@ func differenceRunBitmap(a, b *container) *container { break } } + if bit == 65535 { //overflow break } } if run.start <= run.last { - output.runs = append(output.runs, run) - + if add { + output.runs = append(output.runs, run) + } } } From c9c2a2b0d838a9aaa37951244b972ad0337bd3a6 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Sat, 11 Nov 2017 09:44:15 -0600 Subject: [PATCH 3/3] added test for differenceRunBitmap overflow bug --- roaring/roaring_internal_test.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index a4b963a13..b36723b26 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -1485,6 +1485,12 @@ func MakeBitmap(start []uint64) []uint64 { } return b } +func MakeLastBitSet() []uint64 { + obj := NewBitmap(65535) + c := obj.container(0) + c.arrayToBitmap() + return c.bitmap +} func TestDifferenceRunBitmap(t *testing.T) { a := &container{} @@ -1529,14 +1535,19 @@ func TestDifferenceRunBitmap(t *testing.T) { bitmap: MakeBitmap([]uint64{0x0000000000000001}), exp: []interval16{{start: 1, last: 65535}}, }, + { + runs: []interval16{{start: 0, last: 65533}, {start: 65535, last: 65535}}, + bitmap: MakeLastBitSet(), + exp: []interval16{{start: 0, last: 65533}}, + }, } for i, test := range tests { a.runs = test.runs - a.n = a.runCountRange(0, 65535) + a.n = a.runCountRange(0, 65536) for i, v := range test.bitmap { b.bitmap[i] = v } - b.n = b.bitmapCountRange(0, 65535) + b.n = b.bitmapCountRange(0, 65536) ret := differenceRunBitmap(a, b) if !reflect.DeepEqual(ret.runs, test.exp) { t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)