Skip to content

Commit ea5628e

Browse files
addaleaxBethGriggs
authored andcommitted
process: allow reading from stdout/stderr sockets
Allow reading from stdio streams that are conventionally associated with process output, since this is only convention. This involves disabling the oddness around closing stdio streams. Its purpose is to prevent the file descriptors 0 through 2 from being closed, since doing so can lead to information leaks when new file descriptors are being opened; instead, not doing anything seems like a more reasonable choice. Fixes: #21203 Backport-PR-URL: #25351 PR-URL: #23053 Reviewed-By: James M Snell <[email protected]>
1 parent 1a9582b commit ea5628e

8 files changed

+35
-20
lines changed

doc/api/errors.md

+20
Original file line numberDiff line numberDiff line change
@@ -1172,12 +1172,32 @@ A call was made and the UDP subsystem was not running.
11721172
<a id="ERR_STDERR_CLOSE"></a>
11731173
### ERR_STDERR_CLOSE
11741174

1175+
<!-- YAML
1176+
removed: REPLACEME
1177+
changes:
1178+
- version: REPLACEME
1179+
pr-url: https://github.com/nodejs/node/pull/23053
1180+
description: Rather than emitting an error, `process.stderr.end()` now
1181+
only closes the stream side but not the underlying resource,
1182+
making this error obsolete.
1183+
-->
1184+
11751185
An attempt was made to close the `process.stderr` stream. By design, Node.js
11761186
does not allow `stdout` or `stderr` streams to be closed by user code.
11771187

11781188
<a id="ERR_STDOUT_CLOSE"></a>
11791189
### ERR_STDOUT_CLOSE
11801190

1191+
<!-- YAML
1192+
removed: REPLACEME
1193+
changes:
1194+
- version: REPLACEME
1195+
pr-url: https://github.com/nodejs/node/pull/23053
1196+
description: Rather than emitting an error, `process.stderr.end()` now
1197+
only closes the stream side but not the underlying resource,
1198+
making this error obsolete.
1199+
-->
1200+
11811201
An attempt was made to close the `process.stdout` stream. By design, Node.js
11821202
does not allow `stdout` or `stderr` streams to be closed by user code.
11831203

doc/api/process.md

+1-5
Original file line numberDiff line numberDiff line change
@@ -1703,9 +1703,7 @@ important ways:
17031703

17041704
1. They are used internally by [`console.log()`][] and [`console.error()`][],
17051705
respectively.
1706-
2. They cannot be closed ([`end()`][] will throw).
1707-
3. They will never emit the [`'finish'`][] event.
1708-
4. Writes may be synchronous depending on what the stream is connected to
1706+
2. Writes may be synchronous depending on what the stream is connected to
17091707
and whether the system is Windows or POSIX:
17101708
- Files: *synchronous* on Windows and POSIX
17111709
- TTYs (Terminals): *asynchronous* on Windows, *synchronous* on POSIX
@@ -1925,7 +1923,6 @@ cases:
19251923

19261924

19271925
[`'exit'`]: #process_event_exit
1928-
[`'finish'`]: stream.html#stream_event_finish
19291926
[`'message'`]: child_process.html#child_process_event_message
19301927
[`'rejectionHandled'`]: #process_event_rejectionhandled
19311928
[`'uncaughtException'`]: #process_event_uncaughtexception
@@ -1936,7 +1933,6 @@ cases:
19361933
[`EventEmitter`]: events.html#events_class_eventemitter
19371934
[`console.error()`]: console.html#console_console_error_data_args
19381935
[`console.log()`]: console.html#console_console_log_data_args
1939-
[`end()`]: stream.html#stream_writable_end_chunk_encoding_callback
19401936
[`net.Server`]: net.html#net_class_net_server
19411937
[`net.Socket`]: net.html#net_class_net_socket
19421938
[`process.argv`]: #process_process_argv

lib/internal/errors.js

-2
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,6 @@ E('ERR_SOCKET_BUFFER_SIZE',
427427
(reason) => `Could not get or set buffer size: ${reason}`);
428428
E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data');
429429
E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running');
430-
E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed');
431-
E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed');
432430
E('ERR_UNKNOWN_BUILTIN_MODULE', (id) => `No such built-in module: ${id}`);
433431
E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s');
434432
E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s');

lib/internal/process/stdio.js

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
'use strict';
22

3-
const errors = require('internal/errors');
3+
const errors = require('internal/errors').codes;
44

55
exports.setup = setupStdio;
66

7+
function dummyDestroy(err, cb) { cb(err); }
8+
79
function setupStdio() {
810
var stdin;
911
var stdout;
@@ -13,11 +15,8 @@ function setupStdio() {
1315
if (stdout) return stdout;
1416
stdout = createWritableStdioStream(1);
1517
stdout.destroySoon = stdout.destroy;
16-
stdout._destroy = function(er, cb) {
17-
// Avoid errors if we already emitted
18-
er = er || new errors.Error('ERR_STDOUT_CLOSE');
19-
cb(er);
20-
};
18+
// Override _destroy so that the fd is never actually closed.
19+
stdout._destroy = dummyDestroy;
2120
if (stdout.isTTY) {
2221
process.on('SIGWINCH', () => stdout._refreshSize());
2322
}
@@ -28,11 +27,8 @@ function setupStdio() {
2827
if (stderr) return stderr;
2928
stderr = createWritableStdioStream(2);
3029
stderr.destroySoon = stderr.destroy;
31-
stderr._destroy = function(er, cb) {
32-
// Avoid errors if we already emitted
33-
er = er || new errors.Error('ERR_STDERR_CLOSE');
34-
cb(er);
35-
};
30+
// Override _destroy so that the fd is never actually closed.
31+
stdout._destroy = dummyDestroy;
3632
if (stderr.isTTY) {
3733
process.on('SIGWINCH', () => stderr._refreshSize());
3834
}

test/parallel/test-stdout-cannot-be-closed-child-process-pipe.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ function parent() {
2424
});
2525

2626
child.on('close', function(code, signal) {
27-
assert(code);
27+
assert.strictEqual(code, 0);
28+
assert.strictEqual(err, '');
2829
assert.strictEqual(out, 'foo');
29-
assert(/process\.stdout cannot be closed/.test(err));
3030
console.log('ok');
3131
});
3232
}

test/pseudo-tty/test-stdout-read.in

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello!

test/pseudo-tty/test-stdout-read.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
const common = require('../common');
3+
process.stderr.on('data', common.mustCall(console.log));

test/pseudo-tty/test-stdout-read.out

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<Buffer 48 65 6c 6c 6f 21 0a>

0 commit comments

Comments
 (0)