guards against too many matches.

Signed-off-by: Cyril Tovena <cyril.tovena@gmail.com>
This commit is contained in:
Cyril Tovena 2021-10-05 16:46:24 +02:00
parent 639cd00721
commit d217825af8
No known key found for this signature in database
GPG key ID: FD8F768F9D633FB6
2 changed files with 17 additions and 2 deletions

View file

@ -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 {

View file

@ -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) {