Skip to content

Commit c302450

Browse files
RaisinTendanielleadams
authored andcommitted
fs: allow passing negative zero fd
Fixes: #37122 PR-URL: #37123 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Zijian Liu <lxxyxzj@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 48a634e commit c302450

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

lib/fs.js

+25-25
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const {
8989
Dirent,
9090
getDirents,
9191
getOptions,
92+
getValidatedFd,
9293
getValidatedPath,
9394
getValidMode,
9495
handleErrorFromBinding,
@@ -128,7 +129,6 @@ const {
128129
validateCallback,
129130
validateFunction,
130131
validateInteger,
131-
validateInt32,
132132
} = require('internal/validators');
133133
// 2 ** 32 - 1
134134
const kMaxUserId = 4294967295;
@@ -443,7 +443,7 @@ function defaultCloseCallback(err) {
443443
}
444444

445445
function close(fd, callback = defaultCloseCallback) {
446-
validateInt32(fd, 'fd', 0);
446+
fd = getValidatedFd(fd);
447447
if (callback !== defaultCloseCallback)
448448
callback = makeCallback(callback);
449449

@@ -453,7 +453,7 @@ function close(fd, callback = defaultCloseCallback) {
453453
}
454454

455455
function closeSync(fd) {
456-
validateInt32(fd, 'fd', 0);
456+
fd = getValidatedFd(fd);
457457

458458
const ctx = {};
459459
binding.close(fd, undefined, ctx);
@@ -503,7 +503,7 @@ function openSync(path, flags, mode) {
503503
// OR
504504
// fs.read(fd, {}, callback)
505505
function read(fd, buffer, offset, length, position, callback) {
506-
validateInt32(fd, 'fd', 0);
506+
fd = getValidatedFd(fd);
507507

508508
if (arguments.length <= 3) {
509509
// Assume fs.read(fd, options, callback)
@@ -576,7 +576,7 @@ ObjectDefineProperty(read, internalUtil.customPromisifyArgs,
576576
// OR
577577
// fs.readSync(fd, buffer, {}) or fs.readSync(fd, buffer)
578578
function readSync(fd, buffer, offset, length, position) {
579-
validateInt32(fd, 'fd', 0);
579+
fd = getValidatedFd(fd);
580580

581581
if (arguments.length <= 3) {
582582
// Assume fs.read(fd, buffer, options)
@@ -623,7 +623,7 @@ function readv(fd, buffers, position, callback) {
623623
callback(err, read || 0, buffers);
624624
}
625625

626-
validateInt32(fd, 'fd', /* min */ 0);
626+
fd = getValidatedFd(fd);
627627
validateBufferArray(buffers);
628628
callback = maybeCallback(callback || position);
629629

@@ -640,7 +640,7 @@ ObjectDefineProperty(readv, internalUtil.customPromisifyArgs,
640640
{ value: ['bytesRead', 'buffers'], enumerable: false });
641641

642642
function readvSync(fd, buffers, position) {
643-
validateInt32(fd, 'fd', 0);
643+
fd = getValidatedFd(fd);
644644
validateBufferArray(buffers);
645645

646646
const ctx = {};
@@ -663,7 +663,7 @@ function write(fd, buffer, offset, length, position, callback) {
663663
callback(err, written || 0, buffer);
664664
}
665665

666-
validateInt32(fd, 'fd', 0);
666+
fd = getValidatedFd(fd);
667667

668668
if (isArrayBufferView(buffer)) {
669669
callback = maybeCallback(callback || position || length || offset);
@@ -709,7 +709,7 @@ ObjectDefineProperty(write, internalUtil.customPromisifyArgs,
709709
// OR
710710
// fs.writeSync(fd, string[, position[, encoding]]);
711711
function writeSync(fd, buffer, offset, length, position) {
712-
validateInt32(fd, 'fd', 0);
712+
fd = getValidatedFd(fd);
713713
const ctx = {};
714714
let result;
715715
if (isArrayBufferView(buffer)) {
@@ -744,7 +744,7 @@ function writev(fd, buffers, position, callback) {
744744
callback(err, written || 0, buffers);
745745
}
746746

747-
validateInt32(fd, 'fd', 0);
747+
fd = getValidatedFd(fd);
748748
validateBufferArray(buffers);
749749
callback = maybeCallback(callback || position);
750750

@@ -763,7 +763,7 @@ ObjectDefineProperty(writev, internalUtil.customPromisifyArgs, {
763763
});
764764

765765
function writevSync(fd, buffers, position) {
766-
validateInt32(fd, 'fd', 0);
766+
fd = getValidatedFd(fd);
767767
validateBufferArray(buffers);
768768

769769
const ctx = {};
@@ -849,7 +849,7 @@ function ftruncate(fd, len = 0, callback) {
849849
callback = len;
850850
len = 0;
851851
}
852-
validateInt32(fd, 'fd', 0);
852+
fd = getValidatedFd(fd);
853853
validateInteger(len, 'len');
854854
len = MathMax(0, len);
855855
callback = makeCallback(callback);
@@ -860,7 +860,7 @@ function ftruncate(fd, len = 0, callback) {
860860
}
861861

862862
function ftruncateSync(fd, len = 0) {
863-
validateInt32(fd, 'fd', 0);
863+
fd = getValidatedFd(fd);
864864
validateInteger(len, 'len');
865865
len = MathMax(0, len);
866866
const ctx = {};
@@ -942,28 +942,28 @@ function rmSync(path, options) {
942942
}
943943

944944
function fdatasync(fd, callback) {
945-
validateInt32(fd, 'fd', 0);
945+
fd = getValidatedFd(fd);
946946
const req = new FSReqCallback();
947947
req.oncomplete = makeCallback(callback);
948948
binding.fdatasync(fd, req);
949949
}
950950

951951
function fdatasyncSync(fd) {
952-
validateInt32(fd, 'fd', 0);
952+
fd = getValidatedFd(fd);
953953
const ctx = {};
954954
binding.fdatasync(fd, undefined, ctx);
955955
handleErrorFromBinding(ctx);
956956
}
957957

958958
function fsync(fd, callback) {
959-
validateInt32(fd, 'fd', 0);
959+
fd = getValidatedFd(fd);
960960
const req = new FSReqCallback();
961961
req.oncomplete = makeCallback(callback);
962962
binding.fsync(fd, req);
963963
}
964964

965965
function fsyncSync(fd) {
966-
validateInt32(fd, 'fd', 0);
966+
fd = getValidatedFd(fd);
967967
const ctx = {};
968968
binding.fsync(fd, undefined, ctx);
969969
handleErrorFromBinding(ctx);
@@ -1054,7 +1054,7 @@ function fstat(fd, options = { bigint: false }, callback) {
10541054
callback = options;
10551055
options = {};
10561056
}
1057-
validateInt32(fd, 'fd', 0);
1057+
fd = getValidatedFd(fd);
10581058
callback = makeStatsCallback(callback);
10591059

10601060
const req = new FSReqCallback(options.bigint);
@@ -1102,7 +1102,7 @@ function hasNoEntryError(ctx) {
11021102
}
11031103

11041104
function fstatSync(fd, options = { bigint: false, throwIfNoEntry: true }) {
1105-
validateInt32(fd, 'fd', 0);
1105+
fd = getValidatedFd(fd);
11061106
const ctx = { fd };
11071107
const stats = binding.fstat(fd, options.bigint, undefined, ctx);
11081108
handleErrorFromBinding(ctx);
@@ -1255,7 +1255,7 @@ function unlinkSync(path) {
12551255
}
12561256

12571257
function fchmod(fd, mode, callback) {
1258-
validateInt32(fd, 'fd', 0);
1258+
fd = getValidatedFd(fd);
12591259
mode = parseFileMode(mode, 'mode');
12601260
callback = makeCallback(callback);
12611261

@@ -1265,7 +1265,7 @@ function fchmod(fd, mode, callback) {
12651265
}
12661266

12671267
function fchmodSync(fd, mode) {
1268-
validateInt32(fd, 'fd', 0);
1268+
fd = getValidatedFd(fd);
12691269
mode = parseFileMode(mode, 'mode');
12701270
const ctx = {};
12711271
binding.fchmod(fd, mode, undefined, ctx);
@@ -1343,7 +1343,7 @@ function lchownSync(path, uid, gid) {
13431343
}
13441344

13451345
function fchown(fd, uid, gid, callback) {
1346-
validateInt32(fd, 'fd', 0);
1346+
fd = getValidatedFd(fd);
13471347
validateInteger(uid, 'uid', -1, kMaxUserId);
13481348
validateInteger(gid, 'gid', -1, kMaxUserId);
13491349
callback = makeCallback(callback);
@@ -1354,7 +1354,7 @@ function fchown(fd, uid, gid, callback) {
13541354
}
13551355

13561356
function fchownSync(fd, uid, gid) {
1357-
validateInt32(fd, 'fd', 0);
1357+
fd = getValidatedFd(fd);
13581358
validateInteger(uid, 'uid', -1, kMaxUserId);
13591359
validateInteger(gid, 'gid', -1, kMaxUserId);
13601360

@@ -1405,7 +1405,7 @@ function utimesSync(path, atime, mtime) {
14051405
}
14061406

14071407
function futimes(fd, atime, mtime, callback) {
1408-
validateInt32(fd, 'fd', 0);
1408+
fd = getValidatedFd(fd);
14091409
atime = toUnixTimestamp(atime, 'atime');
14101410
mtime = toUnixTimestamp(mtime, 'mtime');
14111411
callback = makeCallback(callback);
@@ -1416,7 +1416,7 @@ function futimes(fd, atime, mtime, callback) {
14161416
}
14171417

14181418
function futimesSync(fd, atime, mtime) {
1419-
validateInt32(fd, 'fd', 0);
1419+
fd = getValidatedFd(fd);
14201420
atime = toUnixTimestamp(atime, 'atime');
14211421
mtime = toUnixTimestamp(mtime, 'mtime');
14221422
const ctx = {};

lib/internal/fs/utils.js

+12
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const {
1212
NumberIsFinite,
1313
NumberIsInteger,
1414
MathMin,
15+
ObjectIs,
1516
ObjectPrototypeHasOwnProperty,
1617
ObjectSetPrototypeOf,
1718
ReflectApply,
@@ -649,6 +650,16 @@ const getValidatedPath = hideStackFrames((fileURLOrPath, propName = 'path') => {
649650
return path;
650651
});
651652

653+
const getValidatedFd = hideStackFrames((fd, propName = 'fd') => {
654+
if (ObjectIs(fd, -0)) {
655+
return 0;
656+
}
657+
658+
validateInt32(fd, propName, 0);
659+
660+
return fd;
661+
});
662+
652663
const validateBufferArray = hideStackFrames((buffers, propName = 'buffers') => {
653664
if (!ArrayIsArray(buffers))
654665
throw new ERR_INVALID_ARG_TYPE(propName, 'ArrayBufferView[]', buffers);
@@ -843,6 +854,7 @@ module.exports = {
843854
getDirent,
844855
getDirents,
845856
getOptions,
857+
getValidatedFd,
846858
getValidatedPath,
847859
getValidMode,
848860
handleErrorFromBinding,

test/parallel/test-fs-stat.js

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ fs.lstat('.', common.mustSucceed(function(stats) {
4747
fs.open('.', 'r', undefined, common.mustSucceed(function(fd) {
4848
assert.ok(fd);
4949

50+
fs.fstat(-0, common.mustSucceed());
51+
5052
fs.fstat(fd, common.mustSucceed(function(stats) {
5153
assert.ok(stats.mtime instanceof Date);
5254
fs.close(fd, assert.ifError);

0 commit comments

Comments
 (0)