minimatch 6.2.1 → 6.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,6 +7,43 @@ This is the matching library used internally by npm.
7
7
  It works by converting glob expressions into JavaScript `RegExp`
8
8
  objects.
9
9
 
10
+ ## Important Security Consideration!
11
+
12
+ > [!WARNING]
13
+ > This library uses JavaScript regular expressions. Please read
14
+ > the following warning carefully, and be thoughtful about what
15
+ > you provide to this library in production systems.
16
+
17
+ _Any_ library in JavaScript that deals with matching string
18
+ patterns using regular expressions will be subject to
19
+ [ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
20
+ if the pattern is generated using untrusted input.
21
+
22
+ Efforts have been made to mitigate risk as much as is feasible in
23
+ such a library, providing maximum recursion depths and so forth,
24
+ but these measures can only ultimately protect against accidents,
25
+ not malice. A dedicated attacker can _always_ find patterns that
26
+ cannot be defended against by a bash-compatible glob pattern
27
+ matching system that uses JavaScript regular expressions.
28
+
29
+ To be extremely clear:
30
+
31
+ > [!WARNING]
32
+ > **If you create a system where you take user input, and use
33
+ > that input as the source of a Regular Expression pattern, in
34
+ > this or any extant glob matcher in JavaScript, you will be
35
+ > pwned.**
36
+
37
+ A future version of this library _may_ use a different matching
38
+ algorithm which does not exhibit backtracking problems. If and
39
+ when that happens, it will likely be a sweeping change, and those
40
+ improvements will **not** be backported to legacy versions.
41
+
42
+ In the near term, it is not reasonable to continue to play
43
+ whack-a-mole with security advisories, and so any future ReDoS
44
+ reports will be considered "working as intended", and resolved
45
+ entirely by this warning.
46
+
10
47
  ## Usage
11
48
 
12
49
  ```js
package/changelog.md ADDED
@@ -0,0 +1,61 @@
1
+ # change log
2
+
3
+ ## 6.1
4
+
5
+ - Handle UNC paths on Windows
6
+
7
+ This adds some slightly modified behavior when a pattern or path starts
8
+ with `//` on Windows.
9
+
10
+ - In the case of `//?/<drive letter>:/...`, the `?` is treated as a
11
+ literal character, rather than a wildcard. That is, `//?/c:` will
12
+ _not_ match `//x/c:`.
13
+ - UNC patterns starting with `//?/<drive letter>:/` will match file paths
14
+ starting with `<drive letter>:` if the drive letters match
15
+ case-insensitively.
16
+ - File paths starting with `//?/<drive letter>:/` will match file
17
+ patterns starting with `<drive letter>:` if the drive letters match
18
+ case-insensitively.
19
+
20
+ - Add `{preserveMultipleSlashes:true}` option to suppress the
21
+ behavior where multiple consecutive `/` characters would be
22
+ effectively coerced into a single path portion separator.
23
+
24
+ ## 6.0
25
+
26
+ - hybrid module supporting both `require()` and `import`
27
+ - exported types
28
+
29
+ ## 5.1
30
+
31
+ - use windowsPathNoEscape/allowWindowsEscape opts
32
+ - make character classes more faithful to bash glob behavior
33
+ - fix handling of escapes
34
+ - treat invalid character classes as non-matching pattern
35
+ rather than escaped literals
36
+
37
+ ## 5.0
38
+
39
+ - brace-expansion: ignore only blocks that begins with $
40
+ - Expect exclusively forward slash as path sep, same as node-glob
41
+
42
+ ## 4.2
43
+
44
+ - makeRe: globstar should match zero+ path portions
45
+ - Fix bug with escaped '@' in patterns
46
+
47
+ ## 4.1
48
+
49
+ - treat `nocase:true` as always having magic
50
+ - expose GLOBSTAR marker
51
+
52
+ ## 4.0
53
+
54
+ - Update to modern JS syntax
55
+ - Add `allowWindowsEscape` option
56
+
57
+ ## 3.x
58
+
59
+ - Added basic redos protection
60
+ - Handle unfinished `!(` extglob patterns
61
+ - Add `partial: true` option
@@ -0,0 +1,8 @@
1
+ export type ParseClassResult = [
2
+ src: string,
3
+ uFlag: boolean,
4
+ consumed: number,
5
+ hasMagic: boolean
6
+ ];
7
+ export declare const parseClass: (glob: string, position: number) => ParseClassResult;
8
+ //# sourceMappingURL=brace-expressions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brace-expressions.d.ts","sourceRoot":"","sources":["../../src/brace-expressions.ts"],"names":[],"mappings":"AA+BA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM;IACX,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,OAAO;CAClB,CAAA;AAQD,eAAO,MAAM,UAAU,SACf,MAAM,YACF,MAAM,qBA8HjB,CAAA"}
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ // translate the various posix character classes into unicode properties
3
+ // this works across all unicode locales
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.parseClass = void 0;
6
+ // { <posix class>: [<translation>, /u flag required, negated]
7
+ const posixClasses = {
8
+ '[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
9
+ '[:alpha:]': ['\\p{L}\\p{Nl}', true],
10
+ '[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
11
+ '[:blank:]': ['\\p{Zs}\\t', true],
12
+ '[:cntrl:]': ['\\p{Cc}', true],
13
+ '[:digit:]': ['\\p{Nd}', true],
14
+ '[:graph:]': ['\\p{Z}\\p{C}', true, true],
15
+ '[:lower:]': ['\\p{Ll}', true],
16
+ '[:print:]': ['\\p{C}', true],
17
+ '[:punct:]': ['\\p{P}', true],
18
+ '[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
19
+ '[:upper:]': ['\\p{Lu}', true],
20
+ '[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
21
+ '[:xdigit:]': ['A-Fa-f0-9', false],
22
+ };
23
+ // only need to escape a few things inside of brace expressions
24
+ // escapes: [ \ ] -
25
+ const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
26
+ // escape all regexp magic characters
27
+ const regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
28
+ // everything has already been escaped, we just have to join
29
+ const rangesToString = (ranges) => ranges.join('');
30
+ // takes a glob string at a posix brace expression, and returns
31
+ // an equivalent regular expression source, and boolean indicating
32
+ // whether the /u flag needs to be applied, and the number of chars
33
+ // consumed to parse the character class.
34
+ // This also removes out of order ranges, and returns ($.) if the
35
+ // entire class just no good.
36
+ const parseClass = (glob, position) => {
37
+ const pos = position;
38
+ /* c8 ignore start */
39
+ if (glob.charAt(pos) !== '[') {
40
+ throw new Error('not in a brace expression');
41
+ }
42
+ /* c8 ignore stop */
43
+ const ranges = [];
44
+ const negs = [];
45
+ let i = pos + 1;
46
+ let sawStart = false;
47
+ let uflag = false;
48
+ let escaping = false;
49
+ let negate = false;
50
+ let endPos = pos;
51
+ let rangeStart = '';
52
+ WHILE: while (i < glob.length) {
53
+ const c = glob.charAt(i);
54
+ if ((c === '!' || c === '^') && i === pos + 1) {
55
+ negate = true;
56
+ i++;
57
+ continue;
58
+ }
59
+ if (c === ']' && sawStart && !escaping) {
60
+ endPos = i + 1;
61
+ break;
62
+ }
63
+ sawStart = true;
64
+ if (c === '\\') {
65
+ if (!escaping) {
66
+ escaping = true;
67
+ i++;
68
+ continue;
69
+ }
70
+ // escaped \ char, fall through and treat like normal char
71
+ }
72
+ if (c === '[' && !escaping) {
73
+ // either a posix class, a collation equivalent, or just a [
74
+ for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
75
+ if (glob.startsWith(cls, i)) {
76
+ // invalid, [a-[] is fine, but not [a-[:alpha]]
77
+ if (rangeStart) {
78
+ return ['$.', false, glob.length - pos, true];
79
+ }
80
+ i += cls.length;
81
+ if (neg)
82
+ negs.push(unip);
83
+ else
84
+ ranges.push(unip);
85
+ uflag = uflag || u;
86
+ continue WHILE;
87
+ }
88
+ }
89
+ }
90
+ // now it's just a normal character, effectively
91
+ escaping = false;
92
+ if (rangeStart) {
93
+ // throw this range away if it's not valid, but others
94
+ // can still match.
95
+ if (c > rangeStart) {
96
+ ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c));
97
+ }
98
+ else if (c === rangeStart) {
99
+ ranges.push(braceEscape(c));
100
+ }
101
+ rangeStart = '';
102
+ i++;
103
+ continue;
104
+ }
105
+ // now might be the start of a range.
106
+ // can be either c-d or c-] or c<more...>] or c] at this point
107
+ if (glob.startsWith('-]', i + 1)) {
108
+ ranges.push(braceEscape(c + '-'));
109
+ i += 2;
110
+ continue;
111
+ }
112
+ if (glob.startsWith('-', i + 1)) {
113
+ rangeStart = c;
114
+ i += 2;
115
+ continue;
116
+ }
117
+ // not the start of a range, just a single character
118
+ ranges.push(braceEscape(c));
119
+ i++;
120
+ }
121
+ if (endPos < i) {
122
+ // didn't see the end of the class, not a valid class,
123
+ // but might still be valid as a literal match.
124
+ return ['', false, 0, false];
125
+ }
126
+ // if we got no ranges and no negates, then we have a range that
127
+ // cannot possibly match anything, and that poisons the whole glob
128
+ if (!ranges.length && !negs.length) {
129
+ return ['$.', false, glob.length - pos, true];
130
+ }
131
+ // if we got one positive range, and it's a single character, then that's
132
+ // not actually a magic pattern, it's just that one literal character.
133
+ // we should not treat that as "magic", we should just return the literal
134
+ // character. [_] is a perfectly valid way to escape glob magic chars.
135
+ if (negs.length === 0 &&
136
+ ranges.length === 1 &&
137
+ /^\\?.$/.test(ranges[0]) &&
138
+ !negate) {
139
+ const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
140
+ return [regexpEscape(r), false, endPos - pos, false];
141
+ }
142
+ const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']';
143
+ const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']';
144
+ const comb = ranges.length && negs.length
145
+ ? '(' + sranges + '|' + snegs + ')'
146
+ : ranges.length
147
+ ? sranges
148
+ : snegs;
149
+ return [comb, uflag, endPos - pos, true];
150
+ };
151
+ exports.parseClass = parseClass;
152
+ //# sourceMappingURL=brace-expressions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brace-expressions.js","sourceRoot":"","sources":["../../src/brace-expressions.ts"],"names":[],"mappings":"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","sourcesContent":["// translate the various posix character classes into unicode properties\n// this works across all unicode locales\n\n// { <posix class>: [<translation>, /u flag required, negated]\nconst posixClasses: { [k: string]: [e: string, u: boolean, n?: boolean] } = {\n '[:alnum:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}', true],\n '[:alpha:]': ['\\\\p{L}\\\\p{Nl}', true],\n '[:ascii:]': ['\\\\x' + '00-\\\\x' + '7f', false],\n '[:blank:]': ['\\\\p{Zs}\\\\t', true],\n '[:cntrl:]': ['\\\\p{Cc}', true],\n '[:digit:]': ['\\\\p{Nd}', true],\n '[:graph:]': ['\\\\p{Z}\\\\p{C}', true, true],\n '[:lower:]': ['\\\\p{Ll}', true],\n '[:print:]': ['\\\\p{C}', true],\n '[:punct:]': ['\\\\p{P}', true],\n '[:space:]': ['\\\\p{Z}\\\\t\\\\r\\\\n\\\\v\\\\f', true],\n '[:upper:]': ['\\\\p{Lu}', true],\n '[:word:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}\\\\p{Pc}', true],\n '[:xdigit:]': ['A-Fa-f0-9', false],\n}\n\n// only need to escape a few things inside of brace expressions\n// escapes: [ \\ ] -\nconst braceEscape = (s: string) => s.replace(/[[\\]\\\\-]/g, '\\\\$&')\n// escape all regexp magic characters\nconst regexpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// everything has already been escaped, we just have to join\nconst rangesToString = (ranges: string[]): string => ranges.join('')\n\nexport type ParseClassResult = [\n src: string,\n uFlag: boolean,\n consumed: number,\n hasMagic: boolean\n]\n\n// takes a glob string at a posix brace expression, and returns\n// an equivalent regular expression source, and boolean indicating\n// whether the /u flag needs to be applied, and the number of chars\n// consumed to parse the character class.\n// This also removes out of order ranges, and returns ($.) if the\n// entire class just no good.\nexport const parseClass = (\n glob: string,\n position: number\n): ParseClassResult => {\n const pos = position\n /* c8 ignore start */\n if (glob.charAt(pos) !== '[') {\n throw new Error('not in a brace expression')\n }\n /* c8 ignore stop */\n const ranges: string[] = []\n const negs: string[] = []\n\n let i = pos + 1\n let sawStart = false\n let uflag = false\n let escaping = false\n let negate = false\n let endPos = pos\n let rangeStart = ''\n WHILE: while (i < glob.length) {\n const c = glob.charAt(i)\n if ((c === '!' || c === '^') && i === pos + 1) {\n negate = true\n i++\n continue\n }\n\n if (c === ']' && sawStart && !escaping) {\n endPos = i + 1\n break\n }\n\n sawStart = true\n if (c === '\\\\') {\n if (!escaping) {\n escaping = true\n i++\n continue\n }\n // escaped \\ char, fall through and treat like normal char\n }\n if (c === '[' && !escaping) {\n // either a posix class, a collation equivalent, or just a [\n for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {\n if (glob.startsWith(cls, i)) {\n // invalid, [a-[] is fine, but not [a-[:alpha]]\n if (rangeStart) {\n return ['$.', false, glob.length - pos, true]\n }\n i += cls.length\n if (neg) negs.push(unip)\n else ranges.push(unip)\n uflag = uflag || u\n continue WHILE\n }\n }\n }\n\n // now it's just a normal character, effectively\n escaping = false\n if (rangeStart) {\n // throw this range away if it's not valid, but others\n // can still match.\n if (c > rangeStart) {\n ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c))\n } else if (c === rangeStart) {\n ranges.push(braceEscape(c))\n }\n rangeStart = ''\n i++\n continue\n }\n\n // now might be the start of a range.\n // can be either c-d or c-] or c<more...>] or c] at this point\n if (glob.startsWith('-]', i + 1)) {\n ranges.push(braceEscape(c + '-'))\n i += 2\n continue\n }\n if (glob.startsWith('-', i + 1)) {\n rangeStart = c\n i += 2\n continue\n }\n\n // not the start of a range, just a single character\n ranges.push(braceEscape(c))\n i++\n }\n\n if (endPos < i) {\n // didn't see the end of the class, not a valid class,\n // but might still be valid as a literal match.\n return ['', false, 0, false]\n }\n\n // if we got no ranges and no negates, then we have a range that\n // cannot possibly match anything, and that poisons the whole glob\n if (!ranges.length && !negs.length) {\n return ['$.', false, glob.length - pos, true]\n }\n\n // if we got one positive range, and it's a single character, then that's\n // not actually a magic pattern, it's just that one literal character.\n // we should not treat that as \"magic\", we should just return the literal\n // character. [_] is a perfectly valid way to escape glob magic chars.\n if (\n negs.length === 0 &&\n ranges.length === 1 &&\n /^\\\\?.$/.test(ranges[0]) &&\n !negate\n ) {\n const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0]\n return [regexpEscape(r), false, endPos - pos, false]\n }\n\n const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']'\n const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']'\n const comb =\n ranges.length && negs.length\n ? '(' + sranges + '|' + snegs + ')'\n : ranges.length\n ? sranges\n : snegs\n\n return [comb, uflag, endPos - pos, true]\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { MinimatchOptions } from './index.js';
2
+ /**
3
+ * Escape all magic characters in a glob pattern.
4
+ *
5
+ * If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
6
+ * option is used, then characters are escaped by wrapping in `[]`, because
7
+ * a magic character wrapped in a character class can only be satisfied by
8
+ * that exact character. In this mode, `\` is _not_ escaped, because it is
9
+ * not interpreted as a magic character, but instead as a path separator.
10
+ */
11
+ export declare const escape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, 'windowsPathsNoEscape'>) => string;
12
+ //# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,MACd,MAAM,8BAGN,KAAK,gBAAgB,EAAE,sBAAsB,CAAC,WAQlD,CAAA"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.escape = void 0;
4
+ /**
5
+ * Escape all magic characters in a glob pattern.
6
+ *
7
+ * If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
8
+ * option is used, then characters are escaped by wrapping in `[]`, because
9
+ * a magic character wrapped in a character class can only be satisfied by
10
+ * that exact character. In this mode, `\` is _not_ escaped, because it is
11
+ * not interpreted as a magic character, but instead as a path separator.
12
+ */
13
+ const escape = (s, { windowsPathsNoEscape = false, } = {}) => {
14
+ // don't need to escape +@! because we escape the parens
15
+ // that make those magic, and escaping ! as [!] isn't valid,
16
+ // because [!]] is a valid glob class meaning not ']'.
17
+ return windowsPathsNoEscape
18
+ ? s.replace(/[?*()[\]]/g, '[$&]')
19
+ : s.replace(/[?*()[\]\\]/g, '\\$&');
20
+ };
21
+ exports.escape = escape;
22
+ //# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":";;;AACA;;;;;;;;GAQG;AACI,MAAM,MAAM,GAAG,CACpB,CAAS,EACT,EACE,oBAAoB,GAAG,KAAK,MACsB,EAAE,EACtD,EAAE;IACF,wDAAwD;IACxD,4DAA4D;IAC5D,sDAAsD;IACtD,OAAO,oBAAoB;QACzB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC;QACjC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;AACvC,CAAC,CAAA;AAZY,QAAA,MAAM,UAYlB","sourcesContent":["import { MinimatchOptions } from './index.js'\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape'> = {}\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n return windowsPathsNoEscape\n ? s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-cjs.d.ts","sourceRoot":"","sources":["../../src/index-cjs.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,kBAAoE"}
@@ -10,6 +10,7 @@ export interface MinimatchOptions {
10
10
  allowWindowsEscape?: boolean;
11
11
  partial?: boolean;
12
12
  dot?: boolean;
13
+ maxGlobstarRecursion?: number;
13
14
  nocase?: boolean;
14
15
  nocaseMagicOnly?: boolean;
15
16
  matchBase?: boolean;
@@ -57,11 +58,15 @@ export declare class Minimatch {
57
58
  globSet: string[];
58
59
  globParts: string[][];
59
60
  regexp: false | null | MMRegExp;
61
+ maxGlobstarRecursion: number;
60
62
  constructor(pattern: string, options?: MinimatchOptions);
61
63
  debug(..._: any[]): void;
62
64
  make(): void;
63
65
  parseNegate(): void;
64
66
  matchOne(file: string[], pattern: ParseReturn[], partial?: boolean): boolean;
67
+ _matchGlobstar(file: string[], pattern: ParseReturn[], partial: boolean, fileIndex: number, patternIndex: number): boolean;
68
+ _matchGlobStarBodySections(file: string[], bodySegments: [ParseReturn[], number][], fileIndex: number, bodyIndex: number, partial: boolean, globStarDepth: number, sawTail: boolean): boolean | null;
69
+ _matchOne(file: string[], pattern: ParseReturn[], partial: boolean, fileIndex: number, patternIndex: number): boolean;
65
70
  braceExpand(): string[];
66
71
  parse(pattern: string, isSub?: typeof SUBPARSE): ParseReturn | SubparseReturn;
67
72
  makeRe(): false | MMRegExp;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/dist/cjs/index.js CHANGED
@@ -213,6 +213,7 @@ class Minimatch {
213
213
  globSet;
214
214
  globParts;
215
215
  regexp;
216
+ maxGlobstarRecursion;
216
217
  constructor(pattern, options = {}) {
217
218
  assertValidPattern(pattern);
218
219
  options = options || {};
@@ -230,6 +231,8 @@ class Minimatch {
230
231
  this.comment = false;
231
232
  this.empty = false;
232
233
  this.partial = !!options.partial;
234
+ this.maxGlobstarRecursion = options.maxGlobstarRecursion !== undefined
235
+ ? options.maxGlobstarRecursion : 200;
233
236
  this.globSet = [];
234
237
  this.globParts = [];
235
238
  this.set = [];
@@ -352,7 +355,6 @@ class Minimatch {
352
355
  // out of pattern, then that's fine, as long as all
353
356
  // the parts match.
354
357
  matchOne(file, pattern, partial = false) {
355
- const options = this.options;
356
358
  // a UNC pattern like //?/c:/* can match a path like c:/x
357
359
  // and vice versa
358
360
  if (isWindows) {
@@ -389,99 +391,155 @@ class Minimatch {
389
391
  }
390
392
  }
391
393
  }
392
- this.debug('matchOne', this, { file, pattern });
393
- this.debug('matchOne', file.length, pattern.length);
394
- for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
394
+ if (pattern.indexOf(exports.GLOBSTAR) !== -1) {
395
+ return this._matchGlobstar(file, pattern, partial, 0, 0);
396
+ }
397
+ return this._matchOne(file, pattern, partial, 0, 0);
398
+ }
399
+ _matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
400
+ // find first globstar from patternIndex
401
+ let firstgs = -1;
402
+ for (let i = patternIndex; i < pattern.length; i++) {
403
+ if (pattern[i] === exports.GLOBSTAR) {
404
+ firstgs = i;
405
+ break;
406
+ }
407
+ }
408
+ // find last globstar
409
+ let lastgs = -1;
410
+ for (let i = pattern.length - 1; i >= 0; i--) {
411
+ if (pattern[i] === exports.GLOBSTAR) {
412
+ lastgs = i;
413
+ break;
414
+ }
415
+ }
416
+ const head = pattern.slice(patternIndex, firstgs);
417
+ const body = partial ? pattern.slice(firstgs + 1) : pattern.slice(firstgs + 1, lastgs);
418
+ const tail = partial ? [] : pattern.slice(lastgs + 1);
419
+ // check the head
420
+ if (head.length) {
421
+ const fileHead = file.slice(fileIndex, fileIndex + head.length);
422
+ if (!this._matchOne(fileHead, head, partial, 0, 0)) {
423
+ return false;
424
+ }
425
+ fileIndex += head.length;
426
+ }
427
+ // check the tail
428
+ let fileTailMatch = 0;
429
+ if (tail.length) {
430
+ if (tail.length + fileIndex > file.length)
431
+ return false;
432
+ const tailStart = file.length - tail.length;
433
+ if (this._matchOne(file, tail, partial, tailStart, 0)) {
434
+ fileTailMatch = tail.length;
435
+ }
436
+ else {
437
+ // affordance for stuff like a/**/* matching a/b/
438
+ if (file[file.length - 1] !== '' ||
439
+ fileIndex + tail.length === file.length) {
440
+ return false;
441
+ }
442
+ if (!this._matchOne(file, tail, partial, tailStart - 1, 0)) {
443
+ return false;
444
+ }
445
+ fileTailMatch = tail.length + 1;
446
+ }
447
+ }
448
+ // if body is empty (single ** between head and tail)
449
+ if (!body.length) {
450
+ let sawSome = !!fileTailMatch;
451
+ for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
452
+ const f = String(file[i]);
453
+ sawSome = true;
454
+ if (f === '.' ||
455
+ f === '..' ||
456
+ (!this.options.dot && f.startsWith('.'))) {
457
+ return false;
458
+ }
459
+ }
460
+ return partial || sawSome;
461
+ }
462
+ // split body into segments at each GLOBSTAR
463
+ const bodySegments = [[[], 0]];
464
+ let currentBody = bodySegments[0];
465
+ let nonGsParts = 0;
466
+ const nonGsPartsSums = [0];
467
+ for (const b of body) {
468
+ if (b === exports.GLOBSTAR) {
469
+ nonGsPartsSums.push(nonGsParts);
470
+ currentBody = [[], 0];
471
+ bodySegments.push(currentBody);
472
+ }
473
+ else {
474
+ currentBody[0].push(b);
475
+ nonGsParts++;
476
+ }
477
+ }
478
+ let idx = bodySegments.length - 1;
479
+ const fileLength = file.length - fileTailMatch;
480
+ for (const b of bodySegments) {
481
+ b[1] = fileLength - (nonGsPartsSums[idx--] + b[0].length);
482
+ }
483
+ return !!this._matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
484
+ }
485
+ // return false for "nope, not matching"
486
+ // return null for "not matching, cannot keep trying"
487
+ _matchGlobStarBodySections(file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
488
+ const bs = bodySegments[bodyIndex];
489
+ if (!bs) {
490
+ // just make sure there are no bad dots
491
+ for (let i = fileIndex; i < file.length; i++) {
492
+ sawTail = true;
493
+ const f = file[i];
494
+ if (f === '.' ||
495
+ f === '..' ||
496
+ (!this.options.dot && f.startsWith('.'))) {
497
+ return false;
498
+ }
499
+ }
500
+ return sawTail;
501
+ }
502
+ const [body, after] = bs;
503
+ while (fileIndex <= after) {
504
+ const m = this._matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
505
+ // if limit exceeded, no match. intentional false negative,
506
+ // acceptable break in correctness for security.
507
+ if (m && globStarDepth < this.maxGlobstarRecursion) {
508
+ const sub = this._matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
509
+ if (sub !== false) {
510
+ return sub;
511
+ }
512
+ }
513
+ const f = file[fileIndex];
514
+ if (f === '.' ||
515
+ f === '..' ||
516
+ (!this.options.dot && f.startsWith('.'))) {
517
+ return false;
518
+ }
519
+ fileIndex++;
520
+ }
521
+ return partial || null;
522
+ }
523
+ _matchOne(file, pattern, partial, fileIndex, patternIndex) {
524
+ let fi;
525
+ let pi;
526
+ let fl;
527
+ let pl;
528
+ for (fi = fileIndex,
529
+ pi = patternIndex,
530
+ fl = file.length,
531
+ pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
395
532
  this.debug('matchOne loop');
396
- var p = pattern[pi];
397
- var f = file[fi];
533
+ const p = pattern[pi];
534
+ const f = file[fi];
398
535
  this.debug(pattern, p, f);
399
536
  // should be impossible.
400
537
  // some invalid regexp stuff in the set.
401
538
  /* c8 ignore start */
402
- if (p === false) {
539
+ if (p === false || p === exports.GLOBSTAR) {
403
540
  return false;
404
541
  }
405
542
  /* c8 ignore stop */
406
- if (p === exports.GLOBSTAR) {
407
- this.debug('GLOBSTAR', [pattern, p, f]);
408
- // "**"
409
- // a/**/b/**/c would match the following:
410
- // a/b/x/y/z/c
411
- // a/x/y/z/b/c
412
- // a/b/x/b/x/c
413
- // a/b/c
414
- // To do this, take the rest of the pattern after
415
- // the **, and see if it would match the file remainder.
416
- // If so, return success.
417
- // If not, the ** "swallows" a segment, and try again.
418
- // This is recursively awful.
419
- //
420
- // a/**/b/**/c matching a/b/x/y/z/c
421
- // - a matches a
422
- // - doublestar
423
- // - matchOne(b/x/y/z/c, b/**/c)
424
- // - b matches b
425
- // - doublestar
426
- // - matchOne(x/y/z/c, c) -> no
427
- // - matchOne(y/z/c, c) -> no
428
- // - matchOne(z/c, c) -> no
429
- // - matchOne(c, c) yes, hit
430
- var fr = fi;
431
- var pr = pi + 1;
432
- if (pr === pl) {
433
- this.debug('** at the end');
434
- // a ** at the end will just swallow the rest.
435
- // We have found a match.
436
- // however, it will not swallow /.x, unless
437
- // options.dot is set.
438
- // . and .. are *never* matched by **, for explosively
439
- // exponential reasons.
440
- for (; fi < fl; fi++) {
441
- if (file[fi] === '.' ||
442
- file[fi] === '..' ||
443
- (!options.dot && file[fi].charAt(0) === '.'))
444
- return false;
445
- }
446
- return true;
447
- }
448
- // ok, let's see if we can swallow whatever we can.
449
- while (fr < fl) {
450
- var swallowee = file[fr];
451
- this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
452
- // XXX remove this slice. Just pass the start index.
453
- if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
454
- this.debug('globstar found match!', fr, fl, swallowee);
455
- // found a match.
456
- return true;
457
- }
458
- else {
459
- // can't swallow "." or ".." ever.
460
- // can only swallow ".foo" when explicitly asked.
461
- if (swallowee === '.' ||
462
- swallowee === '..' ||
463
- (!options.dot && swallowee.charAt(0) === '.')) {
464
- this.debug('dot detected!', file, fr, pattern, pr);
465
- break;
466
- }
467
- // ** swallows a segment, and continue.
468
- this.debug('globstar swallow a segment, and continue');
469
- fr++;
470
- }
471
- }
472
- // no match was found.
473
- // However, in partial mode, we can't say this is necessarily over.
474
- /* c8 ignore start */
475
- if (partial) {
476
- // ran out of file
477
- this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
478
- if (fr === fl) {
479
- return true;
480
- }
481
- }
482
- /* c8 ignore stop */
483
- return false;
484
- }
485
543
  // something other than **
486
544
  // non-magic patterns just have to match exactly
487
545
  // patterns with magic have been turned into regexps.
@@ -497,16 +555,6 @@ class Minimatch {
497
555
  if (!hit)
498
556
  return false;
499
557
  }
500
- // Note: ending in / means that we'll get a final ""
501
- // at the end of the pattern. This can only match a
502
- // corresponding "" at the end of the file.
503
- // If the file ends in /, then it can only match a
504
- // a pattern that ends in /, unless the pattern just
505
- // doesn't have any more for it. But, a/b/ should *not*
506
- // match "a/b/*", even though "" matches against the
507
- // [^/]*? pattern, except in partial mode, where it might
508
- // simply not be reached yet.
509
- // However, a/b/ should still satisfy a/*
510
558
  // now either we fell off the end of the pattern, or we're done.
511
559
  if (fi === fl && pi === pl) {
512
560
  // ran out of pattern and filename at the same time.