Skip to content

Commit ed05549

Browse files
authored
fs: validate position argument before length === 0 early return
PR-URL: #62674 Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1 parent a0160a8 commit ed05549

File tree

5 files changed

+84
-19
lines changed

5 files changed

+84
-19
lines changed

lib/fs.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,12 @@ function read(fd, buffer, offsetOrOptions, length, position, callback) {
641641

642642
length |= 0;
643643

644+
if (position == null) {
645+
position = -1;
646+
} else {
647+
validatePosition(position, 'position', length);
648+
}
649+
644650
if (length === 0) {
645651
return process.nextTick(function tick() {
646652
callback(null, 0, buffer);
@@ -654,12 +660,6 @@ function read(fd, buffer, offsetOrOptions, length, position, callback) {
654660

655661
validateOffsetLengthRead(offset, length, buffer.byteLength);
656662

657-
if (position == null) {
658-
position = -1;
659-
} else {
660-
validatePosition(position, 'position', length);
661-
}
662-
663663
function wrapper(err, bytesRead) {
664664
// Retain a reference to buffer so that it can't be GC'ed too soon.
665665
callback(err, bytesRead || 0, buffer);
@@ -712,6 +712,12 @@ function readSync(fd, buffer, offsetOrOptions, length, position) {
712712

713713
length |= 0;
714714

715+
if (position == null) {
716+
position = -1;
717+
} else {
718+
validatePosition(position, 'position', length);
719+
}
720+
715721
if (length === 0) {
716722
return 0;
717723
}
@@ -723,12 +729,6 @@ function readSync(fd, buffer, offsetOrOptions, length, position) {
723729

724730
validateOffsetLengthRead(offset, length, buffer.byteLength);
725731

726-
if (position == null) {
727-
position = -1;
728-
} else {
729-
validatePosition(position, 'position', length);
730-
}
731-
732732
return binding.read(fd, buffer, offset, length, position);
733733
}
734734

lib/internal/fs/promises.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,12 @@ async function read(handle, bufferOrParams, offset, length, position) {
13191319

13201320
length ??= buffer.byteLength - offset;
13211321

1322+
if (position == null) {
1323+
position = -1;
1324+
} else {
1325+
validatePosition(position, 'position', length);
1326+
}
1327+
13221328
if (length === 0)
13231329
return { __proto__: null, bytesRead: length, buffer };
13241330

@@ -1329,12 +1335,6 @@ async function read(handle, bufferOrParams, offset, length, position) {
13291335

13301336
validateOffsetLengthRead(offset, length, buffer.byteLength);
13311337

1332-
if (position == null) {
1333-
position = -1;
1334-
} else {
1335-
validatePosition(position, 'position', length);
1336-
}
1337-
13381338
const bytesRead = (await PromisePrototypeThen(
13391339
binding.read(handle.fd, buffer, offset, length, position, kUsePromises),
13401340
undefined,

test/parallel/test-fs-read-position-validation.mjs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,26 @@ async function testInvalid(code, position) {
9191
await testInvalid('ERR_INVALID_ARG_TYPE', badTypeValue);
9292
}
9393
}
94+
95+
{
96+
const emptyBuffer = Buffer.alloc(0);
97+
await new Promise((resolve, reject) => {
98+
fs.open(filepath, 'r', common.mustSucceed((fd) => {
99+
try {
100+
assert.throws(
101+
() => fs.read(fd, emptyBuffer, 0, 0, { not: 'a number' }, common.mustNotCall()),
102+
{ code: 'ERR_INVALID_ARG_TYPE' }
103+
);
104+
assert.throws(
105+
() => fs.read(fd, { buffer: emptyBuffer, offset: 0, length: 0, position: 'string' }, common.mustNotCall()),
106+
{ code: 'ERR_INVALID_ARG_TYPE' }
107+
);
108+
resolve();
109+
} catch (err) {
110+
reject(err);
111+
} finally {
112+
fs.close(fd, common.mustSucceed());
113+
}
114+
}));
115+
});
116+
}

test/parallel/test-fs-read-promises-position-validation.mjs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,30 @@ async function testInvalid(code, position) {
7979
for (const badTypeValue of [
8080
false, true, '1', Symbol(1), {}, [], () => {}, Promise.resolve(1),
8181
]) {
82-
testInvalid('ERR_INVALID_ARG_TYPE', badTypeValue);
82+
await testInvalid('ERR_INVALID_ARG_TYPE', badTypeValue);
83+
}
84+
}
85+
86+
{
87+
const emptyBuffer = Buffer.alloc(0);
88+
let fh;
89+
try {
90+
fh = await fs.promises.open(filepath, 'r');
91+
await assert.rejects(
92+
fh.read(emptyBuffer, 0, 0, { not: 'a number' }),
93+
{ code: 'ERR_INVALID_ARG_TYPE' }
94+
);
95+
} finally {
96+
await fh?.close();
97+
}
98+
99+
try {
100+
fh = await fs.promises.open(filepath, 'r');
101+
await assert.rejects(
102+
fh.read({ buffer: emptyBuffer, offset: 0, length: 0, position: 'string' }),
103+
{ code: 'ERR_INVALID_ARG_TYPE' }
104+
);
105+
} finally {
106+
await fh?.close();
83107
}
84108
}

test/parallel/test-fs-readSync-position-validation.mjs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,21 @@ function testInvalid(code, position) {
7777
testInvalid('ERR_INVALID_ARG_TYPE', badTypeValue);
7878
}
7979
}
80+
81+
{
82+
const emptyBuffer = Buffer.alloc(0);
83+
let fdSync;
84+
try {
85+
fdSync = fs.openSync(filepath, 'r');
86+
assert.throws(
87+
() => fs.readSync(fdSync, emptyBuffer, 0, 0, { not: 'a number' }),
88+
{ code: 'ERR_INVALID_ARG_TYPE' }
89+
);
90+
assert.throws(
91+
() => fs.readSync(fdSync, emptyBuffer, { offset: 0, length: 0, position: 'string' }),
92+
{ code: 'ERR_INVALID_ARG_TYPE' }
93+
);
94+
} finally {
95+
if (fdSync) fs.closeSync(fdSync);
96+
}
97+
}

0 commit comments

Comments
 (0)