Skip to content

Commit 1638698

Browse files
committed
fs: move type checking for fs.read to js
PR-URL: #17334 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Jon Moss <me@jonathanmoss.me> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 448ec0b commit 1638698

File tree

3 files changed

+61
-23
lines changed

3 files changed

+61
-23
lines changed

lib/fs.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,18 +691,38 @@ fs.openSync = function(path, flags, mode) {
691691
};
692692

693693
fs.read = function(fd, buffer, offset, length, position, callback) {
694+
if (!Number.isInteger(fd))
695+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number');
696+
if (fd < 0 || fd > 0xFFFFFFFF)
697+
throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd');
698+
if (!isUint8Array(buffer))
699+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buffer',
700+
['Buffer', 'Uint8Array']);
701+
702+
offset |= 0;
703+
length |= 0;
704+
694705
if (length === 0) {
695706
return process.nextTick(function() {
696707
callback && callback(null, 0, buffer);
697708
});
698709
}
699710

711+
if (offset < 0 || offset >= buffer.length)
712+
throw new errors.RangeError('ERR_OUT_OF_RANGE', 'offset');
713+
714+
if (length < 0 || offset + length > buffer.length)
715+
throw new errors.RangeError('ERR_OUT_OF_RANGE', 'length');
716+
717+
if (!Number.isInteger(position))
718+
position = -1;
719+
700720
function wrapper(err, bytesRead) {
701721
// Retain a reference to buffer so that it can't be GC'ed too soon.
702722
callback && callback(err, bytesRead || 0, buffer);
703723
}
704724

705-
var req = new FSReqWrap();
725+
const req = new FSReqWrap();
706726
req.oncomplete = wrapper;
707727

708728
binding.read(fd, buffer, offset, length, position, req);
@@ -712,10 +732,30 @@ Object.defineProperty(fs.read, internalUtil.customPromisifyArgs,
712732
{ value: ['bytesRead', 'buffer'], enumerable: false });
713733

714734
fs.readSync = function(fd, buffer, offset, length, position) {
735+
if (!Number.isInteger(fd))
736+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'fd', 'number');
737+
if (fd < 0 || fd > 0xFFFFFFFF)
738+
throw new errors.RangeError('ERR_OUT_OF_RANGE', 'fd');
739+
if (!isUint8Array(buffer))
740+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buffer',
741+
['Buffer', 'Uint8Array']);
742+
743+
offset |= 0;
744+
length |= 0;
745+
715746
if (length === 0) {
716747
return 0;
717748
}
718749

750+
if (offset < 0 || offset >= buffer.length)
751+
throw new errors.RangeError('ERR_OUT_OF_RANGE', 'offset');
752+
753+
if (length < 0 || offset + length > buffer.length)
754+
throw new errors.RangeError('ERR_OUT_OF_RANGE', 'length');
755+
756+
if (!Number.isInteger(position))
757+
position = -1;
758+
719759
return binding.read(fd, buffer, offset, length, position);
720760
};
721761

src/node_file.cc

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,12 +1178,8 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
11781178
static void Read(const FunctionCallbackInfo<Value>& args) {
11791179
Environment* env = Environment::GetCurrent(args);
11801180

1181-
if (args.Length() < 2)
1182-
return TYPE_ERROR("fd and buffer are required");
1183-
if (!args[0]->IsInt32())
1184-
return TYPE_ERROR("fd must be a file descriptor");
1185-
if (!Buffer::HasInstance(args[1]))
1186-
return TYPE_ERROR("Second argument needs to be a buffer");
1181+
CHECK(args[0]->IsInt32());
1182+
CHECK(Buffer::HasInstance(args[1]));
11871183

11881184
int fd = args[0]->Int32Value();
11891185

@@ -1199,13 +1195,10 @@ static void Read(const FunctionCallbackInfo<Value>& args) {
11991195
size_t buffer_length = Buffer::Length(buffer_obj);
12001196

12011197
size_t off = args[2]->Int32Value();
1202-
if (off >= buffer_length) {
1203-
return env->ThrowError("Offset is out of bounds");
1204-
}
1198+
CHECK_LT(off, buffer_length);
12051199

12061200
len = args[3]->Int32Value();
1207-
if (!Buffer::IsWithinBounds(off, len, buffer_length))
1208-
return env->ThrowRangeError("Length extends beyond buffer");
1201+
CHECK(Buffer::IsWithinBounds(off, len, buffer_length));
12091202

12101203
pos = GET_OFFSET(args[4]);
12111204

test/parallel/test-fs-read-type.js

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict';
22
const common = require('../common');
3-
const assert = require('assert');
43
const fs = require('fs');
54
const fixtures = require('../common/fixtures');
65

@@ -9,14 +8,20 @@ const fd = fs.openSync(filepath, 'r');
98
const expected = 'xyz\n';
109

1110
// Error must be thrown with string
12-
assert.throws(() => {
13-
fs.read(fd,
14-
expected.length,
15-
0,
16-
'utf-8',
17-
common.mustNotCall());
18-
}, /^TypeError: Second argument needs to be a buffer$/);
11+
common.expectsError(
12+
() => fs.read(fd, expected.length, 0, 'utf-8', common.mustNotCall()),
13+
{
14+
code: 'ERR_INVALID_ARG_TYPE',
15+
type: TypeError,
16+
message: 'The "buffer" argument must be one of type Buffer or Uint8Array'
17+
}
18+
);
1919

20-
assert.throws(() => {
21-
fs.readSync(fd, expected.length, 0, 'utf-8');
22-
}, /^TypeError: Second argument needs to be a buffer$/);
20+
common.expectsError(
21+
() => fs.readSync(fd, expected.length, 0, 'utf-8'),
22+
{
23+
code: 'ERR_INVALID_ARG_TYPE',
24+
type: TypeError,
25+
message: 'The "buffer" argument must be one of type Buffer or Uint8Array'
26+
}
27+
);

0 commit comments

Comments
 (0)