Skip to content

Commit db3fc6d

Browse files
lux01ruyadorno
authored andcommitted
fs: fix readdir and opendir recursive with unknown file types
If the libuv operations invoked by `readdir`/`opendir` return `uv_dirent_t` values where the `type` is `UV_DIRENT_UNKNOWN` then a further `lstat` is issued to fully construct the `Dirent` values. In the recursive versions of these functions, the `path` parameter was incorrectly assumed to be the path to the entry when it should be the path to the directory containing the entry. Fixes#49499. PR-URL: #49603 Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Moshe Atlow <[email protected]>
1 parent ed7c6d1 commit db3fc6d

File tree

4 files changed

+26
-19
lines changed

4 files changed

+26
-19
lines changed

‎lib/internal/fs/dir.js‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class Dir{
152152
ArrayPrototypePush(
153153
this[kDirBufferedEntries],
154154
getDirent(
155-
pathModule.join(path,result[i]),
155+
path,
156156
result[i],
157157
result[i+1],
158158
),
@@ -161,9 +161,10 @@ class Dir{
161161
}
162162

163163
readSyncRecursive(dirent){
164-
constctx={path: dirent.path};
164+
constpath=pathModule.join(dirent.path,dirent.name);
165+
constctx={ path };
165166
consthandle=dirBinding.opendir(
166-
pathModule.toNamespacedPath(dirent.path),
167+
pathModule.toNamespacedPath(path),
167168
this[kDirOptions].encoding,
168169
undefined,
169170
ctx,
@@ -177,7 +178,7 @@ class Dir{
177178
);
178179

179180
if(result){
180-
this.processReadResult(dirent.path,result);
181+
this.processReadResult(path,result);
181182
}
182183

183184
handle.close(undefined,ctx);

‎lib/internal/fs/utils.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ function join(path, name){
234234
}
235235

236236
if(typeofpath==='string'&&typeofname==='string'){
237-
returnpathModule.basename(path)===name ? path : pathModule.join(path,name);
237+
returnpathModule.join(path,name);
238238
}
239239

240240
if(isUint8Array(path)&&isUint8Array(name)){

‎test/sequential/test-fs-opendir-recursive.js‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const tmpdir = require('../common/tmpdir');
1010
consttestDir=tmpdir.path;
1111

1212
constfileStructure=[
13-
['a',['foo','bar']],
13+
['a',['a','foo','bar']],
1414
['b',['foo','bar']],
1515
['c',['foo','bar']],
1616
['d',['foo','bar']],
@@ -91,7 +91,7 @@ fs.symlinkSync(symlinkTargetFile, pathModule.join(symlinksRootPath, 'symlink-src
9191
fs.symlinkSync(symlinkTargetDir,pathModule.join(symlinksRootPath,'symlink-src-dir'));
9292

9393
constexpected=[
94-
'a','a/bar','a/foo','aa','aa/bar','aa/foo',
94+
'a','a/a','a/bar','a/foo','aa','aa/bar','aa/foo',
9595
'abc','abc/def','abc/def/bar','abc/def/foo','abc/ghi','abc/ghi/bar','abc/ghi/foo',
9696
'b','b/bar','b/foo','bb','bb/bar','bb/foo',
9797
'c','c/bar','c/foo','cc','cc/bar','cc/foo',
@@ -128,15 +128,18 @@ for (let i = 0; i < expected.length; i++){
128128
}
129129

130130
functiongetDirentPath(dirent){
131-
returnpathModule.relative(testDir,dirent.path);
131+
returnpathModule.relative(testDir,pathModule.join(dirent.path,dirent.name));
132132
}
133133

134134
functionassertDirents(dirents){
135135
dirents.sort((a,b)=>(getDirentPath(a)<getDirentPath(b) ? -1 : 1));
136-
for(const[i,dirent]ofdirents.entries()){
137-
assert(direntinstanceoffs.Dirent);
138-
assert.strictEqual(getDirentPath(dirent),expected[i]);
139-
}
136+
assert.deepStrictEqual(
137+
dirents.map((dirent)=>{
138+
assert(direntinstanceoffs.Dirent);
139+
returngetDirentPath(dirent);
140+
}),
141+
expected
142+
);
140143
}
141144

142145
functionprocessDirSync(dir){

‎test/sequential/test-fs-readdir-recursive.js‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const tmpdir = require('../common/tmpdir');
99
constreaddirDir=tmpdir.path;
1010

1111
constfileStructure=[
12-
['a',['foo','bar']],
12+
['a',['a','foo','bar']],
1313
['b',['foo','bar']],
1414
['c',['foo','bar']],
1515
['d',['foo','bar']],
@@ -90,7 +90,7 @@ fs.symlinkSync(symlinkTargetFile, pathModule.join(symlinksRootPath, 'symlink-src
9090
fs.symlinkSync(symlinkTargetDir,pathModule.join(symlinksRootPath,'symlink-src-dir'));
9191

9292
constexpected=[
93-
'a','a/bar','a/foo','aa','aa/bar','aa/foo',
93+
'a','a/a','a/bar','a/foo','aa','aa/bar','aa/foo',
9494
'abc','abc/def','abc/def/bar','abc/def/foo','abc/ghi','abc/ghi/bar','abc/ghi/foo',
9595
'b','b/bar','b/foo','bb','bb/bar','bb/foo',
9696
'c','c/bar','c/foo','cc','cc/bar','cc/foo',
@@ -133,11 +133,14 @@ function getDirentPath(dirent){
133133
functionassertDirents(dirents){
134134
assert.strictEqual(dirents.length,expected.length);
135135
dirents.sort((a,b)=>(getDirentPath(a)<getDirentPath(b) ? -1 : 1));
136-
for(const[i,dirent]ofdirents.entries()){
137-
assert(direntinstanceoffs.Dirent);
138-
assert.notStrictEqual(dirent.name,undefined);
139-
assert.strictEqual(getDirentPath(dirent),expected[i]);
140-
}
136+
assert.deepStrictEqual(
137+
dirents.map((dirent)=>{
138+
assert(direntinstanceoffs.Dirent);
139+
assert.notStrictEqual(dirent.name,undefined);
140+
returngetDirentPath(dirent);
141+
}),
142+
expected
143+
);
141144
}
142145

143146
// readdirSync

0 commit comments

Comments
(0)