Skip to content

Commit c2898f3

Browse files
rexagodhimself65
authored andcommitted
stream: add null check in Readable.from
Throws `ERR_STREAM_NULL_VALUES` error if a null value is passed to `Readable.from`. Also added docs for the same. Co-Authored-By: 扩散性百万甜面包 <[email protected]> Fixes: #32845 PR-URL: #32873 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 9dc9c09 commit c2898f3

File tree

4 files changed

+34
-9
lines changed

4 files changed

+34
-9
lines changed

doc/api/stream.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,8 @@ added:
16211621
-->
16221622

16231623
* `iterable` {Iterable} Object implementing the `Symbol.asyncIterator` or
1624-
`Symbol.iterator` iterable protocol.
1624+
`Symbol.iterator` iterable protocol. Emits an 'error' event if a null
1625+
value is passed.
16251626
* `options` {Object} Options provided to `new stream.Readable([options])`.
16261627
By default, `Readable.from()` will set `options.objectMode` to `true`, unless
16271628
this is explicitly opted out by setting `options.objectMode` to `false`.

lib/internal/streams/from.js

+11-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const {
77
const { Buffer } = require('buffer');
88

99
const {
10-
ERR_INVALID_ARG_TYPE
10+
ERR_INVALID_ARG_TYPE,
11+
ERR_STREAM_NULL_VALUES
1112
} = require('internal/errors').codes;
1213

1314
function from(Readable, iterable, opts) {
@@ -73,15 +74,20 @@ function from(Readable, iterable, opts) {
7374
needToClose = false;
7475
const { value, done } = await iterator.next();
7576
needToClose = !done;
76-
const resolved = await value;
7777
if (done) {
7878
readable.push(null);
7979
} else if (readable.destroyed) {
8080
await close();
81-
} else if (readable.push(resolved)) {
82-
next();
8381
} else {
84-
reading = false;
82+
const res = await value;
83+
if (res === null) {
84+
reading = false;
85+
throw new ERR_STREAM_NULL_VALUES();
86+
} else if (readable.push(res)) {
87+
next();
88+
} else {
89+
reading = false;
90+
}
8591
}
8692
} catch (err) {
8793
readable.destroy(err);

test/parallel/test-readable-from-iterator-closing.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -168,18 +168,17 @@ async function closeAfterNullYielded() {
168168
const finallyMustCall = mustCall();
169169
const dataMustCall = mustCall(3);
170170

171-
function* infiniteGenerate() {
171+
function* generate() {
172172
try {
173173
yield 'a';
174174
yield 'a';
175175
yield 'a';
176-
while (true) yield null;
177176
} finally {
178177
finallyMustCall();
179178
}
180179
}
181180

182-
const stream = Readable.from(infiniteGenerate());
181+
const stream = Readable.from(generate());
183182

184183
stream.on('data', (chunk) => {
185184
dataMustCall();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
const { mustNotCall, expectsError } = require('../common');
3+
const { Readable } = require('stream');
4+
5+
async function* generate() {
6+
yield null;
7+
}
8+
9+
const stream = Readable.from(generate());
10+
11+
stream.on('error', expectsError({
12+
code: 'ERR_STREAM_NULL_VALUES',
13+
name: 'TypeError',
14+
message: 'May not write null values to stream'
15+
}));
16+
17+
stream.on('data', mustNotCall((chunk) => {}));
18+
19+
stream.on('end', mustNotCall());

0 commit comments

Comments
 (0)