diff --git a/promql/parser/lex.go b/promql/parser/lex.go index ece762dc4..313bd8f88 100644 --- a/promql/parser/lex.go +++ b/promql/parser/lex.go @@ -583,8 +583,12 @@ func lexEscape(l *Lexer) stateFn { return lexString } x = x*base + d - ch = l.next() n-- + + // Don't seek after last rune. + if n > 0 { + ch = l.next() + } } if x > max || 0xD800 <= x && x < 0xE000 { diff --git a/promql/parser/parse_test.go b/promql/parser/parse_test.go index 10096188a..d4203c16e 100644 --- a/promql/parser/parse_test.go +++ b/promql/parser/parse_test.go @@ -3274,6 +3274,16 @@ var testSeries = []struct { input: `my_metric{a="b"} 1 2 3 `, expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), expectedValues: newSeq(1, 2, 3), + }, { + // Handle escaped unicode characters as whole label values. + input: `my_metric{a="\u70ac"} 1 2 3`, + expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", `炬`), + expectedValues: newSeq(1, 2, 3), + }, { + // Handle escaped unicode characters as partial label values. + input: `my_metric{a="\u70ac = torch"} 1 2 3`, + expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", `炬 = torch`), + expectedValues: newSeq(1, 2, 3), }, { input: `my_metric{a="b"} -3-3 -3`, fail: true,