Skip to content

Commit 3b1ceaa

Browse files
litmitisaacs
authored andcommitted
Fix bug with escaped '@' in patterns
For example, ```js minimatch('@', '\\@*') ``` was returns `false` when `true` expected Close: #110
1 parent dd7aa95 commit 3b1ceaa

2 files changed

Lines changed: 58 additions & 11 deletions

File tree

minimatch.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -472,16 +472,23 @@ class Minimatch {
472472
this.debug('%s\t%s %s %j', pattern, i, re, c)
473473

474474
// skip over any that are escaped.
475-
if (escaping && reSpecials[c]) {
476-
re += '\\' + c
475+
if (escaping) {
476+
/* istanbul ignore next - completely not allowed, even escaped. */
477+
if (c === '/') {
478+
return false
479+
}
480+
481+
if (reSpecials[c]) {
482+
re += '\\'
483+
}
484+
re += c
477485
escaping = false
478486
continue
479487
}
480488

481489
switch (c) {
482490
/* istanbul ignore next */
483491
case '/': {
484-
// completely not allowed, even escaped.
485492
// Should already be path-split by now.
486493
return false
487494
}
@@ -564,9 +571,8 @@ class Minimatch {
564571
continue
565572

566573
case '|':
567-
if (inClass || !patternListStack.length || escaping) {
574+
if (inClass || !patternListStack.length) {
568575
re += '\\|'
569-
escaping = false
570576
continue
571577
}
572578

@@ -597,7 +603,6 @@ class Minimatch {
597603
// first in the list. -- POSIX.2 2.8.3.2
598604
if (i === classStart + 1 || !inClass) {
599605
re += '\\' + c
600-
escaping = false
601606
continue
602607
}
603608

@@ -632,15 +637,12 @@ class Minimatch {
632637
// swallow any state char that wasn't consumed
633638
clearStateChar()
634639

635-
if (escaping) {
636-
// no need
637-
escaping = false
638-
} else if (reSpecials[c]
639-
&& !(c === '^' && inClass)) {
640+
if (reSpecials[c] && !(c === '^' && inClass)) {
640641
re += '\\'
641642
}
642643

643644
re += c
645+
break
644646

645647
} // switch
646648
} // for
@@ -670,6 +672,7 @@ class Minimatch {
670672
this.debug('setting tail', re, pl)
671673
// maybe some even number of \, then maybe 1 \, followed by a |
672674
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
675+
/* istanbul ignore else - should already be done */
673676
if (!$2) {
674677
// the | isn't already escaped, so escape it.
675678
$2 = '\\'

test/escaping.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
var tap = require('tap')
2+
var minimatch = require('../')
3+
4+
// test all characters with codes in range [mincc,maxcc]
5+
var mincc = 0x20
6+
var maxcc = 0xFF
7+
// except listed in exceptions array
8+
var exceptions = ['/', '\\']
9+
var pre = 'x' // prepended to the testable character
10+
var post = 'y' // appended to the testable character
11+
12+
function escapeChar (cc) {
13+
return '"\\u' + ('000' + cc.toString(16).toUpperCase()).substr(-4) + '"'
14+
}
15+
16+
tap.test('escaping tests', function (t) {
17+
for (var cc = mincc; cc <= maxcc; ++cc) {
18+
var cp = String.fromCharCode(cc)
19+
if (exceptions.indexOf(cp) === -1) {
20+
var str = pre + cp + post
21+
var pattern = '*\\' + cp + '*'
22+
var msg = JSON.stringify(str) +
23+
' (for codepoint ' + escapeChar(cc) + ')' +
24+
' should match pattern ' + JSON.stringify(pattern)
25+
t.equal(minimatch(str, pattern), true, msg)
26+
}
27+
}
28+
t.end()
29+
})
30+
31+
tap.test('class escaping tests', function (t) {
32+
for (var cc = mincc; cc <= maxcc; ++cc) {
33+
var cp = String.fromCharCode(cc)
34+
if (exceptions.indexOf(cp) === -1) {
35+
var str = pre + cp + post
36+
var pattern = '*[\\' + cp + ']*'
37+
var msg = JSON.stringify(str) +
38+
' (for codepoint ' + escapeChar(cc) + ')' +
39+
' should match pattern ' + JSON.stringify(pattern)
40+
t.equal(minimatch(str, pattern), true, msg)
41+
}
42+
}
43+
t.end()
44+
})

0 commit comments

Comments
 (0)