Skip to content

Commit b1aba4a

Browse files
committed
path: fix path.normalize not correctly normalizing relative paths
After slicing, the `lastSegmentLength` should be calculated again, instead of assigning value `j`. Fixes: #17928
1 parent f51067a commit b1aba4a

File tree

2 files changed

+46
-20
lines changed

2 files changed

+46
-20
lines changed

lib/path.js

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ function assertPath(path) {
2929
}
3030
}
3131

32+
function findLastSlashIndex(path, isWin32) {
33+
var i = path.length - 1;
34+
for (; i >= 0; i--) {
35+
const charCode = path.charCodeAt(i);
36+
if ((!isWin32 && charCode === 47/*/*/) ||
37+
(isWin32 && charCode === 92/*\*/))
38+
break;
39+
}
40+
return i;
41+
}
42+
3243
// Resolves . and .. elements in a path with directory names
3344
function normalizeStringWin32(path, allowAboveRoot) {
3445
var res = '';
@@ -51,19 +62,15 @@ function normalizeStringWin32(path, allowAboveRoot) {
5162
res.charCodeAt(res.length - 1) !== 46/*.*/ ||
5263
res.charCodeAt(res.length - 2) !== 46/*.*/) {
5364
if (res.length > 2) {
54-
const start = res.length - 1;
55-
var j = start;
56-
for (; j >= 0; --j) {
57-
if (res.charCodeAt(j) === 92/*\*/)
58-
break;
59-
}
60-
if (j !== start) {
61-
if (j === -1) {
65+
const lastSlashIndex = findLastSlashIndex(res, true);
66+
if (lastSlashIndex !== res.length - 1) {
67+
if (lastSlashIndex === -1) {
6268
res = '';
6369
lastSegmentLength = 0;
6470
} else {
65-
res = res.slice(0, j);
66-
lastSegmentLength = j;
71+
res = res.slice(0, lastSlashIndex);
72+
lastSegmentLength = res.length - 1 -
73+
findLastSlashIndex(res, true);
6774
}
6875
lastSlash = i;
6976
dots = 0;
@@ -124,19 +131,14 @@ function normalizeStringPosix(path, allowAboveRoot) {
124131
res.charCodeAt(res.length - 1) !== 46/*.*/ ||
125132
res.charCodeAt(res.length - 2) !== 46/*.*/) {
126133
if (res.length > 2) {
127-
const start = res.length - 1;
128-
var j = start;
129-
for (; j >= 0; --j) {
130-
if (res.charCodeAt(j) === 47/*/*/)
131-
break;
132-
}
133-
if (j !== start) {
134-
if (j === -1) {
134+
const lastSlashIndex = findLastSlashIndex(res);
135+
if (lastSlashIndex !== res.length - 1) {
136+
if (lastSlashIndex === -1) {
135137
res = '';
136138
lastSegmentLength = 0;
137139
} else {
138-
res = res.slice(0, j);
139-
lastSegmentLength = j;
140+
res = res.slice(0, lastSlashIndex);
141+
lastSegmentLength = res.length - 1 - findLastSlashIndex(res);
140142
}
141143
lastSlash = i;
142144
dots = 0;

test/parallel/test-path-normalize.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ assert.strictEqual(path.win32.normalize('..\\foo..\\..\\..\\bar'),
2727
'..\\..\\bar');
2828
assert.strictEqual(path.win32.normalize('..\\...\\..\\.\\...\\..\\..\\bar'),
2929
'..\\..\\bar');
30+
assert.strictEqual(path.win32.normalize('../../../foo/../../../bar'),
31+
'..\\..\\..\\..\\..\\bar');
32+
assert.strictEqual(path.win32.normalize('../../../foo/../../../bar/../../'),
33+
'..\\..\\..\\..\\..\\..\\');
34+
assert.strictEqual(
35+
path.win32.normalize('../foobar/barfoo/foo/../../../bar/../../'),
36+
'..\\..\\'
37+
);
38+
assert.strictEqual(
39+
path.win32.normalize('../.../../foobar/../../../bar/../../baz'),
40+
'..\\..\\..\\..\\baz'
41+
);
3042

3143
assert.strictEqual(path.posix.normalize('./fixtures///b/../b/c.js'),
3244
'fixtures/b/c.js');
@@ -44,3 +56,15 @@ assert.strictEqual(path.posix.normalize('bar/foo..'), 'bar/foo..');
4456
assert.strictEqual(path.posix.normalize('../foo../../../bar'), '../../bar');
4557
assert.strictEqual(path.posix.normalize('../.../.././.../../../bar'),
4658
'../../bar');
59+
assert.strictEqual(path.posix.normalize('../../../foo/../../../bar'),
60+
'../../../../../bar');
61+
assert.strictEqual(path.posix.normalize('../../../foo/../../../bar/../../'),
62+
'../../../../../../');
63+
assert.strictEqual(
64+
path.posix.normalize('../foobar/barfoo/foo/../../../bar/../../'),
65+
'../../'
66+
);
67+
assert.strictEqual(
68+
path.posix.normalize('../.../../foobar/../../../bar/../../baz'),
69+
'../../../../baz'
70+
);

0 commit comments

Comments
 (0)