vfs: reject statfs for missing paths

Validate mounted VFS paths before returning synthetic statfs data
so fs.statfsSync() and fs.promises.statfs() report ENOENT for missing
paths. Forward validation errors asynchronously to fs.statfs()
callbacks.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/65693
Fixes: https://github.com/nodejs/node/issues/65692
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
Trivikram Kamat authored and GitHub committed 2026-09-09 05:27:35 +00:00
1 parent cb9b8708c9
commit 1dd48de141
4 files changed
+31 -4

No files matched your search

+7 -1
View File
@@ -2050,7 +2050,13 @@ function statfs(path, options = { __proto__: null, bigint: false }, callback) {
const h = vfsState.handlers;
if (h !== null) {
const result = h.statfsSync(path, options);
let result;
try {
result = h.statfsSync(path, options);
} catch (err) {
process.nextTick(callback, err);
return;
}
if (result !== undefined) {
process.nextTick(callback, null, result);
return;
+3 -2
View File
@@ -320,6 +320,7 @@ function findVFSWith(filename, syscall, fn) {
const r = findVFS(filename);
if (r === null) return undefined;
if (r.vfs.existsSync(filename)) {
if (fn === undefined) return true;
return fn(r.vfs, filename);
}
throw createENOENT(syscall, filename);
@@ -432,7 +433,7 @@ function createVfsHandlers() {
},
statfsSync(path, options) {
const pathStr = toPathStr(path);
if (pathStr !== null && findVFSForPath(pathStr) !== null) {
if (pathStr !== null && findVFSWith(pathStr, 'statfs')) {
if (options?.bigint) {
return {
type: 0n, bsize: 4096n, blocks: 0n,
@@ -709,7 +710,7 @@ function createVfsHandlers() {
vfsOp(path, (vfs, n) => vfs.promises.lutimes(n, atime, mtime).then(() => true)),
statfs(path, options) {
const pathStr = toPathStr(path);
if (pathStr !== null && findVFSForPath(pathStr) !== null) {
if (pathStr !== null && findVFSWith(pathStr, 'statfs')) {
if (options?.bigint) {
return {
__proto__: null,
+5
View File
@@ -31,6 +31,11 @@ const vfs = require('node:vfs');
// statfs
const sfs = await fsp.statfs(p('src/hello.txt'));
assert.strictEqual(typeof sfs.bsize, 'number');
await assert.rejects(fsp.statfs(p('missing')), {
code: 'ENOENT',
syscall: 'statfs',
path: p('missing'),
});
// Path-based writes
await fsp.writeFile(p('src/pw.txt'), 'pdata');
+16 -1
View File
@@ -4,7 +4,7 @@
// fs.statSync / fs.lstatSync / fs.statfsSync dispatch through the VFS layer,
// including the `throwIfNoEntry: false` option.
require('../common');
const common = require('../common');
const assert = require('assert');
const fs = require('fs');
const path = require('path');
@@ -57,4 +57,19 @@ assert.strictEqual(
assert.strictEqual(typeof s.bsize, 'bigint');
}
// statfsSync on a missing path throws ENOENT
assert.throws(() => fs.statfsSync(path.join(mountPoint, 'missing')),
{
code: 'ENOENT',
syscall: 'statfs',
path: path.join(mountPoint, 'missing'),
});
// Statfs on a missing path reports ENOENT through the callback
fs.statfs(path.join(mountPoint, 'missing'), common.mustCall((err) => {
assert.strictEqual(err.code, 'ENOENT');
assert.strictEqual(err.syscall, 'statfs');
assert.strictEqual(err.path, path.join(mountPoint, 'missing'));
}));
myVfs.unmount();