Fix int32 overflow issues (#12978)

On a 32 bit architecture the size of int is 32 bits. Thus converting from
int64, uint64 can overflow it and flip the sign.

Try for yourself in playground:
package main

import "fmt"

func main() {
	x := int64(0x1F0000001)
	y := int64(1)
	z := int32(x - y) // numerically this is 0x1F0000000
	fmt.Printf("%v\n", z)
}

Prints -268435456 as if x was smaller.

Followup to #12650

Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
This commit is contained in:
George Krajcsovits 2023-10-16 16:23:26 +02:00 committed by GitHub
parent dcaca86958
commit 7d7b9eacff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 10 deletions

View File

@ -458,7 +458,16 @@ func analyzeBlock(ctx context.Context, path, blockID string, limit int, runExten
postingInfos := []postingInfo{}
printInfo := func(postingInfos []postingInfo) {
slices.SortFunc(postingInfos, func(a, b postingInfo) int { return int(b.metric) - int(a.metric) })
slices.SortFunc(postingInfos, func(a, b postingInfo) int {
switch {
case b.metric < a.metric:
return -1
case b.metric > a.metric:
return 1
default:
return 0
}
})
for i, pc := range postingInfos {
if i >= limit {

View File

@ -201,7 +201,14 @@ func (c *LeveledCompactor) Plan(dir string) ([]string, error) {
func (c *LeveledCompactor) plan(dms []dirMeta) ([]string, error) {
slices.SortFunc(dms, func(a, b dirMeta) int {
return int(a.meta.MinTime - b.meta.MinTime)
switch {
case a.meta.MinTime < b.meta.MinTime:
return -1
case a.meta.MinTime > b.meta.MinTime:
return 1
default:
return 0
}
})
res := c.selectOverlappingDirs(dms)

View File

@ -580,7 +580,14 @@ func (db *DBReadOnly) Blocks() ([]BlockReader, error) {
}
slices.SortFunc(loadable, func(a, b *Block) int {
return int(a.Meta().MinTime - b.Meta().MinTime)
switch {
case a.Meta().MinTime < b.Meta().MinTime:
return -1
case a.Meta().MinTime > b.Meta().MinTime:
return 1
default:
return 0
}
})
blockMetas := make([]BlockMeta, 0, len(loadable))
@ -1448,7 +1455,14 @@ func (db *DB) reloadBlocks() (err error) {
db.metrics.blocksBytes.Set(float64(blocksSize))
slices.SortFunc(toLoad, func(a, b *Block) int {
return int(a.Meta().MinTime - b.Meta().MinTime)
switch {
case a.Meta().MinTime < b.Meta().MinTime:
return -1
case a.Meta().MinTime > b.Meta().MinTime:
return 1
default:
return 0
}
})
// Swap new blocks first for subsequently created readers to be seen.
@ -1518,7 +1532,14 @@ func deletableBlocks(db *DB, blocks []*Block) map[ulid.ULID]struct{} {
// Sort the blocks by time - newest to oldest (largest to smallest timestamp).
// This ensures that the retentions will remove the oldest blocks.
slices.SortFunc(blocks, func(a, b *Block) int {
return int(b.Meta().MaxTime - a.Meta().MaxTime)
switch {
case b.Meta().MaxTime < a.Meta().MaxTime:
return -1
case b.Meta().MaxTime > a.Meta().MaxTime:
return 1
default:
return 0
}
})
for _, block := range blocks {

View File

@ -63,6 +63,15 @@ func (m *maxHeap) push(item Stat) {
}
func (m *maxHeap) get() []Stat {
slices.SortFunc(m.Items, func(a, b Stat) int { return int(b.Count - a.Count) })
slices.SortFunc(m.Items, func(a, b Stat) int {
switch {
case b.Count < a.Count:
return -1
case b.Count > a.Count:
return 1
default:
return 0
}
})
return m.Items
}

View File

@ -179,16 +179,44 @@ type chunkMetaAndChunkDiskMapperRef struct {
func refLessByMinTimeAndMinRef(a, b chunkMetaAndChunkDiskMapperRef) int {
if a.meta.MinTime == b.meta.MinTime {
return int(a.meta.Ref - b.meta.Ref)
switch {
case a.meta.Ref < b.meta.Ref:
return -1
case a.meta.Ref > b.meta.Ref:
return 1
default:
return 0
}
}
switch {
case a.meta.MinTime < b.meta.MinTime:
return -1
case a.meta.MinTime > b.meta.MinTime:
return 1
default:
return 0
}
return int(a.meta.MinTime - b.meta.MinTime)
}
func lessByMinTimeAndMinRef(a, b chunks.Meta) int {
if a.MinTime == b.MinTime {
return int(a.Ref - b.Ref)
switch {
case a.Ref < b.Ref:
return -1
case a.Ref > b.Ref:
return 1
default:
return 0
}
}
switch {
case a.MinTime < b.MinTime:
return -1
case a.MinTime > b.MinTime:
return 1
default:
return 0
}
return int(a.MinTime - b.MinTime)
}
func (oh *OOOHeadIndexReader) Postings(ctx context.Context, name string, values ...string) (index.Postings, error) {