From 1e4187fcf4b8cc27df027fee2c4c266f17f14161 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Sat, 25 Apr 2020 03:37:43 +0530 Subject: [PATCH] http2: add `invalidheaders` test Refs: https://github.com/nodejs/node/issues/29829 PR-URL: https://github.com/nodejs/node/pull/33161 Reviewed-By: Robert Nagy Reviewed-By: Matteo Collina Reviewed-By: James M Snell Reviewed-By: Trivikram Kamat Reviewed-By: Denys Otrishko --- lib/internal/http2/compat.js | 2 +- lib/internal/http2/util.js | 6 +- .../parallel/test-http2-invalidheaderfield.js | 65 +++++++++++++++++++ .../test-http2-invalidheaderfields-client.js | 20 ++++-- 4 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 test/parallel/test-http2-invalidheaderfield.js diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index 841f9b69a033cd..6a2d5097116cc2 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -73,7 +73,7 @@ let statusConnectionHeaderWarned = false; // close as possible to the current require('http') API const assertValidHeader = hideStackFrames((name, value) => { - if (name === '' || typeof name !== 'string') { + if (name === '' || typeof name !== 'string' || name.indexOf(' ') >= 0) { throw new ERR_INVALID_HTTP_TOKEN('Header name', name); } if (isPseudoHeader(name)) { diff --git a/lib/internal/http2/util.js b/lib/internal/http2/util.js index 2ef0824cf760bc..8327a1d248f803 100644 --- a/lib/internal/http2/util.js +++ b/lib/internal/http2/util.js @@ -18,7 +18,8 @@ const { ERR_HTTP2_INVALID_CONNECTION_HEADERS, ERR_HTTP2_INVALID_PSEUDOHEADER, ERR_HTTP2_INVALID_SETTING_VALUE, - ERR_INVALID_ARG_TYPE + ERR_INVALID_ARG_TYPE, + ERR_INVALID_HTTP_TOKEN }, addCodeToName, hideStackFrames @@ -490,6 +491,9 @@ function mapToHeaders(map, count++; continue; } + if (key.indexOf(' ') >= 0) { + throw new ERR_INVALID_HTTP_TOKEN('Header name', key); + } if (isIllegalConnectionSpecificHeader(key, value)) { throw new ERR_HTTP2_INVALID_CONNECTION_HEADERS(key); } diff --git a/test/parallel/test-http2-invalidheaderfield.js b/test/parallel/test-http2-invalidheaderfield.js new file mode 100644 index 00000000000000..0ff8503b8cf79b --- /dev/null +++ b/test/parallel/test-http2-invalidheaderfield.js @@ -0,0 +1,65 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) { common.skip('missing crypto'); } + +// Check for: +// Spaced headers +// Psuedo headers +// Capitalized headers + +const http2 = require('http2'); +const { throws, strictEqual } = require('assert'); + +const server = http2.createServer(common.mustCall((req, res) => { + throws(() => { + res.setHeader(':path', '/'); + }, { + code: 'ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED' + }); + throws(() => { + res.setHeader('t est', 123); + }, { + code: 'ERR_INVALID_HTTP_TOKEN' + }); + res.setHeader('TEST', 123); + res.setHeader('test_', 123); + res.setHeader(' test', 123); + res.end(); +})); + +server.listen(0, common.mustCall(() => { + const session1 = http2.connect(`http://localhost:${server.address().port}`); + session1.request({ 'test_': 123, 'TEST': 123 }) + .on('end', common.mustCall(() => { + session1.close(); + server.close(); + })); + + const session2 = http2.connect(`http://localhost:${server.address().port}`); + session2.on('error', common.mustCall((e) => { + strictEqual(e.code, 'ERR_INVALID_HTTP_TOKEN'); + })); + throws(() => { + session2.request({ 't est': 123 }); + }, { + code: 'ERR_INVALID_HTTP_TOKEN' + }); + + const session3 = http2.connect(`http://localhost:${server.address().port}`); + session3.on('error', common.mustCall((e) => { + strictEqual(e.code, 'ERR_INVALID_HTTP_TOKEN'); + })); + throws(() => { + session3.request({ ' test': 123 }); + }, { + code: 'ERR_INVALID_HTTP_TOKEN' + }); + + const session4 = http2.connect(`http://localhost:${server.address().port}`); + throws(() => { + session4.request({ ':test': 123 }); + }, { + code: 'ERR_HTTP2_INVALID_PSEUDOHEADER' + }); + session4.close(); +})); diff --git a/test/parallel/test-http2-invalidheaderfields-client.js b/test/parallel/test-http2-invalidheaderfields-client.js index 90a3ea4622fccc..a5681970faab27 100644 --- a/test/parallel/test-http2-invalidheaderfields-client.js +++ b/test/parallel/test-http2-invalidheaderfields-client.js @@ -9,7 +9,11 @@ const server1 = http2.createServer(); server1.listen(0, common.mustCall(() => { const session = http2.connect(`http://localhost:${server1.address().port}`); // Check for req headers - session.request({ 'no underscore': 123 }); + assert.throws(() => { + session.request({ 'no underscore': 123 }); + }, { + code: 'ERR_INVALID_HTTP_TOKEN' + }); session.on('error', common.mustCall((e) => { assert.strictEqual(e.code, 'ERR_INVALID_HTTP_TOKEN'); server1.close(); @@ -18,15 +22,18 @@ server1.listen(0, common.mustCall(() => { const server2 = http2.createServer(common.mustCall((req, res) => { // check for setHeader - res.setHeader('x y z', 123); + assert.throws(() => { + res.setHeader('x y z', 123); + }, { + code: 'ERR_INVALID_HTTP_TOKEN' + }); res.end(); })); server2.listen(0, common.mustCall(() => { const session = http2.connect(`http://localhost:${server2.address().port}`); const req = session.request(); - req.on('error', common.mustCall((e) => { - assert.strictEqual(e.code, 'ERR_HTTP2_STREAM_ERROR'); + req.on('end', common.mustCall(() => { session.close(); server2.close(); })); @@ -39,7 +46,7 @@ const server3 = http2.createServer(common.mustCall((req, res) => { 'an invalid header': 123 }); }), { - code: 'ERR_HTTP2_INVALID_STREAM' + code: 'ERR_INVALID_HTTP_TOKEN' }); res.end(); })); @@ -47,8 +54,7 @@ const server3 = http2.createServer(common.mustCall((req, res) => { server3.listen(0, common.mustCall(() => { const session = http2.connect(`http://localhost:${server3.address().port}`); const req = session.request(); - req.on('error', common.mustCall((e) => { - assert.strictEqual(e.code, 'ERR_HTTP2_STREAM_ERROR'); + req.on('end', common.mustCall(() => { server3.close(); session.close(); }));