Skip to content

Commit 68f19a1

Browse files
committed
path: match Windows reserved names by component boundary
1 parent 396aad0 commit 68f19a1

2 files changed

Lines changed: 30 additions & 4 deletions

File tree

‎lib/path.js‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,31 @@ function isWindowsReservedName(path, colonIndex) {
8383
return ArrayPrototypeIncludes(WINDOWS_RESERVED_NAMES, devicePart);
8484
}
8585

86+
function hasWindowsReservedNamePrefix(path) {
87+
let firstPartEnd = path.length;
88+
for (let i = 0; i < path.length; i++) {
89+
if (isPathSeparator(StringPrototypeCharCodeAt(path, i))) {
90+
firstPartEnd = i;
91+
break;
92+
}
93+
}
94+
95+
const firstPart = StringPrototypeSlice(path, 0, firstPartEnd);
96+
const colonIndex = StringPrototypeIndexOf(firstPart, ':');
97+
const dotIndex = StringPrototypeIndexOf(firstPart, '.');
98+
let reservedNameBoundary = colonIndex;
99+
100+
if (reservedNameBoundary === -1 ||
101+
(dotIndex !== -1 && dotIndex < reservedNameBoundary)) {
102+
reservedNameBoundary = dotIndex;
103+
}
104+
105+
if (reservedNameBoundary <= 0)
106+
return false;
107+
108+
return isWindowsReservedName(firstPart, reservedNameBoundary);
109+
}
110+
86111
function isWindowsDeviceRoot(code) {
87112
return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||
88113
(code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);
@@ -470,8 +495,7 @@ const win32 = {
470495
}
471496
} while ((index = StringPrototypeIndexOf(path, ':', index + 1)) !== -1);
472497
}
473-
const colonIndex = StringPrototypeIndexOf(path, ':');
474-
if (isWindowsReservedName(path, colonIndex)) {
498+
if (hasWindowsReservedNamePrefix(path)) {
475499
return `.\\${device ?? ''}${tail}`;
476500
}
477501
if (device === undefined) {

‎test/parallel/test-path-win32-normalize-device-names.js‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const normalizeDeviceNameTests = [
2828
{ input: 'con:', expected: '.\\con:.' },
2929
{ input: 'CON:.', expected: '.\\CON:.' },
3030
{ input: 'coN:', expected: '.\\coN:.' },
31-
{ input: 'LPT9.foo', expected: 'LPT9.foo' },
31+
{ input: 'LPT9.foo', expected: '.\\LPT9.foo' },
3232
{ input: 'COM9:', expected: '.\\COM9:.' },
3333
{ input: 'COM9.', expected: '.\\COM9.' },
3434
{ input: 'C:COM9', expected: 'C:COM9' },
@@ -76,7 +76,9 @@ const normalizeDeviceNameTests = [
7676
{ input: 'D:bar', expected: 'D:bar' },
7777

7878
{ input: 'CON', expected: 'CON' },
79-
{ input: 'CON.TXT', expected: 'CON.TXT' },
79+
{ input: 'CON.TXT', expected: '.\\CON.TXT' },
80+
{ input: 'NUL.txt', expected: '.\\NUL.txt' },
81+
{ input: 'CONx', expected: 'CONx' },
8082
{ input: 'COM10:', expected: '.\\COM10:' },
8183
{ input: 'LPT10:', expected: '.\\LPT10:' },
8284
{ input: 'CONNINGTOWER:', expected: '.\\CONNINGTOWER:' },

0 commit comments

Comments
 (0)