mirror of
https://github.com/prometheus/prometheus.git
synced 2025-02-21 03:16:00 -08:00
Fix containsStringMatcher() when the text contains multiple occurrences of a substring (#431)
Signed-off-by: Marco Pracucci <marco@pracucci.com>
This commit is contained in:
parent
c77900d58e
commit
2e0ecc013f
|
@ -397,27 +397,36 @@ type containsStringMatcher struct {
|
||||||
func (m *containsStringMatcher) Matches(s string) bool {
|
func (m *containsStringMatcher) Matches(s string) bool {
|
||||||
for _, substr := range m.substrings {
|
for _, substr := range m.substrings {
|
||||||
if m.right != nil && m.left != nil {
|
if m.right != nil && m.left != nil {
|
||||||
pos := strings.Index(s, substr)
|
searchStartPos := 0
|
||||||
|
|
||||||
|
for {
|
||||||
|
pos := strings.Index(s[searchStartPos:], substr)
|
||||||
if pos < 0 {
|
if pos < 0 {
|
||||||
continue
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since we started searching from searchStartPos, we have to add that offset
|
||||||
|
// to get the actual position of the substring inside the text.
|
||||||
|
pos += searchStartPos
|
||||||
|
|
||||||
|
// If both the left and right matchers match, then we can stop searching because
|
||||||
|
// we've found a match.
|
||||||
if m.left.Matches(s[:pos]) && m.right.Matches(s[pos+len(substr):]) {
|
if m.left.Matches(s[:pos]) && m.right.Matches(s[pos+len(substr):]) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
|
// Continue searching for another occurrence of the substring inside the text.
|
||||||
|
searchStartPos = pos + 1
|
||||||
}
|
}
|
||||||
|
} else if m.left != nil {
|
||||||
// If we have to check for characters on the left then we need to match a suffix.
|
// If we have to check for characters on the left then we need to match a suffix.
|
||||||
if m.left != nil {
|
|
||||||
if strings.HasSuffix(s, substr) && m.left.Matches(s[:len(s)-len(substr)]) {
|
if strings.HasSuffix(s, substr) && m.left.Matches(s[:len(s)-len(substr)]) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
continue
|
} else if m.right != nil {
|
||||||
}
|
|
||||||
if m.right != nil {
|
|
||||||
if strings.HasPrefix(s, substr) && m.right.Matches(s[len(substr):]) {
|
if strings.HasPrefix(s, substr) && m.right.Matches(s[len(substr):]) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/regexp"
|
|
||||||
"github.com/grafana/regexp/syntax"
|
"github.com/grafana/regexp/syntax"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -60,6 +59,7 @@ var (
|
||||||
"foo", " foo bar", "bar", "buzz\nbar", "bar foo", "bfoo", "\n", "\nfoo", "foo\n", "hello foo world", "hello foo\n world", "",
|
"foo", " foo bar", "bar", "buzz\nbar", "bar foo", "bfoo", "\n", "\nfoo", "foo\n", "hello foo world", "hello foo\n world", "",
|
||||||
"FOO", "Foo", "OO", "Oo", "\nfoo\n", strings.Repeat("f", 20), "prometheus", "prometheus_api_v1", "prometheus_api_v1_foo",
|
"FOO", "Foo", "OO", "Oo", "\nfoo\n", strings.Repeat("f", 20), "prometheus", "prometheus_api_v1", "prometheus_api_v1_foo",
|
||||||
"10.0.1.20", "10.0.2.10", "10.0.3.30", "10.0.4.40",
|
"10.0.1.20", "10.0.2.10", "10.0.3.30", "10.0.4.40",
|
||||||
|
"foofoo0", "foofoo",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,9 +72,7 @@ func TestNewFastRegexMatcher(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
m, err := NewFastRegexMatcher(r)
|
m, err := NewFastRegexMatcher(r)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
re, err := regexp.Compile("^(?:" + r + ")$")
|
require.Equal(t, m.re.MatchString(v), m.MatchString(v))
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, re.MatchString(v), m.MatchString(v))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,3 +327,24 @@ func RandStringRunes(n int) string {
|
||||||
}
|
}
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FuzzFastRegexMatcher_WithStaticallyDefinedRegularExpressions(f *testing.F) {
|
||||||
|
// Create all matchers.
|
||||||
|
matchers := make([]*FastRegexMatcher, 0, len(regexes))
|
||||||
|
for _, re := range regexes {
|
||||||
|
m, err := NewFastRegexMatcher(re)
|
||||||
|
require.NoError(f, err)
|
||||||
|
matchers = append(matchers, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add known values to seed corpus.
|
||||||
|
for _, v := range values {
|
||||||
|
f.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Fuzz(func(t *testing.T, text string) {
|
||||||
|
for _, m := range matchers {
|
||||||
|
require.Equalf(t, m.re.MatchString(text), m.MatchString(text), "regexp: %s text: %s", m.re.String(), text)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue