path,win: fix bug in resolve and normalize

Fixes: https://github.com/nodejs/node/issues/54025
PR-URL: https://github.com/nodejs/node/pull/55623
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
Hüseyin Açacak 2024-11-06 02:21:54 +03:00 committed by GitHub
parent 25f8474730
commit 7f68e5466a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 45 additions and 19 deletions

View File

@ -268,10 +268,16 @@ const win32 = {
j++; j++;
} }
if (j === len || j !== last) { if (j === len || j !== last) {
// We matched a UNC root if (firstPart !== '.' && firstPart !== '?') {
device = // We matched a UNC root
`\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`; device =
rootEnd = j; `\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`;
rootEnd = j;
} else {
// We matched a device root (e.g. \\\\.\\PHYSICALDRIVE0)
device = `\\\\${firstPart}`;
rootEnd = 4;
}
} }
} }
} }
@ -381,17 +387,22 @@ const win32 = {
!isPathSeparator(StringPrototypeCharCodeAt(path, j))) { !isPathSeparator(StringPrototypeCharCodeAt(path, j))) {
j++; j++;
} }
if (j === len) { if (j === len || j !== last) {
// We matched a UNC root only if (firstPart === '.' || firstPart === '?') {
// Return the normalized version of the UNC root since there // We matched a device root (e.g. \\\\.\\PHYSICALDRIVE0)
// is nothing left to process device = `\\\\${firstPart}`;
return `\\\\${firstPart}\\${StringPrototypeSlice(path, last)}\\`; rootEnd = 4;
} } else if (j === len) {
if (j !== last) { // We matched a UNC root only
// We matched a UNC root with leftovers // Return the normalized version of the UNC root since there
device = // is nothing left to process
`\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`; return `\\\\${firstPart}\\${StringPrototypeSlice(path, last)}\\`;
rootEnd = j; } else {
// We matched a UNC root with leftovers
device =
`\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`;
rootEnd = j;
}
} }
} }
} }

View File

@ -170,9 +170,16 @@ std::string PathResolve(Environment* env,
j++; j++;
} }
if (j == len || j != last) { if (j == len || j != last) {
// We matched a UNC root if (firstPart != "." && firstPart != "?") {
device = "\\\\" + firstPart + "\\" + path.substr(last, j - last); // We matched a UNC root
rootEnd = j; device =
"\\\\" + firstPart + "\\" + path.substr(last, j - last);
rootEnd = j;
} else {
// We matched a device root (e.g. \\\\.\\PHYSICALDRIVE0)
device = "\\\\" + firstPart;
rootEnd = 4;
}
} }
} }
} }

View File

@ -39,6 +39,10 @@ TEST_F(PathTest, PathResolve) {
EXPECT_EQ( EXPECT_EQ(
PathResolve(*env, {"C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js"}), PathResolve(*env, {"C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js"}),
"C:\\foo\\tmp.3\\cycles\\root.js"); "C:\\foo\\tmp.3\\cycles\\root.js");
EXPECT_EQ(PathResolve(*env, {"\\\\.\\PHYSICALDRIVE0"}),
"\\\\.\\PHYSICALDRIVE0");
EXPECT_EQ(PathResolve(*env, {"\\\\?\\PHYSICALDRIVE0"}),
"\\\\?\\PHYSICALDRIVE0");
#else #else
EXPECT_EQ(PathResolve(*env, {"/var/lib", "../", "file/"}), "/var/file"); EXPECT_EQ(PathResolve(*env, {"/var/lib", "../", "file/"}), "/var/file");
EXPECT_EQ(PathResolve(*env, {"/var/lib", "/../", "file/"}), "/file"); EXPECT_EQ(PathResolve(*env, {"/var/lib", "/../", "file/"}), "/file");

View File

@ -79,7 +79,7 @@ assert.strictEqual(path.win32.toNamespacedPath('\\\\foo\\bar'),
'\\\\?\\UNC\\foo\\bar\\'); '\\\\?\\UNC\\foo\\bar\\');
assert.strictEqual(path.win32.toNamespacedPath('//foo//bar'), assert.strictEqual(path.win32.toNamespacedPath('//foo//bar'),
'\\\\?\\UNC\\foo\\bar\\'); '\\\\?\\UNC\\foo\\bar\\');
assert.strictEqual(path.win32.toNamespacedPath('\\\\?\\foo'), '\\\\?\\foo\\'); assert.strictEqual(path.win32.toNamespacedPath('\\\\?\\foo'), '\\\\?\\foo');
assert.strictEqual(path.win32.toNamespacedPath('\\\\?\\c:\\Windows/System'), '\\\\?\\c:\\Windows\\System'); assert.strictEqual(path.win32.toNamespacedPath('\\\\?\\c:\\Windows/System'), '\\\\?\\c:\\Windows\\System');
assert.strictEqual(path.win32.toNamespacedPath(null), null); assert.strictEqual(path.win32.toNamespacedPath(null), null);
assert.strictEqual(path.win32.toNamespacedPath(true), true); assert.strictEqual(path.win32.toNamespacedPath(true), true);

View File

@ -40,6 +40,8 @@ assert.strictEqual(
'..\\..\\..\\..\\baz' '..\\..\\..\\..\\baz'
); );
assert.strictEqual(path.win32.normalize('foo/bar\\baz'), 'foo\\bar\\baz'); assert.strictEqual(path.win32.normalize('foo/bar\\baz'), 'foo\\bar\\baz');
assert.strictEqual(path.win32.normalize('\\\\.\\foo'), '\\\\.\\foo');
assert.strictEqual(path.win32.normalize('\\\\.\\foo\\'), '\\\\.\\foo\\');
assert.strictEqual(path.posix.normalize('./fixtures///b/../b/c.js'), assert.strictEqual(path.posix.normalize('./fixtures///b/../b/c.js'),
'fixtures/b/c.js'); 'fixtures/b/c.js');

View File

@ -33,6 +33,8 @@ const resolveTests = [
[['c:/', '///some//dir'], 'c:\\some\\dir'], [['c:/', '///some//dir'], 'c:\\some\\dir'],
[['C:\\foo\\tmp.3\\', '..\\tmp.3\\cycles\\root.js'], [['C:\\foo\\tmp.3\\', '..\\tmp.3\\cycles\\root.js'],
'C:\\foo\\tmp.3\\cycles\\root.js'], 'C:\\foo\\tmp.3\\cycles\\root.js'],
[['\\\\.\\PHYSICALDRIVE0'], '\\\\.\\PHYSICALDRIVE0'],
[['\\\\?\\PHYSICALDRIVE0'], '\\\\?\\PHYSICALDRIVE0'],
], ],
], ],
[ path.posix.resolve, [ path.posix.resolve,