From 1289c1bf3ce845f82b5fa3b19b0e82aa107d9f49 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Thu, 17 Nov 2022 16:13:06 -0700 Subject: [PATCH] fix: Ensure glob-like characters are escaped in cwd & root options --- index.js | 30 ++++++++++++++++++++++++++++-- test.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 268fc47..1635d24 100644 --- a/index.js +++ b/index.js @@ -9,16 +9,20 @@ module.exports = function(glob, options) { var opts = options || {}; // ensure cwd is absolute - var cwd = path.resolve(opts.cwd ? opts.cwd : process.cwd()); + var cwd = unescape(opts.cwd ? opts.cwd : process.cwd()) + cwd = path.resolve(cwd); cwd = unixify(cwd); + cwd = escape(cwd); var rootDir = opts.root; // if `options.root` is defined, ensure it's absolute if (rootDir) { + rootDir = unescape(rootDir); rootDir = unixify(rootDir); if (process.platform === 'win32' || !isAbsolute(rootDir)) { rootDir = unixify(path.resolve(rootDir)); } + rootDir = escape(rootDir); } // trim starting ./ from glob patterns @@ -54,8 +58,30 @@ module.exports = function(glob, options) { return ing.negated ? '!' + glob : glob; }; +function escape(path) { + return path + .replace(/\[(.*?)\]/g, "\\[$1\\]") + .replace(/\((.*?)\)/g, "\\($1\\)") + .replace(/\{(.*?)\}/g, "\\{$1\\}") + .replace(/\*/g, "\\*") + .replace(/\!/g, "\\!") + .replace(/\?/g, "\\?"); +} + +function unescape(path) { + return path + .replace(/\\\[(.*?)\\\]/g, "[$1]") + .replace(/\\\((.*?)\\\)/g, "($1)") + .replace(/\\\{(.*?)\\\}/g, "{$1}") + .replace(/\\\*/g, "*") + .replace(/\\\!/g, "!") + .replace(/\\\?/g, "?"); +} + +// Before calling unixify, we remove the escapes and then +// we add them back afterwards to avoid double-escaping function unixify(filepath) { - return filepath.replace(/\\/g, '/'); + return filepath.replace(/\\/g, "/"); } function join(dir, glob) { diff --git a/test.js b/test.js index 4ecbb08..1c65804 100644 --- a/test.js +++ b/test.js @@ -61,6 +61,27 @@ describe('resolve', function () { assert.equal(actual, unixify(path.resolve('foo/a/*.js'))); }); + it('should escape glob patterns in an absolute cwd', function () { + actual = resolve('a/*.js', {cwd: '/(foo)/[bar]/{baz}/*/**/?/!'}); + var expected = unixify(path.resolve('/(foo)/[bar]/{baz}/*/**/?/!/a/*.js')) + .replace('/(foo)/[bar]/{baz}/*/**/?/!', '/\\(foo\\)/\\[bar\\]/\\{baz\\}/\\*/\\*\\*/\\?/\\!'); + assert.equal(actual, expected); + }); + + it('should escape glob patterns in a relative cwd', function () { + actual = resolve('a/*.js', {cwd: '(foo)/[bar]/{baz}/*/**/?/!'}); + var expected = unixify(path.resolve('(foo)/[bar]/{baz}/*/**/?/!/a/*.js')) + .replace('(foo)/[bar]/{baz}/*/**/?/!', '\\(foo\\)/\\[bar\\]/\\{baz\\}/\\*/\\*\\*/\\?/\\!'); + assert.equal(actual, expected); + }); + + it('avoids double escaping in cwd', function () { + actual = resolve('a/*.js', {cwd: '/\\(foo\\)/\\[bar\\]/\\{baz\\}/\\*/\\*\\*/\\?/\\!'}); + var expected = unixify(path.resolve('/(foo)/[bar]/{baz}/*/**/?/!/a/*.js')) + .replace('/(foo)/[bar]/{baz}/*/**/?/!', '/\\(foo\\)/\\[bar\\]/\\{baz\\}/\\*/\\*\\*/\\?/\\!'); + assert.equal(actual, expected); + }); + it('should make a negative glob absolute from a cwd', function () { actual = resolve('!a/*.js', {cwd: 'foo'}); assert.equal(actual, '!' + unixify(path.resolve('foo/a/*.js'))); @@ -76,6 +97,27 @@ describe('resolve', function () { assert.equal(actual, unixify(path.resolve('/a/*.js'))); }); + it('should escape glob patterns in an absolute root', function () { + actual = resolve('/a/*.js', {root: '/(foo)/[bar]/{baz}/*/**/?/!'}); + var expected = unixify(path.resolve('/(foo)/[bar]/{baz}/*/**/?/!/a/*.js')) + .replace('/(foo)/[bar]/{baz}/*/**/?/!', '/\\(foo\\)/\\[bar\\]/\\{baz\\}/\\*/\\*\\*/\\?/\\!'); + assert.equal(actual, expected); + }); + + it('should escape glob patterns in a relative root', function () { + actual = resolve('/a/*.js', {root: '(foo)/[bar]/{baz}/*/**/?/!'}); + var expected = unixify(path.resolve('(foo)/[bar]/{baz}/*/**/?/!/a/*.js')) + .replace('(foo)/[bar]/{baz}/*/**/?/!', '\\(foo\\)/\\[bar\\]/\\{baz\\}/\\*/\\*\\*/\\?/\\!'); + assert.equal(actual, expected); + }); + + it('avoids double escaping in root', function () { + actual = resolve('/a/*.js', {root: '/\\(foo\\)/\\[bar\\]/\\{baz\\}/\\*/\\*\\*/\\?/\\!'}); + var expected = unixify(path.resolve('/(foo)/[bar]/{baz}/*/**/?/!/a/*.js')) + .replace('/(foo)/[bar]/{baz}/*/**/?/!', '/\\(foo\\)/\\[bar\\]/\\{baz\\}/\\*/\\*\\*/\\?/\\!'); + assert.equal(actual, expected); + }); + it('should make a glob absolute from a negative root path', function () { actual = resolve('!/a/*.js', {root: 'foo'}); assert.equal(actual, '!' + unixify(path.resolve('foo/a/*.js')));