diff --git a/expfmt/text_parse.go b/expfmt/text_parse.go index 00c8841a..4ce1f40b 100644 --- a/expfmt/text_parse.go +++ b/expfmt/text_parse.go @@ -339,6 +339,16 @@ func (p *TextParser) startLabelName() stateFn { return nil // Unexpected end of input. } if p.currentByte == '}' { + if p.currentMF == nil { + // The closing brace was reached before any metric name was read, + // e.g. for the input "{}". There is no metric to attach labels to, + // so this is a malformed exposition. This mirrors the guard in + // startLabelValue. currentMF (not currentMetric) is checked because + // reset only clears currentMF between parses. + p.parseError("invalid metric name") + p.currentLabelPairs = nil + return nil + } p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...) p.currentLabelPairs = nil if p.skipBlankTab(); p.err != nil { diff --git a/expfmt/text_parse_test.go b/expfmt/text_parse_test.go index edcee13a..e915fb98 100644 --- a/expfmt/text_parse_test.go +++ b/expfmt/text_parse_test.go @@ -1332,6 +1332,12 @@ request_duration_microseconds_count 2693 `, errUTF8: `text format parsing error in line 5: negative bucket population for histogram "request_duration_microseconds"`, }, + // 47: Empty braces with no metric name (regression test for a nil + // pointer dereference in startLabelName). + { + in: `{} 3.14`, + errUTF8: "text format parsing error in line 1: invalid metric name", + }, } for i, scenario := range scenarios { parser.scheme = model.UTF8Validation