diff --git a/pkg/labels/regexp.go b/pkg/labels/regexp.go index 705d8cc5f4..7fd227e0b5 100644 --- a/pkg/labels/regexp.go +++ b/pkg/labels/regexp.go @@ -19,6 +19,8 @@ import ( "strings" ) +const maxSetMatches = 256 + type FastRegexMatcher struct { re *regexp.Regexp @@ -86,12 +88,12 @@ func findSetMatches(re *syntax.Regexp, base string) []string { var matches []string var totalSet int for i := 0; i < len(re.Rune); i = i + 2 { - totalSet += int(re.Rune[i+1] - re.Rune[i]) + totalSet += int(re.Rune[i+1]-re.Rune[i]) + 1 } // limits the total characters that can be used to create matches. // In some case like negation [^0-9] a lot of possibilities exists and that // can create thousands of possible matches at which points we're better off using regexp. - if totalSet > 100 { + if totalSet > maxSetMatches { return nil } for i := 0; i < len(re.Rune); i = i + 2 { @@ -128,6 +130,9 @@ func findSetMatchesFromConcat(re *syntax.Regexp, base string) []string { if m == nil { return nil } + if tooManyMatches(newMatches, m...) { + return nil + } newMatches = append(newMatches, m...) } matches = newMatches @@ -143,6 +148,9 @@ func findSetMatchesFromAlternate(re *syntax.Regexp, base string) []string { if found == nil { return nil } + if tooManyMatches(setMatches, found...) { + return nil + } setMatches = append(setMatches, found...) } return setMatches @@ -163,6 +171,11 @@ func isCaseInsensitive(reg *syntax.Regexp) bool { return (reg.Flags & syntax.FoldCase) != 0 } +// tooManyMatches guards against creating too many set matches +func tooManyMatches(matches []string, new ...string) bool { + return len(matches)+len(new) > maxSetMatches +} + func (m *FastRegexMatcher) MatchString(s string) bool { if len(m.setMatches) != 0 { for _, match := range m.setMatches { diff --git a/pkg/labels/regexp_test.go b/pkg/labels/regexp_test.go index abaa6b5d3f..f3d8cc5ebf 100644 --- a/pkg/labels/regexp_test.go +++ b/pkg/labels/regexp_test.go @@ -137,6 +137,8 @@ func TestFindSetMatches(t *testing.T) { {"(api|rpc)_(v1|prom)_((?i)push|query)", nil}, // too high charset combination {"(api|rpc)_[^0-9]", nil}, + // too many combinations + {"[a-z][a-z]", nil}, } { c := c t.Run(c.pattern, func(t *testing.T) {