Support UTF-8 label matchers: Do not allow unquoted escape sequences (#3571)

* Do not allow unquoted escape sequences

This commit updates the matchers parser to reject unquoted
openmetrics escape sequences. As an example, foo=bar\n
will no longer parse, and must instead be written as
foo="bar\n". This avoids an issue where the input is valid
in both the matchers and classic parsers, but results
in two different parsings.

---------

Signed-off-by: George Robinson <george.robinson@grafana.com>
This commit is contained in:
George Robinson 2023-10-30 13:56:54 +00:00 committed by GitHub
parent 8512285e54
commit b5b5a1df3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 12 additions and 5 deletions

View File

@ -38,8 +38,8 @@ func TestFallbackMatcherParser(t *testing.T) {
expected: mustNewMatcher(t, labels.MatchEqual, "foo🙂", "bar"),
}, {
name: "is accepted in old parser but not new",
input: "foo=!bar",
expected: mustNewMatcher(t, labels.MatchEqual, "foo", "!bar"),
input: "foo=!bar\\n",
expected: mustNewMatcher(t, labels.MatchEqual, "foo", "!bar\n"),
}, {
name: "is accepted in neither",
input: "foo!bar",
@ -81,10 +81,10 @@ func TestFallbackMatchersParser(t *testing.T) {
},
}, {
name: "is accepted in old parser but not new",
input: "{foo=!bar,bar=$baz}",
input: "{foo=!bar,bar=$baz\\n}",
expected: labels.Matchers{
mustNewMatcher(t, labels.MatchEqual, "foo", "!bar"),
mustNewMatcher(t, labels.MatchEqual, "bar", "$baz"),
mustNewMatcher(t, labels.MatchEqual, "bar", "$baz\n"),
},
}, {
name: "is accepted in neither",

View File

@ -76,6 +76,7 @@ func TestCompliance(t *testing.T) {
m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "\\t")
return append(ms, m)
}(),
skip: true,
},
{
input: `{foo=bar\t}`,
@ -84,6 +85,7 @@ func TestCompliance(t *testing.T) {
m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar\\t")
return append(ms, m)
}(),
skip: true,
},
{
input: `{foo=bar\}`,
@ -92,6 +94,7 @@ func TestCompliance(t *testing.T) {
m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar\\")
return append(ms, m)
}(),
skip: true,
},
{
input: `{foo=bar\\}`,

View File

@ -25,7 +25,7 @@ const (
)
func isReserved(r rune) bool {
return unicode.IsSpace(r) || strings.ContainsRune("{}!=~,\"'`", r)
return unicode.IsSpace(r) || strings.ContainsRune("{}!=~,\\\"'`", r)
}
// expectedError is returned when the next rune does not match what is expected.

View File

@ -195,6 +195,10 @@ func TestMatchers(t *testing.T) {
name: "invalid escape sequence",
input: "{foo=\"bar\\w\"}",
error: "5:12: \"bar\\w\": invalid input",
}, {
name: "no unquoted escape sequences",
input: "{foo=bar\\n}",
error: "8:9: \\: invalid input: expected a comma or close brace",
}}
for _, test := range tests {