Skip to content

Commit 57e78bc

Browse files
committed
url: validate pathToFileURL(path) argument as string
PR-URL: #49161 Reviewed-By: Joyee Cheung <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent 47add7e commit 57e78bc

File tree

3 files changed

+47
-5
lines changed

3 files changed

+47
-5
lines changed

lib/internal/url.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,14 +1449,14 @@ function pathToFileURL(filepath) {
14491449
const hostnameEndIndex = StringPrototypeIndexOf(filepath, '\\', 2);
14501450
if (hostnameEndIndex === -1) {
14511451
throw new ERR_INVALID_ARG_VALUE(
1452-
'filepath',
1452+
'path',
14531453
filepath,
14541454
'Missing UNC resource path',
14551455
);
14561456
}
14571457
if (hostnameEndIndex === 2) {
14581458
throw new ERR_INVALID_ARG_VALUE(
1459-
'filepath',
1459+
'path',
14601460
filepath,
14611461
'Empty UNC servername',
14621462
);

lib/url.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const {
5353
domainToASCII,
5454
domainToUnicode,
5555
fileURLToPath,
56-
pathToFileURL,
56+
pathToFileURL: _pathToFileURL,
5757
urlToHttpOptions,
5858
unsafeProtocol,
5959
hostlessProtocol,
@@ -1017,6 +1017,15 @@ Url.prototype.parseHost = function parseHost() {
10171017
if (host) this.hostname = host;
10181018
};
10191019

1020+
// When used internally, we are not obligated to associate TypeError with
1021+
// this function, so non-strings can be rejected by underlying implementation.
1022+
// Public API has to validate input and throw appropriate error.
1023+
function pathToFileURL(path) {
1024+
validateString(path, 'path');
1025+
1026+
return _pathToFileURL(path);
1027+
}
1028+
10201029
module.exports = {
10211030
// Original API
10221031
Url,

test/parallel/test-url-pathtofileurl.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,30 @@ const url = require('url');
2929

3030
// Missing server:
3131
assert.throws(() => url.pathToFileURL('\\\\\\no-server'), {
32-
code: 'ERR_INVALID_ARG_VALUE'
32+
code: 'ERR_INVALID_ARG_VALUE',
3333
});
3434

3535
// Missing share or resource:
3636
assert.throws(() => url.pathToFileURL('\\\\host'), {
37-
code: 'ERR_INVALID_ARG_VALUE'
37+
code: 'ERR_INVALID_ARG_VALUE',
3838
});
39+
40+
// Regression test for direct String.prototype.startsWith call
41+
assert.throws(() => url.pathToFileURL([
42+
'\\\\',
43+
{ [Symbol.toPrimitive]: () => 'blep\\blop' },
44+
]), {
45+
code: 'ERR_INVALID_ARG_TYPE',
46+
});
47+
assert.throws(() => url.pathToFileURL(['\\\\', 'blep\\blop']), {
48+
code: 'ERR_INVALID_ARG_TYPE',
49+
});
50+
assert.throws(() => url.pathToFileURL({
51+
[Symbol.toPrimitive]: () => '\\\\blep\\blop',
52+
}), {
53+
code: 'ERR_INVALID_ARG_TYPE',
54+
});
55+
3956
} else {
4057
// UNC paths on posix are considered a single path that has backslashes:
4158
const fileURL = url.pathToFileURL('\\\\nas\\share\\path.txt').href;
@@ -144,3 +161,19 @@ const url = require('url');
144161
assert.strictEqual(actual, expected);
145162
}
146163
}
164+
165+
// Test for non-string parameter
166+
{
167+
for (const badPath of [
168+
undefined, null, true, 42, 42n, Symbol('42'), NaN, {}, [], () => {},
169+
Promise.resolve('foo'),
170+
new Date(),
171+
new String('notPrimitive'),
172+
{ toString() { return 'amObject'; } },
173+
{ [Symbol.toPrimitive]: (hint) => 'amObject' },
174+
]) {
175+
assert.throws(() => url.pathToFileURL(badPath), {
176+
code: 'ERR_INVALID_ARG_TYPE',
177+
});
178+
}
179+
}

0 commit comments

Comments
 (0)