From 8b4c9459a2226945e6596489e58dbbe4999e537b Mon Sep 17 00:00:00 2001 From: Oleg Zaytsev Date: Mon, 13 May 2024 17:44:07 +0200 Subject: [PATCH] Check utf8.RuneError result Signed-off-by: Oleg Zaytsev --- model/labels/regexp.go | 6 +++++- model/labels/regexp_test.go | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/model/labels/regexp.go b/model/labels/regexp.go index cc2ab366f1..b484e27168 100644 --- a/model/labels/regexp.go +++ b/model/labels/regexp.go @@ -829,7 +829,11 @@ type zeroOrOneCharacterStringMatcher struct { func (m *zeroOrOneCharacterStringMatcher) Matches(s string) bool { // If there's more than one rune in the string, then it can't match. - if _, size := utf8.DecodeRuneInString(s); size < len(s) { + if r, size := utf8.DecodeRuneInString(s); r == utf8.RuneError { + // Size is 0 for empty strings, 1 for invalid rune. + // Empty string matches, invalid rune matches if there isn't anything else. + return size == len(s) + } else if size < len(s) { return false } diff --git a/model/labels/regexp_test.go b/model/labels/regexp_test.go index e9f12d7b64..1db90a473d 100644 --- a/model/labels/regexp_test.go +++ b/model/labels/regexp_test.go @@ -968,6 +968,23 @@ func TestZeroOrOneCharacterStringMatcher(t *testing.T) { require.False(t, matcher.Matches(emoji1+"x")) require.False(t, matcher.Matches(emoji1+emoji2)) }) + + t.Run("invalid unicode", func(t *testing.T) { + // Just for reference, we also compare to what `^.?$` regular expression matches. + re := regexp.MustCompile("^.?$") + matcher := &zeroOrOneCharacterStringMatcher{matchNL: true} + + requireMatches := func(s string, expected bool) { + t.Helper() + require.Equal(t, expected, matcher.Matches(s)) + require.Equal(t, re.MatchString(s), matcher.Matches(s)) + } + + requireMatches("\xff", true) + requireMatches("x\xff", false) + requireMatches("\xffx", false) + requireMatches("\xff\xfe", false) + }) } func BenchmarkZeroOrOneCharacterStringMatcher(b *testing.B) {