Skip to content

Commit 95cbfce

Browse files
shackijjcodebytere
authored andcommitted
fs: fix readdir failure when libuv returns UV_DIRENT_UNKNOWN
Fixes: #33348 PR-URL: #33395 Refs: #33348 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 4ae4073 commit 95cbfce

3 files changed

Lines changed: 182 additions & 3 deletions

File tree

‎lib/internal/fs/utils.js‎

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,31 @@ function copyObject(source) {
173173
returntarget;
174174
}
175175

176+
constbufferSep=Buffer.from(pathModule.sep);
177+
178+
functionjoin(path,name){
179+
if((typeofpath==='string'||isUint8Array(path))&&
180+
name===undefined){
181+
returnpath;
182+
}
183+
184+
if(typeofpath==='string'&&isUint8Array(name)){
185+
constpathBuffer=Buffer.from(pathModule.join(path,pathModule.sep));
186+
returnBuffer.concat([pathBuffer,name]);
187+
}
188+
189+
if(typeofpath==='string'&&typeofname==='string'){
190+
returnpathModule.join(path,name);
191+
}
192+
193+
if(isUint8Array(path)&&isUint8Array(name)){
194+
returnBuffer.concat([path,bufferSep,name]);
195+
}
196+
197+
thrownewERR_INVALID_ARG_TYPE(
198+
'path',['string','Buffer'],path);
199+
}
200+
176201
functiongetDirents(path,[names,types],callback){
177202
leti;
178203
if(typeofcallback==='function'){
@@ -185,7 +210,14 @@ function getDirents(path, [names, types], callback) {
185210
constname=names[i];
186211
constidx=i;
187212
toFinish++;
188-
lazyLoadFs().lstat(pathModule.join(path,name),(err,stats)=>{
213+
letfilepath;
214+
try{
215+
filepath=join(path,name);
216+
}catch(err){
217+
callback(err);
218+
return;
219+
}
220+
lazyLoadFs().lstat(filepath,(err,stats)=>{
189221
if(err){
190222
callback(err);
191223
return;
@@ -214,7 +246,14 @@ function getDirents(path, [names, types], callback) {
214246
functiongetDirent(path,name,type,callback){
215247
if(typeofcallback==='function'){
216248
if(type===UV_DIRENT_UNKNOWN){
217-
lazyLoadFs().lstat(pathModule.join(path,name),(err,stats)=>{
249+
letfilepath;
250+
try{
251+
filepath=join(path,name);
252+
}catch(err){
253+
callback(err);
254+
return;
255+
}
256+
lazyLoadFs().lstat(filepath,(err,stats)=>{
218257
if(err){
219258
callback(err);
220259
return;
@@ -225,7 +264,7 @@ function getDirent(path, name, type, callback) {
225264
callback(null,newDirent(name,type));
226265
}
227266
}elseif(type===UV_DIRENT_UNKNOWN){
228-
conststats=lazyLoadFs().lstatSync(pathModule.join(path,name));
267+
conststats=lazyLoadFs().lstatSync(join(path,name));
229268
returnnewDirentFromStats(name,stats);
230269
}else{
231270
returnnewDirent(name,type);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
constfs=require('fs');
4+
5+
if(!common.isOSX){
6+
common.skip('this tests works only on MacOS');
7+
}
8+
9+
constassert=require('assert');
10+
11+
fs.readdir(
12+
Buffer.from('/dev'),
13+
{withFileTypes: true,encoding: 'buffer'},
14+
common.mustCall((e,d)=>{
15+
assert.strictEqual(e,null);
16+
})
17+
);
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
constcommon=require('../common');
5+
const{ getDirents, getDirent }=require('internal/fs/utils');
6+
constassert=require('assert');
7+
const{ internalBinding }=require('internal/test/binding');
8+
const{UV_DIRENT_UNKNOWN}=internalBinding('constants').fs;
9+
constfs=require('fs');
10+
constpath=require('path');
11+
12+
consttmpdir=require('../common/tmpdir');
13+
constfilename='foo';
14+
15+
{
16+
// setup
17+
tmpdir.refresh();
18+
fs.writeFileSync(path.join(tmpdir.path,filename),'');
19+
}
20+
// getDirents
21+
{
22+
// string + string
23+
getDirents(
24+
tmpdir.path,
25+
[[filename],[UV_DIRENT_UNKNOWN]],
26+
common.mustCall((err,names)=>{
27+
assert.strictEqual(err,null);
28+
assert.strictEqual(names.length,1);
29+
},
30+
));
31+
}
32+
{
33+
// string + Buffer
34+
getDirents(
35+
tmpdir.path,
36+
[[Buffer.from(filename)],[UV_DIRENT_UNKNOWN]],
37+
common.mustCall((err,names)=>{
38+
assert.strictEqual(err,null);
39+
assert.strictEqual(names.length,1);
40+
},
41+
));
42+
}
43+
{
44+
// Buffer + Buffer
45+
getDirents(
46+
Buffer.from(tmpdir.path),
47+
[[Buffer.from(filename)],[UV_DIRENT_UNKNOWN]],
48+
common.mustCall((err,names)=>{
49+
assert.strictEqual(err,null);
50+
assert.strictEqual(names.length,1);
51+
},
52+
));
53+
}
54+
{
55+
// wrong combination
56+
getDirents(
57+
42,
58+
[[Buffer.from(filename)],[UV_DIRENT_UNKNOWN]],
59+
common.mustCall((err)=>{
60+
assert.strictEqual(
61+
err.message,
62+
[
63+
'The "path" argument must be of type string or an '+
64+
'instance of Buffer. Received type number (42)'
65+
].join(''));
66+
},
67+
));
68+
}
69+
// getDirent
70+
{
71+
// string + string
72+
getDirent(
73+
tmpdir.path,
74+
filename,
75+
UV_DIRENT_UNKNOWN,
76+
common.mustCall((err,dirent)=>{
77+
assert.strictEqual(err,null);
78+
assert.strictEqual(dirent.name,filename);
79+
},
80+
));
81+
}
82+
{
83+
// string + Buffer
84+
constfilenameBuffer=Buffer.from(filename);
85+
getDirent(
86+
tmpdir.path,
87+
filenameBuffer,
88+
UV_DIRENT_UNKNOWN,
89+
common.mustCall((err,dirent)=>{
90+
assert.strictEqual(err,null);
91+
assert.strictEqual(dirent.name,filenameBuffer);
92+
},
93+
));
94+
}
95+
{
96+
// Buffer + Buffer
97+
constfilenameBuffer=Buffer.from(filename);
98+
getDirent(
99+
Buffer.from(tmpdir.path),
100+
filenameBuffer,
101+
UV_DIRENT_UNKNOWN,
102+
common.mustCall((err,dirent)=>{
103+
assert.strictEqual(err,null);
104+
assert.strictEqual(dirent.name,filenameBuffer);
105+
},
106+
));
107+
}
108+
{
109+
// wrong combination
110+
getDirent(
111+
42,
112+
Buffer.from(filename),
113+
UV_DIRENT_UNKNOWN,
114+
common.mustCall((err)=>{
115+
assert.strictEqual(
116+
err.message,
117+
[
118+
'The "path" argument must be of type string or an '+
119+
'instance of Buffer. Received type number (42)'
120+
].join(''));
121+
},
122+
));
123+
}

0 commit comments

Comments
 (0)