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 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 { func globMatch(pattern, str string) bool {
if !validateGlobPattern(pattern) { if !validateGlobPattern(pattern) {
return false return false
@@ -31,55 +31,41 @@ func globMatch(pattern, str string) bool {
// i is the index for the pattern // i is the index for the pattern
// j is the index for the string // j is the index for the string
var i, j int 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.
for j < len(str) { // matchIdx keeps track of the position in the string where the last * matched.
if globMatch(pattern[i:], str[j:]) { var starIdx, matchIdx int = -1, -1
return true
}
j++
}
return false for j < len(str) {
case '\\': if i < len(pattern) && (pattern[i] == str[j] || pattern[i] == '\\' && i+1 < len(pattern) && pattern[i+1] == str[j]) {
// handle escaped '*' // characters match or if there's an escaped character that matches
i++ if pattern[i] == '\\' {
if i < len(pattern) && pattern[i] == '*' { // skip the escape character
if str[j] != '*' {
return false
}
i++ i++
j++
} else {
if i >= len(pattern) || pattern[i] != str[j] {
return false
}
i++
j++
}
default:
if pattern[i] != str[j] {
return false
} }
i++ i++
j++ 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 {
// no match found
return false
} }
} }
// check for remaining characters in pattern // check for remaining characters in the pattern
for i < len(pattern) && pattern[i] == '*' { for i < len(pattern) && pattern[i] == '*' {
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) { func FuzzMatch(f *testing.F) {
// Policy + Data examples // Policy + Data examples
f.Add([]byte(`[["==", ".status", "draft"]]`), []byte(`{"status": "draft"}`)) 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) { 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) policyNode, err := ipld.Decode(policyBytes, dagjson.Decode)
if err != nil { if err != nil {
t.Skip() t.Skip()