Skip to content

Commit 092094d

Browse files
committed
path: fix normalize on directories with two dots
Fixes: #14105
1 parent 79773f8 commit 092094d

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

lib/path.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ function normalizeStringWin32(path, allowAboveRoot) {
3535
var lastSlash = -1;
3636
var dots = 0;
3737
var code;
38+
var isAboveRoot = false;
3839
for (var i = 0; i <= path.length; ++i) {
3940
if (i < path.length)
4041
code = path.charCodeAt(i);
@@ -46,7 +47,7 @@ function normalizeStringWin32(path, allowAboveRoot) {
4647
if (lastSlash === i - 1 || dots === 1) {
4748
// NOOP
4849
} else if (lastSlash !== i - 1 && dots === 2) {
49-
if (res.length < 2 ||
50+
if (res.length < 2 || !isAboveRoot ||
5051
res.charCodeAt(res.length - 1) !== 46/*.*/ ||
5152
res.charCodeAt(res.length - 2) !== 46/*.*/) {
5253
if (res.length > 2) {
@@ -63,12 +64,14 @@ function normalizeStringWin32(path, allowAboveRoot) {
6364
res = res.slice(0, j);
6465
lastSlash = i;
6566
dots = 0;
67+
isAboveRoot = false;
6668
continue;
6769
}
6870
} else if (res.length === 2 || res.length === 1) {
6971
res = '';
7072
lastSlash = i;
7173
dots = 0;
74+
isAboveRoot = false;
7275
continue;
7376
}
7477
}
@@ -77,12 +80,14 @@ function normalizeStringWin32(path, allowAboveRoot) {
7780
res += '\\..';
7881
else
7982
res = '..';
83+
isAboveRoot = true;
8084
}
8185
} else {
8286
if (res.length > 0)
8387
res += '\\' + path.slice(lastSlash + 1, i);
8488
else
8589
res = path.slice(lastSlash + 1, i);
90+
isAboveRoot = false;
8691
}
8792
lastSlash = i;
8893
dots = 0;
@@ -101,6 +106,7 @@ function normalizeStringPosix(path, allowAboveRoot) {
101106
var lastSlash = -1;
102107
var dots = 0;
103108
var code;
109+
var isAboveRoot = false;
104110
for (var i = 0; i <= path.length; ++i) {
105111
if (i < path.length)
106112
code = path.charCodeAt(i);
@@ -112,7 +118,7 @@ function normalizeStringPosix(path, allowAboveRoot) {
112118
if (lastSlash === i - 1 || dots === 1) {
113119
// NOOP
114120
} else if (lastSlash !== i - 1 && dots === 2) {
115-
if (res.length < 2 ||
121+
if (res.length < 2 || !isAboveRoot ||
116122
res.charCodeAt(res.length - 1) !== 46/*.*/ ||
117123
res.charCodeAt(res.length - 2) !== 46/*.*/) {
118124
if (res.length > 2) {
@@ -129,12 +135,14 @@ function normalizeStringPosix(path, allowAboveRoot) {
129135
res = res.slice(0, j);
130136
lastSlash = i;
131137
dots = 0;
138+
isAboveRoot = false;
132139
continue;
133140
}
134141
} else if (res.length === 2 || res.length === 1) {
135142
res = '';
136143
lastSlash = i;
137144
dots = 0;
145+
isAboveRoot = false;
138146
continue;
139147
}
140148
}
@@ -143,12 +151,14 @@ function normalizeStringPosix(path, allowAboveRoot) {
143151
res += '/..';
144152
else
145153
res = '..';
154+
isAboveRoot = true;
146155
}
147156
} else {
148157
if (res.length > 0)
149158
res += '/' + path.slice(lastSlash + 1, i);
150159
else
151160
res = path.slice(lastSlash + 1, i);
161+
isAboveRoot = false;
152162
}
153163
lastSlash = i;
154164
dots = 0;

test/parallel/test-path.js

+10
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,11 @@ assert.strictEqual(path.win32.normalize('C:..\\..\\abc\\..\\def'),
432432
'C:..\\..\\def');
433433
assert.strictEqual(path.win32.normalize('C:\\.'), 'C:\\');
434434
assert.strictEqual(path.win32.normalize('file:stream'), 'file:stream');
435+
assert.strictEqual(path.win32.normalize('bar\\foo..\\..\\'), 'bar\\');
436+
assert.strictEqual(path.win32.normalize('bar\\foo..\\..'), 'bar');
437+
assert.strictEqual(path.win32.normalize('bar\\foo..\\..\\baz'), 'bar\\baz');
438+
assert.strictEqual(path.win32.normalize('bar\\foo..\\'), 'bar\\foo..\\');
439+
assert.strictEqual(path.win32.normalize('bar\\foo..'), 'bar\\foo..');
435440

436441
assert.strictEqual(path.posix.normalize('./fixtures///b/../b/c.js'),
437442
'fixtures/b/c.js');
@@ -441,6 +446,11 @@ assert.strictEqual(path.posix.normalize('a//b//./c'), 'a/b/c');
441446
assert.strictEqual(path.posix.normalize('a//b//.'), 'a/b');
442447
assert.strictEqual(path.posix.normalize('/a/b/c/../../../x/y/z'), '/x/y/z');
443448
assert.strictEqual(path.posix.normalize('///..//./foo/.//bar'), '/foo/bar');
449+
assert.strictEqual(path.posix.normalize('bar/foo../../'), 'bar/');
450+
assert.strictEqual(path.posix.normalize('bar/foo../..'), 'bar');
451+
assert.strictEqual(path.posix.normalize('bar/foo../../baz'), 'bar/baz');
452+
assert.strictEqual(path.posix.normalize('bar/foo../'), 'bar/foo../');
453+
assert.strictEqual(path.posix.normalize('bar/foo..'), 'bar/foo..');
444454

445455

446456
// path.resolve tests

0 commit comments

Comments
 (0)