Skip to content

Commit 8c2d19b

Browse files
ShogunPandaruyadorno
authored andcommittedAug 22, 2022
http: do not leak error listeners
PR-URL: #43587 Fixes: #43548 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Ricky Zhou <[email protected]> Reviewed-By: Mohammed Keyvanzadeh <[email protected]>
1 parent 68ee8e9 commit 8c2d19b

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed
 

‎lib/_http_server.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,10 @@ const requestHeaderFieldsTooLargeResponse = Buffer.from(
766766
function socketOnError(e) {
767767
// Ignore further errors
768768
this.removeListener('error', socketOnError);
769-
this.on('error', noop);
769+
770+
if (this.listenerCount('error') === 0) {
771+
this.on('error', noop);
772+
}
770773

771774
if (!this.server.emit('clientError', e, this)) {
772775
if (this.writable && this.bytesWritten === 0) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const http = require('http');
6+
const net = require('net');
7+
8+
// This test sends an invalid character to a HTTP server and purposely
9+
// does not handle clientError (even if it sets an event handler).
10+
//
11+
// The idea is to let the server emit multiple errors on the socket,
12+
// mostly due to parsing error, and make sure they don't result
13+
// in leaking event listeners.
14+
15+
let i = 0;
16+
let socket;
17+
18+
process.on('warning', common.mustNotCall());
19+
20+
const server = http.createServer(common.mustNotCall());
21+
22+
server.on('clientError', common.mustCallAtLeast((err) => {
23+
assert.strictEqual(err.code, 'HPE_INVALID_METHOD');
24+
assert.strictEqual(err.rawPacket.toString(), '*');
25+
26+
if (i === 20) {
27+
socket.end();
28+
} else {
29+
socket.write('*');
30+
i++;
31+
}
32+
}, 1));
33+
34+
server.listen(0, () => {
35+
socket = net.createConnection({ port: server.address().port });
36+
37+
socket.on('connect', () => {
38+
socket.write('*');
39+
});
40+
41+
socket.on('close', () => {
42+
server.close();
43+
});
44+
});

0 commit comments

Comments
 (0)
Please sign in to comment.