minimatch
Advanced tools
+152
-97
@@ -145,2 +145,4 @@ module.exports = minimatch | ||
| this.options = options | ||
| this.maxGlobstarRecursion = options.maxGlobstarRecursion !== undefined | ||
| ? options.maxGlobstarRecursion : 200 | ||
| this.set = [] | ||
@@ -791,106 +793,170 @@ this.pattern = pattern | ||
| Minimatch.prototype.matchOne = function (file, pattern, partial) { | ||
| var options = this.options | ||
| if (pattern.indexOf(GLOBSTAR) !== -1) { | ||
| return this._matchGlobstar(file, pattern, partial, 0, 0) | ||
| } | ||
| return this._matchOne(file, pattern, partial, 0, 0) | ||
| } | ||
| this.debug('matchOne', | ||
| { 'this': this, file: file, pattern: pattern }) | ||
| Minimatch.prototype._matchGlobstar = function (file, pattern, partial, fileIndex, patternIndex) { | ||
| var i | ||
| this.debug('matchOne', file.length, pattern.length) | ||
| // find first globstar from patternIndex | ||
| var firstgs = -1 | ||
| for (i = patternIndex; i < pattern.length; i++) { | ||
| if (pattern[i] === GLOBSTAR) { firstgs = i; break } | ||
| } | ||
| for (var fi = 0, | ||
| pi = 0, | ||
| fl = file.length, | ||
| pl = pattern.length | ||
| ; (fi < fl) && (pi < pl) | ||
| ; fi++, pi++) { | ||
| this.debug('matchOne loop') | ||
| var p = pattern[pi] | ||
| var f = file[fi] | ||
| // find last globstar | ||
| var lastgs = -1 | ||
| for (i = pattern.length - 1; i >= 0; i--) { | ||
| if (pattern[i] === GLOBSTAR) { lastgs = i; break } | ||
| } | ||
| this.debug(pattern, p, f) | ||
| var head = pattern.slice(patternIndex, firstgs) | ||
| var body = pattern.slice(firstgs + 1, lastgs) | ||
| var tail = pattern.slice(lastgs + 1) | ||
| // should be impossible. | ||
| // some invalid regexp stuff in the set. | ||
| /* istanbul ignore if */ | ||
| if (p === false) return false | ||
| // check the head | ||
| if (head.length) { | ||
| var fileHead = file.slice(fileIndex, fileIndex + head.length) | ||
| if (!this._matchOne(fileHead, head, partial, 0, 0)) { | ||
| return false | ||
| } | ||
| fileIndex += head.length | ||
| } | ||
| if (p === GLOBSTAR) { | ||
| this.debug('GLOBSTAR', [pattern, p, f]) | ||
| // check the tail | ||
| var fileTailMatch = 0 | ||
| if (tail.length) { | ||
| if (tail.length + fileIndex > file.length) return false | ||
| // "**" | ||
| // a/**/b/**/c would match the following: | ||
| // a/b/x/y/z/c | ||
| // a/x/y/z/b/c | ||
| // a/b/x/b/x/c | ||
| // a/b/c | ||
| // To do this, take the rest of the pattern after | ||
| // the **, and see if it would match the file remainder. | ||
| // If so, return success. | ||
| // If not, the ** "swallows" a segment, and try again. | ||
| // This is recursively awful. | ||
| // | ||
| // a/**/b/**/c matching a/b/x/y/z/c | ||
| // - a matches a | ||
| // - doublestar | ||
| // - matchOne(b/x/y/z/c, b/**/c) | ||
| // - b matches b | ||
| // - doublestar | ||
| // - matchOne(x/y/z/c, c) -> no | ||
| // - matchOne(y/z/c, c) -> no | ||
| // - matchOne(z/c, c) -> no | ||
| // - matchOne(c, c) yes, hit | ||
| var fr = fi | ||
| var pr = pi + 1 | ||
| if (pr === pl) { | ||
| this.debug('** at the end') | ||
| // a ** at the end will just swallow the rest. | ||
| // We have found a match. | ||
| // however, it will not swallow /.x, unless | ||
| // options.dot is set. | ||
| // . and .. are *never* matched by **, for explosively | ||
| // exponential reasons. | ||
| for (; fi < fl; fi++) { | ||
| if (file[fi] === '.' || file[fi] === '..' || | ||
| (!options.dot && file[fi].charAt(0) === '.')) return false | ||
| } | ||
| return true | ||
| var tailStart = file.length - tail.length | ||
| if (this._matchOne(file, tail, partial, tailStart, 0)) { | ||
| fileTailMatch = tail.length | ||
| } else { | ||
| // affordance for stuff like a/**/* matching a/b/ | ||
| if (file[file.length - 1] !== '' || | ||
| fileIndex + tail.length === file.length) { | ||
| return false | ||
| } | ||
| tailStart-- | ||
| if (!this._matchOne(file, tail, partial, tailStart, 0)) { | ||
| return false | ||
| } | ||
| fileTailMatch = tail.length + 1 | ||
| } | ||
| } | ||
| // ok, let's see if we can swallow whatever we can. | ||
| while (fr < fl) { | ||
| var swallowee = file[fr] | ||
| // if body is empty (single ** between head and tail) | ||
| if (!body.length) { | ||
| var sawSome = !!fileTailMatch | ||
| for (i = fileIndex; i < file.length - fileTailMatch; i++) { | ||
| var f = String(file[i]) | ||
| sawSome = true | ||
| if (f === '.' || f === '..' || | ||
| (!this.options.dot && f.charAt(0) === '.')) { | ||
| return false | ||
| } | ||
| } | ||
| return sawSome | ||
| } | ||
| this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) | ||
| // split body into segments at each GLOBSTAR | ||
| var bodySegments = [[[], 0]] | ||
| var currentBody = bodySegments[0] | ||
| var nonGsParts = 0 | ||
| var nonGsPartsSums = [0] | ||
| for (var bi = 0; bi < body.length; bi++) { | ||
| var b = body[bi] | ||
| if (b === GLOBSTAR) { | ||
| nonGsPartsSums.push(nonGsParts) | ||
| currentBody = [[], 0] | ||
| bodySegments.push(currentBody) | ||
| } else { | ||
| currentBody[0].push(b) | ||
| nonGsParts++ | ||
| } | ||
| } | ||
| // XXX remove this slice. Just pass the start index. | ||
| if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { | ||
| this.debug('globstar found match!', fr, fl, swallowee) | ||
| // found a match. | ||
| return true | ||
| } else { | ||
| // can't swallow "." or ".." ever. | ||
| // can only swallow ".foo" when explicitly asked. | ||
| if (swallowee === '.' || swallowee === '..' || | ||
| (!options.dot && swallowee.charAt(0) === '.')) { | ||
| this.debug('dot detected!', file, fr, pattern, pr) | ||
| break | ||
| } | ||
| var idx = bodySegments.length - 1 | ||
| var fileLength = file.length - fileTailMatch | ||
| for (var si = 0; si < bodySegments.length; si++) { | ||
| bodySegments[si][1] = fileLength - | ||
| (nonGsPartsSums[idx--] + bodySegments[si][0].length) | ||
| } | ||
| // ** swallows a segment, and continue. | ||
| this.debug('globstar swallow a segment, and continue') | ||
| fr++ | ||
| } | ||
| return !!this._matchGlobStarBodySections( | ||
| file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch | ||
| ) | ||
| } | ||
| // return false for "nope, not matching" | ||
| // return null for "not matching, cannot keep trying" | ||
| Minimatch.prototype._matchGlobStarBodySections = function ( | ||
| file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail | ||
| ) { | ||
| var bs = bodySegments[bodyIndex] | ||
| if (!bs) { | ||
| // just make sure there are no bad dots | ||
| for (var i = fileIndex; i < file.length; i++) { | ||
| sawTail = true | ||
| var f = file[i] | ||
| if (f === '.' || f === '..' || | ||
| (!this.options.dot && f.charAt(0) === '.')) { | ||
| return false | ||
| } | ||
| } | ||
| return sawTail | ||
| } | ||
| // no match was found. | ||
| // However, in partial mode, we can't say this is necessarily over. | ||
| // If there's more *pattern* left, then | ||
| /* istanbul ignore if */ | ||
| if (partial) { | ||
| // ran out of file | ||
| this.debug('\n>>> no match, partial?', file, fr, pattern, pr) | ||
| if (fr === fl) return true | ||
| var body = bs[0] | ||
| var after = bs[1] | ||
| while (fileIndex <= after) { | ||
| var m = this._matchOne( | ||
| file.slice(0, fileIndex + body.length), | ||
| body, | ||
| partial, | ||
| fileIndex, | ||
| 0 | ||
| ) | ||
| // if limit exceeded, no match. intentional false negative, | ||
| // acceptable break in correctness for security. | ||
| if (m && globStarDepth < this.maxGlobstarRecursion) { | ||
| var sub = this._matchGlobStarBodySections( | ||
| file, bodySegments, | ||
| fileIndex + body.length, bodyIndex + 1, | ||
| partial, globStarDepth + 1, sawTail | ||
| ) | ||
| if (sub !== false) { | ||
| return sub | ||
| } | ||
| } | ||
| var f = file[fileIndex] | ||
| if (f === '.' || f === '..' || | ||
| (!this.options.dot && f.charAt(0) === '.')) { | ||
| return false | ||
| } | ||
| fileIndex++ | ||
| } | ||
| return null | ||
| } | ||
| Minimatch.prototype._matchOne = function (file, pattern, partial, fileIndex, patternIndex) { | ||
| var fi, pi, fl, pl | ||
| for ( | ||
| fi = fileIndex, pi = patternIndex, fl = file.length, pl = pattern.length | ||
| ; (fi < fl) && (pi < pl) | ||
| ; fi++, pi++ | ||
| ) { | ||
| this.debug('matchOne loop') | ||
| var p = pattern[pi] | ||
| var f = file[fi] | ||
| this.debug(pattern, p, f) | ||
| // should be impossible. | ||
| // some invalid regexp stuff in the set. | ||
| /* istanbul ignore if */ | ||
| if (p === false || p === GLOBSTAR) return false | ||
| // something other than ** | ||
@@ -911,13 +977,2 @@ // non-magic patterns just have to match exactly | ||
| // Note: ending in / means that we'll get a final "" | ||
| // at the end of the pattern. This can only match a | ||
| // corresponding "" at the end of the file. | ||
| // If the file ends in /, then it can only match a | ||
| // a pattern that ends in /, unless the pattern just | ||
| // doesn't have any more for it. But, a/b/ should *not* | ||
| // match "a/b/*", even though "" matches against the | ||
| // [^/]*? pattern, except in partial mode, where it might | ||
| // simply not be reached yet. | ||
| // However, a/b/ should still satisfy a/* | ||
| // now either we fell off the end of the pattern, or we're done. | ||
@@ -924,0 +979,0 @@ if (fi === fl && pi === pl) { |
+1
-1
@@ -5,3 +5,3 @@ { | ||
| "description": "a glob matcher in javascript", | ||
| "version": "3.1.3", | ||
| "version": "3.1.4", | ||
| "publishConfig": { | ||
@@ -8,0 +8,0 @@ "tag": "legacy-v3" |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
36020
2.87%852
6.5%4
100%