mirror of
https://github.com/prometheus/prometheus
synced 2026-04-20 22:41:05 +08:00
textparse: fix panic in protobuf parser for summary with no quantiles
getMagicLabel had no bounds check on the quantile slice for the Summary case. fieldsDone for an empty-quantile summary is set inside Series(), not getMagicLabel. A caller driving Next() without calling Series() at the _sum step would allow fieldPos to advance to 0 and index into an empty slice. Add the same out-of-bounds guard that the histogram branch already has, and a regression test that exercises Next()-only iteration over a summary with no quantiles. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
This commit is contained in:
@@ -674,6 +674,10 @@ func (p *ProtobufParser) getMagicLabel() (bool, string, string) {
|
||||
switch p.dec.GetType() {
|
||||
case dto.MetricType_SUMMARY:
|
||||
qq := p.dec.GetSummary().GetQuantile()
|
||||
if p.fieldPos >= len(qq) {
|
||||
p.fieldsDone = true
|
||||
return false, "", ""
|
||||
}
|
||||
q := qq[p.fieldPos]
|
||||
p.fieldsDone = p.fieldPos == len(qq)-1
|
||||
return true, model.QuantileLabel, labels.FormatOpenMetricsFloat(q.GetQuantile())
|
||||
|
||||
@@ -5911,6 +5911,32 @@ func generateValidMetricName(r *rand.Rand) string {
|
||||
return generateString(r, validFirstRunes, validMetricNameRunes)
|
||||
}
|
||||
|
||||
// TestProtobufParseSummaryNoQuantilesNoPanic is a regression test for a panic
|
||||
// when Next() is called without Series() on a summary with no quantiles.
|
||||
func TestProtobufParseSummaryNoQuantilesNoPanic(t *testing.T) {
|
||||
buf := metricFamiliesToProtobuf(t, []string{`
|
||||
name: "no_quantile_summary"
|
||||
help: "A summary with no quantile entries."
|
||||
type: SUMMARY
|
||||
metric: <
|
||||
summary: <
|
||||
sample_count: 10
|
||||
sample_sum: 1.5
|
||||
>
|
||||
>
|
||||
`})
|
||||
|
||||
p := NewProtobufParser(buf.Bytes(), false, false, false, false, labels.NewSymbolTable())
|
||||
require.NotPanics(t, func() {
|
||||
for {
|
||||
_, err := p.Next()
|
||||
if errors.Is(err, io.EOF) || err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func generateString(r *rand.Rand, firstRunes, restRunes []rune) string {
|
||||
result := make([]rune, 1+r.Intn(20))
|
||||
for i := range result {
|
||||
|
||||
Reference in New Issue
Block a user