Browse Source

Merge pull request #42961 from milas/fix-path-match-escape

pkg/fileutils: escape additional regex meta characters
Sebastiaan van Stijn 3 năm trước cách đây
mục cha
commit
89a3c427aa
2 tập tin đã thay đổi với 26 bổ sung1 xóa
  1. 23 1
      pkg/fileutils/fileutils.go
  2. 3 0
      pkg/fileutils/fileutils_test.go

+ 23 - 1
pkg/fileutils/fileutils.go

@@ -9,8 +9,30 @@ import (
 	"regexp"
 	"strings"
 	"text/scanner"
+	"unicode/utf8"
 )
 
+// escapeBytes is a bitmap used to check whether a character should be escaped when creating the regex.
+var escapeBytes [8]byte
+
+// shouldEscape reports whether a rune should be escaped as part of the regex.
+//
+// This only includes characters that require escaping in regex but are also NOT valid filepath pattern characters.
+// Additionally, '\' is not excluded because there is specific logic to properly handle this, as it's a path separator
+// on Windows.
+//
+// Adapted from regexp::QuoteMeta in go stdlib.
+// See https://cs.opensource.google/go/go/+/refs/tags/go1.17.2:src/regexp/regexp.go;l=703-715;drc=refs%2Ftags%2Fgo1.17.2
+func shouldEscape(b rune) bool {
+	return b < utf8.RuneSelf && escapeBytes[b%8]&(1<<(b/8)) != 0
+}
+
+func init() {
+	for _, b := range []byte(`.+()|{}$`) {
+		escapeBytes[b%8] |= 1 << (b / 8)
+	}
+}
+
 // PatternMatcher allows checking paths against a list of patterns
 type PatternMatcher struct {
 	patterns   []*Pattern
@@ -256,7 +278,7 @@ func (p *Pattern) compile() error {
 		} else if ch == '?' {
 			// "?" is any char except "/"
 			regStr += "[^" + escSL + "]"
-		} else if ch == '.' || ch == '$' {
+		} else if shouldEscape(ch) {
 			// Escape some regexp special chars that have no meaning
 			// in golang's filepath.Match
 			regStr += `\` + string(ch)

+ 3 - 0
pkg/fileutils/fileutils_test.go

@@ -373,6 +373,9 @@ func TestMatches(t *testing.T) {
 		{"abc/**", "abc/def/ghi", true},
 		{"**/.foo", ".foo", true},
 		{"**/.foo", "bar.foo", false},
+		{"a(b)c/def", "a(b)c/def", true},
+		{"a(b)c/def", "a(b)c/xyz", false},
+		{"a.|)$(}+{bc", "a.|)$(}+{bc", true},
 	}
 
 	if runtime.GOOS != "windows" {