diff --git a/lib/tmp.js b/lib/tmp.js index 84aa1c5..162dca1 100644 --- a/lib/tmp.js +++ b/lib/tmp.js @@ -18,34 +18,24 @@ const _c = { fs: fs.constants, os: os.constants }; /* * The working inner variables. */ -const - // the random characters to choose from +const // the random characters to choose from RANDOM_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', - TEMPLATE_PATTERN = /XXXXXX/, - DEFAULT_TRIES = 3, - CREATE_FLAGS = (_c.O_CREAT || _c.fs.O_CREAT) | (_c.O_EXCL || _c.fs.O_EXCL) | (_c.O_RDWR || _c.fs.O_RDWR), - // constants are off on the windows platform and will not match the actual errno codes IS_WIN32 = os.platform() === 'win32', EBADF = _c.EBADF || _c.os.errno.EBADF, ENOENT = _c.ENOENT || _c.os.errno.ENOENT, - DIR_MODE = 0o700 /* 448 */, FILE_MODE = 0o600 /* 384 */, - EXIT = 'exit', - // this will hold the objects need to be removed on exit _removeObjects = [], - // API change in fs.rmdirSync leads to error when passing in a second parameter, e.g. the callback FN_RMDIR_SYNC = fs.rmdirSync.bind(fs); -let - _gracefulCleanup = false; +let _gracefulCleanup = false; /** * Recursively remove a directory and its contents. @@ -75,38 +65,35 @@ function FN_RIMRAF_SYNC(dirPath) { * @param {?tmpNameCallback} callback the callback function */ function tmpName(options, callback) { - const - args = _parseArguments(options, callback), + const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; - try { - _assertAndSanitizeOptions(opts); - } catch (err) { - return cb(err); - } + _assertAndSanitizeOptions(opts, function (err, sanitizedOptions) { + if (err) return cb(err); - let tries = opts.tries; - (function _getUniqueName() { - try { - const name = _generateTmpName(opts); + let tries = sanitizedOptions.tries; + (function _getUniqueName() { + try { + const name = _generateTmpName(sanitizedOptions); - // check whether the path exists then retry if needed - fs.stat(name, function (err) { - /* istanbul ignore else */ - if (!err) { + // check whether the path exists then retry if needed + fs.stat(name, function (err) { /* istanbul ignore else */ - if (tries-- > 0) return _getUniqueName(); + if (!err) { + /* istanbul ignore else */ + if (tries-- > 0) return _getUniqueName(); - return cb(new Error('Could not get a unique tmp filename, max tries reached ' + name)); - } + return cb(new Error('Could not get a unique tmp filename, max tries reached ' + name)); + } - cb(null, name); - }); - } catch (err) { - cb(err); - } - }()); + cb(null, name); + }); + } catch (err) { + cb(err); + } + })(); + }); } /** @@ -117,15 +104,14 @@ function tmpName(options, callback) { * @throws {Error} if the options are invalid or could not generate a filename */ function tmpNameSync(options) { - const - args = _parseArguments(options), + const args = _parseArguments(options), opts = args[0]; - _assertAndSanitizeOptions(opts); + const sanitizedOptions = _assertAndSanitizeOptionsSync(opts); - let tries = opts.tries; + let tries = sanitizedOptions.tries; do { - const name = _generateTmpName(opts); + const name = _generateTmpName(sanitizedOptions); try { fs.statSync(name); } catch (e) { @@ -143,8 +129,7 @@ function tmpNameSync(options) { * @param {?fileCallback} callback */ function file(options, callback) { - const - args = _parseArguments(options, callback), + const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; @@ -181,13 +166,12 @@ function file(options, callback) { * @throws {Error} if cannot create a file */ function fileSync(options) { - const - args = _parseArguments(options), + const args = _parseArguments(options), opts = args[0]; const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor; const name = tmpNameSync(opts); - var fd = fs.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE); + let fd = fs.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE); /* istanbul ignore else */ if (opts.discardDescriptor) { fs.closeSync(fd); @@ -208,8 +192,7 @@ function fileSync(options) { * @param {?dirCallback} callback */ function dir(options, callback) { - const - args = _parseArguments(options, callback), + const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; @@ -236,8 +219,7 @@ function dir(options, callback) { * @throws {Error} if it cannot create a directory */ function dirSync(options) { - const - args = _parseArguments(options), + const args = _parseArguments(options), opts = args[0]; const name = tmpNameSync(opts); @@ -288,8 +270,7 @@ function _removeFileSync(fdPath) { } finally { try { fs.unlinkSync(fdPath[1]); - } - catch (e) { + } catch (e) { // reraise any unanticipated error if (!_isENOENT(e)) rethrownException = e; } @@ -361,7 +342,6 @@ function _prepareRemoveCallback(removeFunction, fileOrDirName, sync, cleanupCall // if sync is true, the next parameter will be ignored return function _cleanupCallback(next) { - /* istanbul ignore else */ if (!called) { // remove cleanupCallback from cache @@ -374,7 +354,7 @@ function _prepareRemoveCallback(removeFunction, fileOrDirName, sync, cleanupCall if (sync || removeFunction === FN_RMDIR_SYNC || removeFunction === FN_RIMRAF_SYNC) { return removeFunction(fileOrDirName); } else { - return removeFunction(fileOrDirName, next || function() {}); + return removeFunction(fileOrDirName, next || function () {}); } } }; @@ -409,8 +389,7 @@ function _garbageCollector() { * @private */ function _randomChars(howMany) { - let - value = [], + let value = [], rnd = null; // make sure that we do not fail because we ran out of entropy @@ -420,24 +399,13 @@ function _randomChars(howMany) { rnd = crypto.pseudoRandomBytes(howMany); } - for (var i = 0; i < howMany; i++) { + for (let i = 0; i < howMany; i++) { value.push(RANDOM_CHARS[rnd[i] % RANDOM_CHARS.length]); } return value.join(''); } -/** - * Helper which determines whether a string s is blank, that is undefined, or empty or null. - * - * @private - * @param {string} s - * @returns {Boolean} true whether the string s is blank, false otherwise - */ -function _isBlank(s) { - return s === null || _isUndefined(s) || !s.trim(); -} - /** * Checks whether the `obj` parameter is defined or not. * @@ -479,6 +447,51 @@ function _parseArguments(options, callback) { return [actualOptions, callback]; } +/** + * Resolve the specified path name in respect to tmpDir. + * + * The specified name might include relative path components, e.g. ../ + * so we need to resolve in order to be sure that is is located inside tmpDir + * + * @private + */ +function _resolvePath(name, tmpDir, cb) { + const pathToResolve = path.isAbsolute(name) ? name : path.join(tmpDir, name); + + fs.stat(pathToResolve, function (err) { + if (err) { + fs.realpath(path.dirname(pathToResolve), function (err, parentDir) { + if (err) return cb(err); + + cb(null, path.join(parentDir, path.basename(pathToResolve))); + }); + } else { + fs.realpath(path, cb); + } + }); +} + +/** + * Resolve the specified path name in respect to tmpDir. + * + * The specified name might include relative path components, e.g. ../ + * so we need to resolve in order to be sure that is is located inside tmpDir + * + * @private + */ +function _resolvePathSync(name, tmpDir) { + const pathToResolve = path.isAbsolute(name) ? name : path.join(tmpDir, name); + + try { + fs.statSync(pathToResolve); + return fs.realpathSync(pathToResolve); + } catch (_err) { + const parentDir = fs.realpathSync(path.dirname(pathToResolve)); + + return path.join(parentDir, path.basename(pathToResolve)); + } +} + /** * Generates a new temporary name. * @@ -487,16 +500,17 @@ function _parseArguments(options, callback) { * @private */ function _generateTmpName(opts) { - const tmpDir = opts.tmpdir; /* istanbul ignore else */ - if (!_isUndefined(opts.name)) + if (!_isUndefined(opts.name)) { return path.join(tmpDir, opts.dir, opts.name); + } /* istanbul ignore else */ - if (!_isUndefined(opts.template)) + if (!_isUndefined(opts.template)) { return path.join(tmpDir, opts.dir, opts.template).replace(TEMPLATE_PATTERN, _randomChars(6)); + } // prefix and postfix const name = [ @@ -512,33 +526,32 @@ function _generateTmpName(opts) { } /** - * Asserts whether the specified options are valid, also sanitizes options and provides sane defaults for missing - * options. + * Asserts and sanitizes the basic options. * - * @param {Options} options * @private */ -function _assertAndSanitizeOptions(options) { +function _assertOptionsBase(options) { + if (!_isUndefined(options.name)) { + const name = options.name; - options.tmpdir = _getTmpDir(options); + // assert that name is not absolute and does not contain a path + if (path.isAbsolute(name)) throw new Error(`name option must not contain an absolute path, found "${name}".`); - const tmpDir = options.tmpdir; + // must not fail on valid . or .. or similar such constructs + const basename = path.basename(name); + if (basename === '..' || basename === '.' || basename !== name) + throw new Error(`name option must not contain a path, found "${name}".`); + } /* istanbul ignore else */ - if (!_isUndefined(options.name)) - _assertIsRelative(options.name, 'name', tmpDir); - /* istanbul ignore else */ - if (!_isUndefined(options.dir)) - _assertIsRelative(options.dir, 'dir', tmpDir); - /* istanbul ignore else */ - if (!_isUndefined(options.template)) { - _assertIsRelative(options.template, 'template', tmpDir); - if (!options.template.match(TEMPLATE_PATTERN)) - throw new Error(`Invalid template, found "${options.template}".`); + if (!_isUndefined(options.template) && !options.template.match(TEMPLATE_PATTERN)) { + throw new Error(`Invalid template, found "${options.template}".`); } + /* istanbul ignore else */ - if (!_isUndefined(options.tries) && isNaN(options.tries) || options.tries < 0) + if ((!_isUndefined(options.tries) && isNaN(options.tries)) || options.tries < 0) { throw new Error(`Invalid tries, found "${options.tries}".`); + } // if a name was specified we will try once options.tries = _isUndefined(options.name) ? options.tries || DEFAULT_TRIES : 1; @@ -547,65 +560,103 @@ function _assertAndSanitizeOptions(options) { options.discardDescriptor = !!options.discardDescriptor; options.unsafeCleanup = !!options.unsafeCleanup; - // sanitize dir, also keep (multiple) blanks if the user, purportedly sane, requests us to - options.dir = _isUndefined(options.dir) ? '' : path.relative(tmpDir, _resolvePath(options.dir, tmpDir)); - options.template = _isUndefined(options.template) ? undefined : path.relative(tmpDir, _resolvePath(options.template, tmpDir)); - // sanitize further if template is relative to options.dir - options.template = _isBlank(options.template) ? undefined : path.relative(options.dir, options.template); - // for completeness' sake only, also keep (multiple) blanks if the user, purportedly sane, requests us to - options.name = _isUndefined(options.name) ? undefined : options.name; options.prefix = _isUndefined(options.prefix) ? '' : options.prefix; options.postfix = _isUndefined(options.postfix) ? '' : options.postfix; } /** - * Resolve the specified path name in respect to tmpDir. + * Gets the relative directory to tmpDir. * - * The specified name might include relative path components, e.g. ../ - * so we need to resolve in order to be sure that is is located inside tmpDir + * @private + */ +function _getRelativePath(option, name, tmpDir, cb) { + if (_isUndefined(name)) return cb(null); + + _resolvePath(name, tmpDir, function (err, resolvedPath) { + if (err) return cb(err); + + const relativePath = path.relative(tmpDir, resolvedPath); + + if (!resolvedPath.startsWith(tmpDir)) { + return cb(new Error(`${option} option must be relative to "${tmpDir}", found "${relativePath}".`)); + } + + cb(null, relativePath); + }); +} + +/** + * Gets the relative path to tmpDir. * - * @param name - * @param tmpDir - * @returns {string} * @private */ -function _resolvePath(name, tmpDir) { - if (name.startsWith(tmpDir)) { - return path.resolve(name); - } else { - return path.resolve(path.join(tmpDir, name)); +function _getRelativePathSync(option, name, tmpDir) { + if (_isUndefined(name)) return; + + const resolvedPath = _resolvePathSync(name, tmpDir); + const relativePath = path.relative(tmpDir, resolvedPath); + + if (!resolvedPath.startsWith(tmpDir)) { + throw new Error(`${option} option must be relative to "${tmpDir}", found "${relativePath}".`); } + + return relativePath; } /** - * Asserts whether specified name is relative to the specified tmpDir. + * Asserts whether the specified options are valid, also sanitizes options and provides sane defaults for missing + * options. * - * @param {string} name - * @param {string} option - * @param {string} tmpDir - * @throws {Error} * @private */ -function _assertIsRelative(name, option, tmpDir) { - if (option === 'name') { - // assert that name is not absolute and does not contain a path - if (path.isAbsolute(name)) - throw new Error(`${option} option must not contain an absolute path, found "${name}".`); - // must not fail on valid . or .. or similar such constructs - let basename = path.basename(name); - if (basename === '..' || basename === '.' || basename !== name) - throw new Error(`${option} option must not contain a path, found "${name}".`); - } - else { // if (option === 'dir' || option === 'template') { - // assert that dir or template are relative to tmpDir - if (path.isAbsolute(name) && !name.startsWith(tmpDir)) { - throw new Error(`${option} option must be relative to "${tmpDir}", found "${name}".`); +function _assertAndSanitizeOptions(options, cb) { + _getTmpDir(options, function (err, tmpDir) { + if (err) return cb(err); + + options.tmpdir = tmpDir; + + try { + _assertOptionsBase(options, tmpDir); + } catch (err) { + return cb(err); } - let resolvedPath = _resolvePath(name, tmpDir); - if (!resolvedPath.startsWith(tmpDir)) - throw new Error(`${option} option must be relative to "${tmpDir}", found "${resolvedPath}".`); - } + + // sanitize dir, also keep (multiple) blanks if the user, purportedly sane, requests us to + _getRelativePath('dir', options.dir, tmpDir, function (err, dir) { + if (err) return cb(err); + + options.dir = _isUndefined(dir) ? '' : dir; + + // sanitize further if template is relative to options.dir + _getRelativePath('template', options.template, tmpDir, function (err, template) { + if (err) return cb(err); + + options.template = template; + + cb(null, options); + }); + }); + }); +} + +/** + * Asserts whether the specified options are valid, also sanitizes options and provides sane defaults for missing + * options. + * + * @private + */ +function _assertAndSanitizeOptionsSync(options) { + const tmpDir = (options.tmpdir = _getTmpDirSync(options)); + + _assertOptionsBase(options, tmpDir); + + const dir = _getRelativePathSync('dir', options.dir, tmpDir); + options.dir = _isUndefined(dir) ? '' : dir; + + options.template = _getRelativePathSync('template', options.template, tmpDir); + + return options; } /** @@ -663,11 +714,18 @@ function setGracefulCleanup() { * Returns the currently configured tmp dir from os.tmpdir(). * * @private - * @param {?Options} options - * @returns {string} the currently configured tmp dir */ -function _getTmpDir(options) { - return path.resolve(options && options.tmpdir || os.tmpdir()); +function _getTmpDir(options, cb) { + return fs.realpath((options && options.tmpdir) || os.tmpdir(), cb); +} + +/** + * Returns the currently configured tmp dir from os.tmpdir(). + * + * @private + */ +function _getTmpDirSync(options) { + return fs.realpathSync((options && options.tmpdir) || os.tmpdir()); } // Install process exit listener @@ -768,7 +826,7 @@ Object.defineProperty(module.exports, 'tmpdir', { enumerable: true, configurable: false, get: function () { - return _getTmpDir(); + return _getTmpDirSync(); } }); diff --git a/package-lock.json b/package-lock.json index 2642803..33f1fc6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tmp", - "version": "0.2.3", + "version": "0.2.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -197,12 +197,23 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" + }, + "dependencies": { + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + } } }, "browser-stdout": { @@ -846,15 +857,6 @@ "flat-cache": "^2.0.1" } }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", diff --git a/package.json b/package.json index 1efd85f..64d1471 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,10 @@ { "name": "tmp", - "version": "0.2.3", + "version": "0.2.4", "description": "Temporary file and directory creator", - "author": "KARASZI István (http://raszi.hu/)", - "contributors": [ - "Carsten Klein (https://github.com/silkentrance)" - ], - "keywords": [ - "temporary", - "tmp", - "temp", - "tempdir", - "tempfile", - "tmpdir", - "tmpfile" - ], + "author": "KARASZI István ", + "contributors": ["Carsten Klein (https://github.com/silkentrance)"], + "keywords": ["temporary", "tmp", "temp", "tempdir", "tempfile", "tmpdir", "tmpfile"], "license": "MIT", "repository": "https://github.com/raszi/node-tmp.git", "homepage": "http://github.com/raszi/node-tmp", @@ -33,9 +23,7 @@ "mocha": "^10.2.0" }, "main": "lib/tmp.js", - "files": [ - "lib/" - ], + "files": ["lib/"], "changelog": { "labels": { "breaking": ":boom: Breaking Change", diff --git a/test/GHSA-52f5-9888-hmc6-test.js b/test/GHSA-52f5-9888-hmc6-test.js new file mode 100644 index 0000000..91e4d79 --- /dev/null +++ b/test/GHSA-52f5-9888-hmc6-test.js @@ -0,0 +1,122 @@ +const assert = require('assert'); +const tmp = require('../lib/tmp'); +const fs = require('fs'); +const os = require('os'); +const { join } = require('path'); +const { randomBytes } = require('crypto'); + +function getRandomChars() { + return randomBytes(10).toString('hex'); +} + +function getRandomPath(dir) { + return join(dir, getRandomChars()); +} + +describe('GHSA-52f5-9888-hmc6', function () { + const realTmpdir = os.tmpdir(); + const restricted = getRandomPath(realTmpdir); + const tmpdir = getRandomPath(realTmpdir); + const evilSymlinkPath = getRandomPath(tmpdir); + + before(function () { + fs.mkdirSync(restricted); + fs.mkdirSync(tmpdir); + fs.symlinkSync(restricted, evilSymlinkPath); + }); + + after(function () { + fs.rmSync(restricted, { recursive: true }); + fs.rmSync(tmpdir, { recursive: true }); + }); + + describe('#fileSync with `dir`', function () { + it('should not allow dirs outside of dir', function (done) { + assert.throws(function () { + tmp.fileSync({ tmpdir: tmpdir, dir: evilSymlinkPath }); + }, new RegExp('^Error: dir option must be relative to')); + + done(); + }); + }); + + describe('#fileSync with `template`', function () { + it('should not allow dirs outside of dir', function (done) { + assert.throws(function () { + tmp.fileSync({ tmpdir: tmpdir, template: join(evilSymlinkPath, 'XXXXXX') }); + }, new RegExp('^Error: template option must be relative to')); + + done(); + }); + }); + + describe('#file with `dir`', function () { + it('should not allow dirs outside of dir', function (done) { + tmp.file({ tmpdir: tmpdir, dir: evilSymlinkPath }, function (err, file) { + assert.ok(err instanceof Error, 'should have failed'); + assert.ifError(file); + + done(); + }); + }); + }); + + describe('#file with `template`', function () { + it('should not allow dirs outside of dir', function (done) { + tmp.file({ tmpdir: tmpdir, template: join(evilSymlinkPath, 'XXXXXX') }, function (err, file) { + assert.ok(err instanceof Error, 'should have failed'); + assert.ifError(file, 'should be null'); + + done(); + }); + }); + }); + + describe('#dirSync with `dir`', function () { + it('should not allow dirs outside of dir', function (done) { + assert.throws(function () { + tmp.dirSync({ + tmpdir: tmpdir, + dir: evilSymlinkPath + }); + }, new RegExp('^Error: dir option must be relative to')); + + done(); + }); + }); + + describe('#dirSync with `template`', function () { + it('should not allow dirs outside of dir', function (done) { + assert.throws(function () { + tmp.dirSync({ + tmpdir: tmpdir, + template: join(evilSymlinkPath, 'XXXXXX') + }); + }, new RegExp('^Error: template option must be relative to')); + + done(); + }); + }); + + describe('#dir with `dir`', function () { + it('should not allow dirs outside of dir', function (done) { + tmp.dir({ tmpdir: tmpdir, dir: evilSymlinkPath }, function (err, dir) { + assert.ok(err instanceof Error, 'should have failed'); + assert.ifError(dir); + + done(); + }); + }); + }); + + describe('#dir with `template`', function () { + it('should not allow dirs outside of dir', function (done) { + tmp.dir({ tmpdir: tmpdir, template: join(evilSymlinkPath, 'XXXXXX') }, function (err, dir) { + assert.ok(err instanceof Error, 'should have failed'); + assert.ifError(dir, 'should be null'); + + done(); + }); + }); + }); +}); diff --git a/test/name-sync-test.js b/test/name-sync-test.js index aa08993..bfe4d9f 100644 --- a/test/name-sync-test.js +++ b/test/name-sync-test.js @@ -1,14 +1,10 @@ /* eslint-disable no-octal */ // vim: expandtab:ts=2:sw=2 -const - assert = require('assert'), - os = require('os'), - path = require('path'), - inbandStandardTests = require('./name-inband-standard'), - tmp = require('../lib/tmp'); - -const isWindows = os.platform() === 'win32'; +const assert = require('assert'); +const os = require('os'); +const inbandStandardTests = require('./name-inband-standard'); +const tmp = require('../lib/tmp'); describe('tmp', function () { describe('#tmpNameSync()', function () { @@ -54,42 +50,6 @@ describe('tmp', function () { } }); }); - describe('on issue #268', function () { - const origfn = os.tmpdir; - it(`should not alter ${isWindows ? 'invalid' : 'valid'} path on os.tmpdir() returning path that includes double quotes`, function () { - const tmpdir = isWindows ? '"C:\\Temp With Spaces"' : '"/tmp with spaces"'; - os.tmpdir = function () { - return tmpdir; - }; - const name = tmp.tmpNameSync(); - const index = name.indexOf(path.sep + tmpdir + path.sep); - try { - assert.ok(index > 0, `${tmpdir} should have been a subdirectory name in ${name}`); - } finally { - os.tmpdir = origfn; - } - }); - it('should not alter valid path on os.tmpdir() returning path that includes single quotes', function () { - const tmpdir = isWindows ? '\'C:\\Temp With Spaces\'' : '\'/tmp with spaces\''; - os.tmpdir = function () { - return tmpdir; - }; - const name = tmp.tmpNameSync(); - const index = name.indexOf(path.sep + tmpdir + path.sep); - try { - assert.ok(index > 0, `${tmpdir} should have been a subdirectory name in ${name}`); - } finally { - os.tmpdir = origfn; - } - }); - }); - }); - - describe('when running standard outband tests', function () { - }); - - describe('when running issue specific outband tests', function () { }); }); }); - diff --git a/test/name-test.js b/test/name-test.js index 4aac4f8..b6b3ef7 100644 --- a/test/name-test.js +++ b/test/name-test.js @@ -1,14 +1,10 @@ /* eslint-disable no-octal */ // vim: expandtab:ts=2:sw=2 -const - assert = require('assert'), - os = require('os'), - path = require('path'), - inbandStandardTests = require('./name-inband-standard'), - tmp = require('../lib/tmp'); - -const isWindows = os.platform() === 'win32'; +const assert = require('assert'); +const os = require('os'); +const inbandStandardTests = require('./name-inband-standard'); +const tmp = require('../lib/tmp'); describe('tmp', function () { describe('#tmpName()', function () { @@ -51,7 +47,9 @@ describe('tmp', function () { describe('on issue #176', function () { const origfn = os.tmpdir; it('must fail on invalid os.tmpdir()', function (done) { - os.tmpdir = function () { return undefined; }; + os.tmpdir = function () { + return undefined; + }; tmp.tmpName(function (err) { try { assert.ok(err instanceof Error, 'should have failed'); @@ -64,45 +62,6 @@ describe('tmp', function () { }); }); }); - describe('on issue #268', function () { - const origfn = os.tmpdir; - it(`should not alter ${isWindows ? 'invalid' : 'valid'} path on os.tmpdir() returning path that includes double quotes`, function (done) { - const tmpdir = isWindows ? '"C:\\Temp With Spaces"' : '"/tmp with spaces"'; - os.tmpdir = function () { return tmpdir; }; - tmp.tmpName(function (err, name) { - const index = name.indexOf(path.sep + tmpdir + path.sep); - try { - assert.ok(index > 0, `${tmpdir} should have been a subdirectory name in ${name}`); - } catch (err) { - return done(err); - } finally { - os.tmpdir = origfn; - } - done(); - }); - }); - it('should not alter valid path on os.tmpdir() returning path that includes single quotes', function (done) { - const tmpdir = isWindows ? '\'C:\\Temp With Spaces\'' : '\'/tmp with spaces\''; - os.tmpdir = function () { return tmpdir; }; - tmp.tmpName(function (err, name) { - const index = name.indexOf(path.sep + tmpdir + path.sep); - try { - assert.ok(index > 0, `${tmpdir} should have been a subdirectory name in ${name}`); - } catch (err) { - return done(err); - } finally { - os.tmpdir = origfn; - } - done(); - }); - }); - }); - }); - - describe('when running standard outband tests', function () { - }); - - describe('when running issue specific outband tests', function () { }); }); });