Skip to content

Commit e507f93

Browse files
committed
fs: improve argument handling for ReadStream
Improve handling of erratic arguments in fs.ReadStream Refs: nodejs#19732
1 parent daed72f commit e507f93

File tree

1 file changed

+45
-21
lines changed

1 file changed

+45
-21
lines changed

lib/fs.js

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,31 +2013,55 @@ function ReadStream(path, options) {
20132013
this.bytesRead = 0;
20142014
this.closed = false;
20152015

2016-
if (this.start !== undefined) {
2017-
if (typeof this.start !== 'number' || Number.isNaN(this.start)) {
2018-
throw new ERR_INVALID_ARG_TYPE('start', 'number', this.start);
2019-
}
2020-
if (this.end === undefined) {
2021-
this.end = Infinity;
2022-
} else if (typeof this.end !== 'number' || Number.isNaN(this.end)) {
2023-
throw new ERR_INVALID_ARG_TYPE('end', 'number', this.end);
2024-
}
2016+
// Case 0: If either start or end is undefined, set them to defaults
2017+
// (0, Infinity) respectively.
2018+
this.start = this.start === undefined ? 0 : this.start;
2019+
this.end = this.end === undefined ? Infinity : this.end;
20252020

2026-
if (this.start > this.end) {
2027-
const errVal = `{start: ${this.start}, end: ${this.end}}`;
2028-
throw new ERR_OUT_OF_RANGE('start', '<= "end"', errVal);
2029-
}
2021+
// Case 1: If the type of either start or end is not number, throw
2022+
// ERR_INVALID_ARG_TYPE (TypeError).
2023+
if (typeof this.start !== 'number') {
2024+
throw new ERR_INVALID_ARG_TYPE('start', 'number', this.start);
2025+
}
2026+
if (typeof this.end !== 'number') {
2027+
throw new ERR_INVALID_ARG_TYPE('end', 'number', this.end);
2028+
}
20302029

2031-
this.pos = this.start;
2030+
// Case 2: If either start or end is NaN, throw ERR_OUT_OF_RANGE (RangeError).
2031+
if (Number.isNaN(this.start)) {
2032+
throw new ERR_OUT_OF_RANGE('start', 'not NaN', this.start);
2033+
}
2034+
if (Number.isNaN(this.end)) {
2035+
throw new ERR_OUT_OF_RANGE('end', 'not NaN', this.end);
20322036
}
20332037

2034-
// Backwards compatibility: Make sure `end` is a number regardless of `start`.
2035-
// TODO(addaleax): Make the above typecheck not depend on `start` instead.
2036-
// (That is a semver-major change).
2037-
if (typeof this.end !== 'number')
2038-
this.end = Infinity;
2039-
else if (Number.isNaN(this.end))
2040-
throw new ERR_INVALID_ARG_TYPE('end', 'number', this.end);
2038+
// Case 3: If either start or end is negative, throw ERR_OUT_OF_RANGE
2039+
// (RangeError).
2040+
if (this.start < 0) {
2041+
throw new ERR_OUT_OF_RANGE('start', 'positive', this.start);
2042+
}
2043+
if (this.end < 0) {
2044+
throw new ERR_OUT_OF_RANGE('end', 'positive', this.end);
2045+
}
2046+
2047+
// Case 4: If either start or end is fractional, round them to the nearest
2048+
// whole number. (Not integer as negatives not allowed)
2049+
if (!Number.isInteger(this.start)) {
2050+
this.start = Math.round(this.start);
2051+
}
2052+
if (!Number.isInteger(this.end)) {
2053+
this.end = Math.round(this.end);
2054+
}
2055+
2056+
// Case 5: If start and end are both whole numbers, work perfectly.
2057+
2058+
// Case 6: If start is greater than end, throw ERR_OUT_OF_RANGE (RangeError)
2059+
if (this.start > this.end) {
2060+
const errVal = `{start: ${this.start}, end: ${this.end}}`;
2061+
throw new ERR_OUT_OF_RANGE('start', '<= "end"', errVal);
2062+
}
2063+
2064+
this.pos = this.start;
20412065

20422066
if (typeof this.fd !== 'number')
20432067
this.open();

0 commit comments

Comments
 (0)