From 7bebb0d988e299703495c59f7e1a2263cf4df32a Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Wed, 17 Jan 2018 15:44:49 +0100 Subject: [PATCH] http: free the parser before emitting 'upgrade' Ensure that the parser is freed before emitting the 'connect' or 'upgrade' event. PR-URL: https://github.com/nodejs/node/pull/18209 Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Jon Moss Reviewed-By: Fedor Indutny Reviewed-By: Ruben Bridgewater --- lib/_http_client.js | 2 +- .../test-http-parser-freed-before-upgrade.js | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-http-parser-freed-before-upgrade.js diff --git a/lib/_http_client.js b/lib/_http_client.js index 1b637c94209f67..8031826d5351b8 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -452,6 +452,7 @@ function socketOnData(d) { socket.removeListener('data', socketOnData); socket.removeListener('end', socketOnEnd); parser.finish(); + freeParser(parser, req, socket); var bodyHead = d.slice(bytesParsed, d.length); @@ -472,7 +473,6 @@ function socketOnData(d) { // Got Upgrade header or CONNECT method, but have no handler. socket.destroy(); } - freeParser(parser, req, socket); } else if (parser.incoming && parser.incoming.complete && // When the status code is 100 (Continue), the server will // send a final response after this client sends a request diff --git a/test/parallel/test-http-parser-freed-before-upgrade.js b/test/parallel/test-http-parser-freed-before-upgrade.js new file mode 100644 index 00000000000000..4ba1de9501681c --- /dev/null +++ b/test/parallel/test-http-parser-freed-before-upgrade.js @@ -0,0 +1,33 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +const server = http.createServer(); + +server.on('upgrade', common.mustCall((request, socket) => { + assert.strictEqual(socket.parser, null); + socket.write([ + 'HTTP/1.1 101 Switching Protocols', + 'Connection: Upgrade', + 'Upgrade: WebSocket', + '\r\n' + ].join('\r\n')); +})); + +server.listen(common.mustCall(() => { + const request = http.get({ + port: server.address().port, + headers: { + Connection: 'Upgrade', + Upgrade: 'WebSocket' + } + }); + + request.on('upgrade', common.mustCall((response, socket) => { + assert.strictEqual(socket.parser, null); + socket.destroy(); + server.close(); + })); +}));