mirror of
https://github.com/prometheus/prometheus.git
synced 2026-05-05 04:16:15 +02:00
textparse: fix parseLVals to only treat quoted strings as metric names
When a label-name position is followed by comma or brace-close, only treat it as a metric name shorthand if the token was a double-quoted string (tQString). Bare identifiers must be followed by an equal sign. Add tests for bare identifier inputs that previously could panic. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
This commit is contained in:
parent
5a02b92c0e
commit
ad2f81ef6d
@ -634,11 +634,13 @@ func (p *OpenMetricsParser) parseLVals(offsets []int, isExemplar bool) ([]int, e
|
||||
for {
|
||||
curTStart := p.l.start
|
||||
curTI := p.l.i
|
||||
var isQString bool
|
||||
switch t {
|
||||
case tBraceClose:
|
||||
return offsets, nil
|
||||
case tLName:
|
||||
case tQString:
|
||||
isQString = true
|
||||
default:
|
||||
return nil, p.parseError("expected label name", t)
|
||||
}
|
||||
@ -647,7 +649,7 @@ func (p *OpenMetricsParser) parseLVals(offsets []int, isExemplar bool) ([]int, e
|
||||
// A quoted string followed by a comma or brace is a metric name. Set the
|
||||
// offsets and continue processing. If this is an exemplar, this format
|
||||
// is not allowed.
|
||||
if t == tComma || t == tBraceClose {
|
||||
if isQString && (t == tComma || t == tBraceClose) {
|
||||
if isExemplar {
|
||||
return nil, p.parseError("expected label name", t)
|
||||
}
|
||||
|
||||
@ -941,6 +941,10 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
||||
input: "empty_label_name{=\"\"} 0\n# EOF\n",
|
||||
err: "expected label name, got \"=\\\"\" (\"EQUAL\") while parsing: \"empty_label_name{=\\\"\"",
|
||||
},
|
||||
{
|
||||
input: "{A}0\n# EOF\n",
|
||||
err: "expected equal, got \"}0\" (\"BCLOSE\") while parsing: \"{A}0\"",
|
||||
},
|
||||
{
|
||||
input: "foo 1_2\n\n# EOF\n",
|
||||
err: "unsupported character in float while parsing: \"foo 1_2\"",
|
||||
@ -971,11 +975,11 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
input: `custom_metric_total 1 # {bb}`,
|
||||
err: "expected label name, got \"}\" (\"BCLOSE\") while parsing: \"custom_metric_total 1 # {bb}\"",
|
||||
err: "expected equal, got \"}\" (\"BCLOSE\") while parsing: \"custom_metric_total 1 # {bb}\"",
|
||||
},
|
||||
{
|
||||
input: `custom_metric_total 1 # {bb, a="dd"}`,
|
||||
err: "expected label name, got \", \" (\"COMMA\") while parsing: \"custom_metric_total 1 # {bb, \"",
|
||||
err: "expected equal, got \", \" (\"COMMA\") while parsing: \"custom_metric_total 1 # {bb, \"",
|
||||
},
|
||||
{
|
||||
input: `custom_metric_total 1 # {aa="bb",,cc="dd"} 1`,
|
||||
@ -1037,6 +1041,22 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenMetricsParseBareIdentifierInBraces(t *testing.T) {
|
||||
require.NotPanics(t, func() {
|
||||
p := NewOpenMetricsParser([]byte("{A} 0\n# EOF\n"), labels.NewSymbolTable(), WithOMParserSTSeriesSkipped())
|
||||
for {
|
||||
et, err := p.Next()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if et == EntrySeries {
|
||||
var lset labels.Labels
|
||||
p.Labels(&lset)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestOMNullByteHandling(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
|
||||
@ -408,11 +408,13 @@ func (p *PromParser) parseLVals() error {
|
||||
for {
|
||||
curTStart := p.l.start
|
||||
curTI := p.l.i
|
||||
var isQString bool
|
||||
switch t {
|
||||
case tBraceClose:
|
||||
return nil
|
||||
case tLName:
|
||||
case tQString:
|
||||
isQString = true
|
||||
default:
|
||||
return p.parseError("expected label name", t)
|
||||
}
|
||||
@ -420,7 +422,7 @@ func (p *PromParser) parseLVals() error {
|
||||
t = p.nextToken()
|
||||
// A quoted string followed by a comma or brace is a metric name. Set the
|
||||
// offsets and continue processing.
|
||||
if t == tComma || t == tBraceClose {
|
||||
if isQString && (t == tComma || t == tBraceClose) {
|
||||
if p.offsets[0] != -1 || p.offsets[1] != -1 {
|
||||
return fmt.Errorf("metric name already set while parsing: %q", p.l.b[p.start:p.l.i])
|
||||
}
|
||||
|
||||
@ -510,6 +510,10 @@ func TestPromParseErrors(t *testing.T) {
|
||||
input: "empty_label_name{=\"\"} 0",
|
||||
err: "expected label name, got \"=\\\"\" (\"EQUAL\") while parsing: \"empty_label_name{=\\\"\"",
|
||||
},
|
||||
{
|
||||
input: "{A}0",
|
||||
err: "expected equal, got \"}0\" (\"BCLOSE\") while parsing: \"{A}0\"",
|
||||
},
|
||||
{
|
||||
input: "foo 1_2\n",
|
||||
err: "unsupported character in float while parsing: \"foo 1_2\"",
|
||||
@ -550,6 +554,22 @@ func TestPromParseErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPromParseBareIdentifierInBraces(t *testing.T) {
|
||||
require.NotPanics(t, func() {
|
||||
p := NewPromParser([]byte("{A} 0\n"), labels.NewSymbolTable(), false)
|
||||
for {
|
||||
et, err := p.Next()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if et == EntrySeries {
|
||||
var lset labels.Labels
|
||||
p.Labels(&lset)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPromNullByteHandling(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user