Skip to content

Commit 195558d

Browse files
committed
pkg/fileutils: escape additional regex meta characters
There were a couple characters being explicitly escaped, but it wasn't comprehensive. This is now the set difference between the Golang regex meta characters and the `filepath` match meta characters with the exception of `\`, which already has special logic due to being the path separator on Windows. Signed-off-by: Milas Bowman <milasb@gmail.com>
1 parent bb6fdac commit 195558d

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

pkg/fileutils/fileutils.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,30 @@ import (
99
"regexp"
1010
"strings"
1111
"text/scanner"
12+
"unicode/utf8"
1213
)
1314

15+
// escapeBytes is a bitmap used to check whether a character should be escaped when creating the regex.
16+
var escapeBytes [8]byte
17+
18+
// shouldEscape reports whether a rune should be escaped as part of the regex.
19+
//
20+
// This only includes characters that require escaping in regex but are also NOT valid filepath pattern characters.
21+
// Additionally, '\' is not excluded because there is specific logic to properly handle this, as it's a path separator
22+
// on Windows.
23+
//
24+
// Adapted from regexp::QuoteMeta in go stdlib.
25+
// 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
26+
func shouldEscape(b rune) bool {
27+
return b < utf8.RuneSelf && escapeBytes[b%8]&(1<<(b/8)) != 0
28+
}
29+
30+
func init() {
31+
for _, b := range []byte(`.+()|{}$`) {
32+
escapeBytes[b%8] |= 1 << (b / 8)
33+
}
34+
}
35+
1436
// PatternMatcher allows checking paths against a list of patterns
1537
type PatternMatcher struct {
1638
patterns []*Pattern
@@ -256,7 +278,7 @@ func (p *Pattern) compile() error {
256278
} else if ch == '?' {
257279
// "?" is any char except "/"
258280
regStr += "[^" + escSL + "]"
259-
} else if ch == '.' || ch == '$' {
281+
} else if shouldEscape(ch) {
260282
// Escape some regexp special chars that have no meaning
261283
// in golang's filepath.Match
262284
regStr += `\` + string(ch)

pkg/fileutils/fileutils_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,9 @@ func TestMatches(t *testing.T) {
373373
{"abc/**", "abc/def/ghi", true},
374374
{"**/.foo", ".foo", true},
375375
{"**/.foo", "bar.foo", false},
376+
{"a(b)c/def", "a(b)c/def", true},
377+
{"a(b)c/def", "a(b)c/xyz", false},
378+
{"a.|)$(}+{bc", "a.|)$(}+{bc", true},
376379
}
377380

378381
if runtime.GOOS != "windows" {

0 commit comments

Comments
 (0)