http: check for handle before running asyncReset()
If an uninitialized or user supplied Socket is in the freeSockets list of the Agent it would automatically attempt to run ._handle.asyncReset(), but would throw from those not existing. Guard against that by first checking that they exist. PR-URL: https://github.com/nodejs/node/pull/14419 Fixes: https://github.com/nodejs/node/issues/13539 Refs: https://github.com/nodejs/node/issues/13352 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
This commit is contained in:
parent
b0a8a7c6ba
commit
93f47b1154
@ -167,9 +167,12 @@ Agent.prototype.addRequest = function addRequest(req, options, port/*legacy*/,
|
||||
if (freeLen) {
|
||||
// we have a free socket, so use that.
|
||||
var socket = this.freeSockets[name].shift();
|
||||
// Assign the handle a new asyncId and run any init() hooks.
|
||||
socket._handle.asyncReset();
|
||||
socket[async_id_symbol] = socket._handle.getAsyncId();
|
||||
// Guard against an uninitialized or user supplied Socket.
|
||||
if (socket._handle && typeof socket._handle.asyncReset === 'function') {
|
||||
// Assign the handle a new asyncId and run any init() hooks.
|
||||
socket._handle.asyncReset();
|
||||
socket[async_id_symbol] = socket._handle.getAsyncId();
|
||||
}
|
||||
|
||||
// don't leak
|
||||
if (!this.freeSockets[name].length)
|
||||
|
30
test/parallel/test-http-agent-uninitialized-with-handle.js
Normal file
30
test/parallel/test-http-agent-uninitialized-with-handle.js
Normal file
@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const http = require('http');
|
||||
const net = require('net');
|
||||
|
||||
const agent = new http.Agent({
|
||||
keepAlive: true,
|
||||
});
|
||||
const socket = new net.Socket();
|
||||
// If _handle exists then internals assume a couple methods exist.
|
||||
socket._handle = {
|
||||
ref() { },
|
||||
readStart() { },
|
||||
};
|
||||
const req = new http.ClientRequest(`http://localhost:${common.PORT}/`);
|
||||
|
||||
const server = http.createServer(common.mustCall((req, res) => {
|
||||
res.end();
|
||||
})).listen(common.PORT, common.mustCall(() => {
|
||||
// Manually add the socket without a _handle.
|
||||
agent.freeSockets[agent.getName(req)] = [socket];
|
||||
// Now force the agent to use the socket and check that _handle exists before
|
||||
// calling asyncReset().
|
||||
agent.addRequest(req, {});
|
||||
req.on('response', common.mustCall(() => {
|
||||
server.close();
|
||||
}));
|
||||
req.end();
|
||||
}));
|
25
test/parallel/test-http-agent-uninitialized.js
Normal file
25
test/parallel/test-http-agent-uninitialized.js
Normal file
@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const http = require('http');
|
||||
const net = require('net');
|
||||
|
||||
const agent = new http.Agent({
|
||||
keepAlive: true,
|
||||
});
|
||||
const socket = new net.Socket();
|
||||
const req = new http.ClientRequest(`http://localhost:${common.PORT}/`);
|
||||
|
||||
const server = http.createServer(common.mustCall((req, res) => {
|
||||
res.end();
|
||||
})).listen(common.PORT, common.mustCall(() => {
|
||||
// Manually add the socket without a _handle.
|
||||
agent.freeSockets[agent.getName(req)] = [socket];
|
||||
// Now force the agent to use the socket and check that _handle exists before
|
||||
// calling asyncReset().
|
||||
agent.addRequest(req, {});
|
||||
req.on('response', common.mustCall(() => {
|
||||
server.close();
|
||||
}));
|
||||
req.end();
|
||||
}));
|
Loading…
x
Reference in New Issue
Block a user