From b5b5a1df3d5509153673fa3b148ed52806c457d8 Mon Sep 17 00:00:00 2001 From: George Robinson Date: Mon, 30 Oct 2023 13:56:54 +0000 Subject: [PATCH] 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 --- matchers/compat/parse_test.go | 8 ++++---- matchers/compliance/compliance_test.go | 3 +++ matchers/parse/lexer.go | 2 +- matchers/parse/parse_test.go | 4 ++++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/matchers/compat/parse_test.go b/matchers/compat/parse_test.go index b3d1f15a..d31e275b 100644 --- a/matchers/compat/parse_test.go +++ b/matchers/compat/parse_test.go @@ -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", diff --git a/matchers/compliance/compliance_test.go b/matchers/compliance/compliance_test.go index 705c4c43..844f80a5 100644 --- a/matchers/compliance/compliance_test.go +++ b/matchers/compliance/compliance_test.go @@ -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\\}`, diff --git a/matchers/parse/lexer.go b/matchers/parse/lexer.go index a25c9d7e..d6daa6a9 100644 --- a/matchers/parse/lexer.go +++ b/matchers/parse/lexer.go @@ -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. diff --git a/matchers/parse/parse_test.go b/matchers/parse/parse_test.go index 03bef2f1..9b99bde5 100644 --- a/matchers/parse/parse_test.go +++ b/matchers/parse/parse_test.go @@ -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 {