Skip to content

Commit 7f10a54

Browse files
committed
stream: pipe to a closed or destroyed stream is not allowed in pipeline
1 parent 00a86fe commit 7f10a54

File tree

4 files changed

+26
-0
lines changed

4 files changed

+26
-0
lines changed

doc/api/errors.md

+6
Original file line numberDiff line numberDiff line change
@@ -2621,6 +2621,12 @@ or a pipeline ends non gracefully with no explicit error.
26212621
An attempt was made to call [`stream.push()`][] after a `null`(EOF) had been
26222622
pushed to the stream.
26232623

2624+
<a id="ERR_STREAM_UNABLE_TO_PIIPE"></a>
2625+
2626+
### `ERR_STREAM_UNABLE_TO_PIIPE`
2627+
2628+
An attempt was made to pipe to a closed or destroyed stream in a pipeline.
2629+
26242630
<a id="ERR_STREAM_UNSHIFT_AFTER_END_EVENT"></a>
26252631

26262632
### `ERR_STREAM_UNSHIFT_AFTER_END_EVENT`

lib/internal/errors.js

+1
Original file line numberDiff line numberDiff line change
@@ -1716,6 +1716,7 @@ E('ERR_STREAM_DESTROYED', 'Cannot call %s after a stream was destroyed', Error);
17161716
E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);
17171717
E('ERR_STREAM_PREMATURE_CLOSE', 'Premature close', Error);
17181718
E('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF', Error);
1719+
E('ERR_STREAM_UNABLE_TO_PIIPE', 'Connot pipe to a closed or destroyed stream', Error);
17191720
E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT',
17201721
'stream.unshift() after end event', Error);
17211722
E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error);

lib/internal/streams/pipeline.js

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const {
2323
ERR_MISSING_ARGS,
2424
ERR_STREAM_DESTROYED,
2525
ERR_STREAM_PREMATURE_CLOSE,
26+
ERR_STREAM_UNABLE_TO_PIIPE,
2627
},
2728
} = require('internal/errors');
2829

@@ -253,10 +254,15 @@ function pipelineImpl(streams, callback, opts) {
253254
const stream = streams[i];
254255
const reading = i < streams.length - 1;
255256
const writing = i > 0;
257+
const next = i + 1 < streams.length ? streams[i + 1] : null;
256258
const end = reading || opts?.end !== false;
257259
const isLastStream = i === streams.length - 1;
258260

259261
if (isNodeStream(stream)) {
262+
if (next !== null && (next.closed || next.destroyed)) {
263+
throw new ERR_STREAM_UNABLE_TO_PIIPE();
264+
}
265+
260266
if (end) {
261267
const { destroy, cleanup } = destroyer(stream, reading, writing);
262268
destroys.push(destroy);

test/parallel/test-stream-pipeline.js

+13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const http = require('http');
1717
const { promisify } = require('util');
1818
const net = require('net');
1919
const tsp = require('timers/promises');
20+
const tmpdir = require('../common/tmpdir');
21+
const fs = require('fs');
2022

2123
{
2224
let finished = false;
@@ -69,6 +71,17 @@ const tsp = require('timers/promises');
6971
}, /ERR_INVALID_ARG_TYPE/);
7072
}
7173

74+
tmpdir.refresh();
75+
{
76+
assert.rejects(async () => {
77+
const read = fs.createReadStream(__filename);
78+
const write = fs.createWriteStream(tmpdir.resolve('a'));
79+
const close = promisify(write.close);
80+
await close.call(write);
81+
await pipelinep(read, write);
82+
}, /ERR_STREAM_UNABLE_TO_PIIPE/).then(common.mustCall());
83+
}
84+
7285
{
7386
const read = new Readable({
7487
read() {}

0 commit comments

Comments
 (0)