From 4e4b468fba981d40bac03a9d58c15ae29b2a4f3f Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Wed, 29 Jul 2015 02:11:13 +0200 Subject: [PATCH] Fix lexer bug treating non-Latin Unicode digits as digits. Fixes https://github.com/prometheus/prometheus/issues/939 --- promql/lex.go | 14 ++++++++++---- promql/lex_test.go | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/promql/lex.go b/promql/lex.go index d8db61239..55e3d5ea8 100644 --- a/promql/lex.go +++ b/promql/lex.go @@ -16,7 +16,6 @@ package promql import ( "fmt" "strings" - "unicode" "unicode/utf8" ) @@ -458,7 +457,7 @@ func lexStatements(l *lexer) stateFn { } else { l.emit(itemGTR) } - case unicode.IsDigit(r) || (r == '.' && unicode.IsDigit(l.peek())): + case isDigit(r) || (r == '.' && isDigit(l.peek())): l.backup() return lexNumberOrDuration case r == '"' || r == '\'': @@ -569,7 +568,7 @@ func lexValueSequence(l *lexer) stateFn { l.emit(itemTimes) case r == '_': l.emit(itemBlank) - case unicode.IsDigit(r) || (r == '.' && unicode.IsDigit(l.peek())): + case isDigit(r) || (r == '.' && isDigit(l.peek())): l.backup() lexNumber(l) case isAlpha(r): @@ -739,7 +738,14 @@ func isEndOfLine(r rune) bool { // isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. func isAlphaNumeric(r rune) bool { - return isAlpha(r) || unicode.IsDigit(r) + return isAlpha(r) || isDigit(r) +} + +// isDigit reports whether r is a digit. Note: we cannot use unicode.IsDigit() +// instead because that also classifies non-Latin digits as digits. See +// https://github.com/prometheus/prometheus/issues/939. +func isDigit(r rune) bool { + return '0' <= r && r <= '9' } // isAlpha reports whether r is an alphabetic or underscore. diff --git a/promql/lex_test.go b/promql/lex_test.go index 92855fd7b..455b2e5be 100644 --- a/promql/lex_test.go +++ b/promql/lex_test.go @@ -99,6 +99,11 @@ var tests = []struct { input: "0x123", expected: []item{{itemNumber, 0, "0x123"}}, }, + { + // See https://github.com/prometheus/prometheus/issues/939. + input: ".٩", + fail: true, + }, // Test duration. { input: "5s",