From a363509fbb5b0fc72c1ae43369640ce21b03a041 Mon Sep 17 00:00:00 2001 From: Sakthipriyan Vairamani Date: Sun, 5 Jul 2015 08:48:40 +0000 Subject: [PATCH] path: Throwing error on zero length strings The path module's `'join', 'normalize', 'isAbsolute', 'relative'` functions return/use the current directory or ignore the path, if they are passed zero length strings. > process.version 'v2.3.4-pre' > path.join('') '.' > path.win32.join('') '.' > path.posix.join('') '.' > path.win32.normalize('') '.' > path.posix.normalize('') '.' > path.win32.isAbsolute('') false > path.posix.isAbsolute('') false > path.win32.relative('', '') '' > path.posix.relative('', '') '' > path.win32relative('.', '') '' > path.posix.relative('.', '') '' But that is unintuitive. This PR throws an error if any of the parameters to those functions are zero length strings. --- lib/path.js | 14 ++++++++------ test/parallel/test-path.js | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/path.js b/lib/path.js index b7e28b22250791..6041ae7e405cf6 100644 --- a/lib/path.js +++ b/lib/path.js @@ -3,10 +3,12 @@ const util = require('util'); const isWindows = process.platform === 'win32'; -function assertPath(path) { +function assertPath(path, allowEmpty) { if (typeof path !== 'string') { throw new TypeError('Path must be a string. Received ' + util.inspect(path)); + } else if (!path && !allowEmpty) { + throw new Error('path must not be a zero length string'); } } @@ -92,7 +94,7 @@ win32.resolve = function() { } } - assertPath(path); + assertPath(path, true); // Skip empty entries if (path === '') { @@ -410,7 +412,7 @@ posix.resolve = function() { for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : process.cwd(); - assertPath(path); + assertPath(path, true); // Skip empty entries if (path === '') { @@ -463,9 +465,9 @@ posix.join = function() { var path = ''; for (var i = 0; i < arguments.length; i++) { var segment = arguments[i]; - if (typeof segment !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } + + assertPath(segment, true); + if (segment) { if (!path) { path += segment; diff --git a/test/parallel/test-path.js b/test/parallel/test-path.js index b1209d762a53d3..9fd5daf0d600fa 100644 --- a/test/parallel/test-path.js +++ b/test/parallel/test-path.js @@ -178,8 +178,6 @@ var joinTests = [['/', '.'], '/'], [['/', '..'], '/'], [['/', '..', '..'], '/'], - [[''], '.'], - [['', ''], '.'], [[' /foo'], ' /foo'], [[' ', 'foo'], ' /foo'], [[' ', '.'], ' '], @@ -413,3 +411,19 @@ if (isWindows) assert.deepEqual(path, path.win32, 'should be win32 path module'); else assert.deepEqual(path, path.posix, 'should be posix path module'); + +const err = /path must not be a zero length string/; +const os = ['win32', 'posix']; +const functions = ['join', 'normalize', 'isAbsolute', 'relative']; +const params = [[['']], [['']], [['']], [['', ''], ['.', ''], ['', '.']]]; + +os.forEach(function(os) { + functions.forEach(function(fn, idx) { + params[idx].forEach(function(args) { + const call = `path.${os}.${fn}(${args.map(JSON.stringify).join(', ')})`; + assert.throws(function() { + path[os][fn].apply(null, args); + }, err, `${call} didn't throw expected Error`); + }); + }); +});