From 59408fb5020123b96a1b8313c055078d7d190008 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 7 Jul 2020 23:28:07 +0200 Subject: [PATCH 1/2] test: add regression tests for HTTP parser crash Since the tests only crash on v12.x, this commit adds separate regression tests. Refs: https://github.com/nodejs/node/issues/15102 --- ...t-http-fake-socket-error-during-headers.js | 34 ++++++++++++ ...t-http-sync-write-error-during-continue.js | 53 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 test/parallel/test-http-fake-socket-error-during-headers.js create mode 100644 test/parallel/test-http-sync-write-error-during-continue.js diff --git a/test/parallel/test-http-fake-socket-error-during-headers.js b/test/parallel/test-http-fake-socket-error-during-headers.js new file mode 100644 index 00000000000000..3654e210296bc6 --- /dev/null +++ b/test/parallel/test-http-fake-socket-error-during-headers.js @@ -0,0 +1,34 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); +const MakeDuplexPair = require('../common/duplexpair'); + +// Regression test for the crash reported in +// https://github.com/nodejs/node/issues/15102 (httpParser.finish() is called +// during httpParser.execute()): + +{ + const { clientSide, serverSide } = MakeDuplexPair(); + + serverSide.on('data', common.mustCall((data) => { + assert.strictEqual(data.toString('utf8'), `\ +GET / HTTP/1.1 +Host: localhost:80 +Connection: close + +`.replace(/\n/g, '\r\n')); + + setImmediate(() => { + serverSide.write('HTTP/1.1 200 OK\r\n\r\n'); + }); + })); + + const req = http.get({ + createConnection: common.mustCall(() => clientSide) + }, common.mustCall((res) => { + req.on('error', common.mustCall()); + req.socket.emit('error', new Error('very fake error')); + })); + req.end(); +} diff --git a/test/parallel/test-http-sync-write-error-during-continue.js b/test/parallel/test-http-sync-write-error-during-continue.js new file mode 100644 index 00000000000000..5476160942dadc --- /dev/null +++ b/test/parallel/test-http-sync-write-error-during-continue.js @@ -0,0 +1,53 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); +const MakeDuplexPair = require('../common/duplexpair'); + +// Regression test for the crash reported in +// https://github.com/nodejs/node/issues/15102 (httpParser.finish() is called +// during httpParser.execute()): + +{ + const { clientSide, serverSide } = MakeDuplexPair(); + + serverSide.on('data', common.mustCall((data) => { + assert.strictEqual(data.toString('utf8'), `\ +GET / HTTP/1.1 +Expect: 100-continue +Host: localhost:80 +Connection: close + +`.replace(/\n/g, '\r\n')); + + setImmediate(() => { + serverSide.write('HTTP/1.1 100 Continue\r\n\r\n'); + }); + })); + + const req = http.request({ + createConnection: common.mustCall(() => clientSide), + headers: { + 'Expect': '100-continue' + } + }); + req.on('continue', common.mustCall((res) => { + let sync = true; + + clientSide._writev = null; + clientSide._write = common.mustCall((chunk, enc, cb) => { + assert(sync); + // On affected versions of Node.js, the error would be emitted on `req` + // synchronously (i.e. before commit f663b31cc2aec), which would cause + // parser.finish() to be called while we are here in the 'continue' + // callback, which is inside a parser.execute() call. + + assert.strictEqual(chunk.length, 0); + clientSide.destroy(new Error('sometimes the code just doesn’t work'), cb); + }); + req.on('error', common.mustCall()); + req.end(); + + sync = false; + })); +} From ef0865761bda0d6c6483d07f143097c76e327a93 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 8 Jul 2020 00:24:58 +0200 Subject: [PATCH 2/2] fixup! test: add regression tests for HTTP parser crash --- ...t-http-fake-socket-error-during-headers.js | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 test/parallel/test-http-fake-socket-error-during-headers.js diff --git a/test/parallel/test-http-fake-socket-error-during-headers.js b/test/parallel/test-http-fake-socket-error-during-headers.js deleted file mode 100644 index 3654e210296bc6..00000000000000 --- a/test/parallel/test-http-fake-socket-error-during-headers.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; -const common = require('../common'); -const assert = require('assert'); -const http = require('http'); -const MakeDuplexPair = require('../common/duplexpair'); - -// Regression test for the crash reported in -// https://github.com/nodejs/node/issues/15102 (httpParser.finish() is called -// during httpParser.execute()): - -{ - const { clientSide, serverSide } = MakeDuplexPair(); - - serverSide.on('data', common.mustCall((data) => { - assert.strictEqual(data.toString('utf8'), `\ -GET / HTTP/1.1 -Host: localhost:80 -Connection: close - -`.replace(/\n/g, '\r\n')); - - setImmediate(() => { - serverSide.write('HTTP/1.1 200 OK\r\n\r\n'); - }); - })); - - const req = http.get({ - createConnection: common.mustCall(() => clientSide) - }, common.mustCall((res) => { - req.on('error', common.mustCall()); - req.socket.emit('error', new Error('very fake error')); - })); - req.end(); -}