iterative glob.go and limit FuzzMatch input size
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user