app/vmselect/netstorage: properly handle the case when an empty brsPool points to the end of brs.brs

This case is possible after a new brsPool is allocated. The fix is to verify whether len(brsPool) >= len(brs.brs)
before trying to append a new item to brsPool and sharing its contents with brs.brs.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5733
This commit is contained in:
Aliaksandr Valialkin 2024-01-31 10:25:53 +02:00
parent 02492bc1a4
commit db4623efc2
No known key found for this signature in database
GPG Key ID: 52C003EE2BCDB9EB
2 changed files with 19 additions and 5 deletions

View File

@ -1227,7 +1227,7 @@ func ProcessSearchQuery(qt *querytracer.Tracer, sq *storage.SearchQuery, deadlin
// bigger than maxFastAllocBlockSize bytes at append() below. // bigger than maxFastAllocBlockSize bytes at append() below.
brsPool = make([]blockRef, 0, maxFastAllocBlockSize/unsafe.Sizeof(blockRef{})) brsPool = make([]blockRef, 0, maxFastAllocBlockSize/unsafe.Sizeof(blockRef{}))
} }
if brs.brs == nil || haveSameBlockRefTails(brs.brs, brsPool) { if canAppendToBlockRefPool(brsPool, brs.brs) {
// It is safe appending blockRef to brsPool, since there are no other items added there yet. // It is safe appending blockRef to brsPool, since there are no other items added there yet.
brsPool = append(brsPool, blockRef{ brsPool = append(brsPool, blockRef{
partRef: partRef, partRef: partRef,
@ -1295,10 +1295,23 @@ type blockRef struct {
addr tmpBlockAddr addr tmpBlockAddr
} }
func haveSameBlockRefTails(a, b []blockRef) bool { // canAppendToBlockRefPool returns true if a points to the pool and the last item in a is the last item in the pool.
sha := (*reflect.SliceHeader)(unsafe.Pointer(&a)) //
shb := (*reflect.SliceHeader)(unsafe.Pointer(&b)) // In this case it is safe appending an item to the pool and then updating the a, so it refers to the extended slice.
return sha.Data+uintptr(sha.Len)*unsafe.Sizeof(blockRef{}) == shb.Data+uintptr(shb.Len)*unsafe.Sizeof(blockRef{}) //
// True is also returned if a is nil, since in this case it is safe appending an item to the pool and pointing a
// to the last item in the pool.
func canAppendToBlockRefPool(pool, a []blockRef) bool {
if a == nil {
return true
}
if len(a) > len(pool) {
// a doesn't belong to pool
return false
}
shPool := (*reflect.SliceHeader)(unsafe.Pointer(&pool))
shA := (*reflect.SliceHeader)(unsafe.Pointer(&a))
return shPool.Data+uintptr(shPool.Len)*unsafe.Sizeof(blockRef{}) == shA.Data+uintptr(shA.Len)*unsafe.Sizeof(blockRef{})
} }
func setupTfss(qt *querytracer.Tracer, tr storage.TimeRange, tagFilterss [][]storage.TagFilter, maxMetrics int, deadline searchutils.Deadline) ([]*storage.TagFilters, error) { func setupTfss(qt *querytracer.Tracer, tr storage.TimeRange, tagFilterss [][]storage.TagFilter, maxMetrics int, deadline searchutils.Deadline) ([]*storage.TagFilters, error) {

View File

@ -28,6 +28,7 @@ The sandbox cluster installation is running under the constant load generated by
## tip ## tip
* BUGFIX: fix `runtime error: slice bounds out of range` panic, which can occur during query execution. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5733). The bug has been introduced in `v1.97.0`.
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly handle `avg_over_time({some_filter}[d]) keep_metric_names` queries, where [`some_filter`](https://docs.victoriametrics.com/keyconcepts/#filtering) matches multiple time series with multiple names, while `d` is bigger or equal to `3h`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5556). * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly handle `avg_over_time({some_filter}[d]) keep_metric_names` queries, where [`some_filter`](https://docs.victoriametrics.com/keyconcepts/#filtering) matches multiple time series with multiple names, while `d` is bigger or equal to `3h`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5556).
* BUGFIX: dashboards/single: fix typo in query for `version` annotation which falsely produced many version change events. * BUGFIX: dashboards/single: fix typo in query for `version` annotation which falsely produced many version change events.