iterative glob.go and limit FuzzMatch input size

This commit is contained in:
Fabio Bozzo
2024-09-17 13:18:12 +02:00
parent c960481a10
commit 53ef97231d
2 changed files with 31 additions and 39 deletions

View File

@@ -22,7 +22,7 @@ func validateGlobPattern(pattern string) bool {
return true
}
// globMatch matches a string against a pattern with '*' wildcards, handling escaped '\*' literals.
// globMatch matches a string against a pattern with * wildcards, handling escaped '\*' literals.
func globMatch(pattern, str string) bool {
if !validateGlobPattern(pattern) {
return false
@@ -31,55 +31,41 @@ func globMatch(pattern, str string) bool {
// i is the index for the pattern
// j is the index for the string
var i, j int
for i < len(pattern) && j < len(str) {
switch pattern[i] {
case '*':
// skip consecutive '*' characters
for i < len(pattern) && pattern[i] == '*' {
i++
}
if i == len(pattern) {
return true
}
// match the rest of the pattern
// starIdx keeps track of the position of the last * in the pattern.
// matchIdx keeps track of the position in the string where the last * matched.
var starIdx, matchIdx int = -1, -1
for j < len(str) {
if globMatch(pattern[i:], str[j:]) {
return true
}
j++
}
return false
case '\\':
// handle escaped '*'
if i < len(pattern) && (pattern[i] == str[j] || pattern[i] == '\\' && i+1 < len(pattern) && pattern[i+1] == str[j]) {
// characters match or if there's an escaped character that matches
if pattern[i] == '\\' {
// skip the escape character
i++
if i < len(pattern) && pattern[i] == '*' {
if str[j] != '*' {
return false
}
i++
j++
} else if i < len(pattern) && pattern[i] == '*' {
// there's a * wildcard in the pattern
starIdx = i
matchIdx = j
i++
} else if starIdx != -1 {
// there's a previous * wildcard, backtrack
i = starIdx + 1
matchIdx++
j = matchIdx
} else {
if i >= len(pattern) || pattern[i] != str[j] {
// no match found
return false
}
i++
j++
}
default:
if pattern[i] != str[j] {
return false
}
i++
j++
}
}
// check for remaining characters in pattern
// check for remaining characters in the pattern
for i < len(pattern) && pattern[i] == '*' {
i++
}
return i == len(pattern) && j == len(str)
// the entire pattern is processed, it's a match
return i == len(pattern)
}

View File

@@ -491,6 +491,8 @@ func TestPolicyExamples(t *testing.T) {
})
}
const maxFuzzInputLength = 128
func FuzzMatch(f *testing.F) {
// Policy + Data examples
f.Add([]byte(`[["==", ".status", "draft"]]`), []byte(`{"status": "draft"}`))
@@ -520,6 +522,10 @@ func FuzzMatch(f *testing.F) {
)
f.Fuzz(func(t *testing.T, policyBytes []byte, dataBytes []byte) {
if len(policyBytes) > maxFuzzInputLength || len(dataBytes) > maxFuzzInputLength {
t.Skip()
}
policyNode, err := ipld.Decode(policyBytes, dagjson.Decode)
if err != nil {
t.Skip()