Skip to content

Commit ac27431

Browse files
LiviaMedeirostargos
authored andcommitted
url: validate pathToFileURL(path) argument as string
PR-URL: #49161 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent daca87b commit ac27431

File tree

3 files changed

+47
-5
lines changed

3 files changed

+47
-5
lines changed

lib/internal/url.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1521,14 +1521,14 @@ function pathToFileURL(filepath) {
15211521
const hostnameEndIndex = StringPrototypeIndexOf(filepath, '\\', 2);
15221522
if (hostnameEndIndex === -1) {
15231523
throw new ERR_INVALID_ARG_VALUE(
1524-
'filepath',
1524+
'path',
15251525
filepath,
15261526
'Missing UNC resource path',
15271527
);
15281528
}
15291529
if (hostnameEndIndex === 2) {
15301530
throw new ERR_INVALID_ARG_VALUE(
1531-
'filepath',
1531+
'path',
15321532
filepath,
15331533
'Empty UNC servername',
15341534
);

lib/url.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const {
5454
domainToASCII,
5555
domainToUnicode,
5656
fileURLToPath,
57-
pathToFileURL,
57+
pathToFileURL: _pathToFileURL,
5858
urlToHttpOptions,
5959
unsafeProtocol,
6060
hostlessProtocol,
@@ -1009,6 +1009,15 @@ Url.prototype.parseHost = function parseHost() {
10091009
if (host) this.hostname = host;
10101010
};
10111011

1012+
// When used internally, we are not obligated to associate TypeError with
1013+
// this function, so non-strings can be rejected by underlying implementation.
1014+
// Public API has to validate input and throw appropriate error.
1015+
function pathToFileURL(path) {
1016+
validateString(path, 'path');
1017+
1018+
return _pathToFileURL(path);
1019+
}
1020+
10121021
module.exports = {
10131022
// Original API
10141023
Url,

test/parallel/test-url-pathtofileurl.js

+35-2
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)