summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMatteo Collina <hello@matteocollina.com>2018-08-21 17:26:51 +0200
committerRod Vagg <rod@vagg.org>2018-11-27 15:07:09 +1100
commit93dba83fb0fb46ee2ea87163f435392490b4d59b (patch)
treecce8102e93a8757b4af6b09921286d167bd0977c /test
parentadd20f373cfe0ab5358f0c3d8b7837ad2ee1be8c (diff)
downloadnode-new-93dba83fb0fb46ee2ea87163f435392490b4d59b.tar.gz
deps,http: http_parser set max header size to 8KB
CVE-2018-12121 PR-URL: https://github.com/nodejs-private/node-private/pull/143 Ref: https://github.com/nodejs-private/security/issues/139 Ref: https://github.com/nodejs-private/http-parser-private/pull/2 Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rod Vagg <rod@vagg.org> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'test')
-rw-r--r--test/parallel/test-http-max-headers-count.js6
-rw-r--r--test/sequential/test-http-max-http-headers.js155
2 files changed, 158 insertions, 3 deletions
diff --git a/test/parallel/test-http-max-headers-count.js b/test/parallel/test-http-max-headers-count.js
index 05f4f774c2..9fcfe316e3 100644
--- a/test/parallel/test-http-max-headers-count.js
+++ b/test/parallel/test-http-max-headers-count.js
@@ -28,14 +28,14 @@ let requests = 0;
let responses = 0;
const headers = {};
-const N = 2000;
+const N = 100;
for (let i = 0; i < N; ++i) {
headers[`key${i}`] = i;
}
const maxAndExpected = [ // for server
[50, 50],
- [1500, 1500],
+ [1500, 102],
[0, N + 2] // Host and Connection
];
let max = maxAndExpected[requests][0];
@@ -56,7 +56,7 @@ server.maxHeadersCount = max;
server.listen(0, function() {
const maxAndExpected = [ // for client
[20, 20],
- [1200, 1200],
+ [1200, 103],
[0, N + 3] // Connection, Date and Transfer-Encoding
];
doRequest();
diff --git a/test/sequential/test-http-max-http-headers.js b/test/sequential/test-http-max-http-headers.js
new file mode 100644
index 0000000000..ae76142a4f
--- /dev/null
+++ b/test/sequential/test-http-max-http-headers.js
@@ -0,0 +1,155 @@
+'use strict';
+
+const assert = require('assert');
+const common = require('../common');
+const http = require('http');
+const net = require('net');
+const MAX = 8 * 1024; // 8KB
+
+// Verify that we cannot receive more than 8KB of headers.
+
+function once(cb) {
+ let called = false;
+ return () => {
+ if (!called) {
+ called = true;
+ cb();
+ }
+ };
+}
+
+function finished(client, callback) {
+ 'abort error end'.split(' ').forEach((e) => {
+ client.on(e, once(() => setImmediate(callback)));
+ });
+}
+
+function fillHeaders(headers, currentSize, valid = false) {
+ headers += 'a'.repeat(MAX - headers.length - 3);
+ // Generate valid headers
+ if (valid) {
+ // TODO(mcollina): understand why -9 is needed instead of -1
+ headers = headers.slice(0, -9);
+ }
+ return headers + '\r\n\r\n';
+}
+
+const timeout = common.platformTimeout(10);
+
+function writeHeaders(socket, headers) {
+ const array = [];
+
+ // this is off from 1024 so that \r\n does not get split
+ const chunkSize = 1000;
+ let last = 0;
+
+ for (let i = 0; i < headers.length / chunkSize; i++) {
+ const current = (i + 1) * chunkSize;
+ array.push(headers.slice(last, current));
+ last = current;
+ }
+
+ // safety check we are chunking correctly
+ assert.strictEqual(array.join(''), headers);
+
+ next();
+
+ function next() {
+ if (socket.write(array.shift())) {
+ if (array.length === 0) {
+ socket.end();
+ } else {
+ setTimeout(next, timeout);
+ }
+ } else {
+ socket.once('drain', next);
+ }
+ }
+}
+
+function test1() {
+ let headers =
+ 'HTTP/1.1 200 OK\r\n' +
+ 'Content-Length: 0\r\n' +
+ 'X-CRASH: ';
+
+ // OK, Content-Length, 0, X-CRASH, aaa...
+ const currentSize = 2 + 14 + 1 + 7;
+ headers = fillHeaders(headers, currentSize);
+
+ const server = net.createServer((sock) => {
+ sock.once('data', (chunk) => {
+ writeHeaders(sock, headers);
+ sock.resume();
+ });
+ });
+
+ server.listen(0, common.mustCall(() => {
+ const port = server.address().port;
+ const client = http.get({ port: port }, common.mustNotCall(() => {}));
+
+ client.on('error', common.mustCall((err) => {
+ assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW');
+ server.close();
+ setImmediate(test2);
+ }));
+ }));
+}
+
+const test2 = common.mustCall(() => {
+ let headers =
+ 'GET / HTTP/1.1\r\n' +
+ 'Host: localhost\r\n' +
+ 'Agent: node\r\n' +
+ 'X-CRASH: ';
+
+ // /, Host, localhost, Agent, node, X-CRASH, a...
+ const currentSize = 1 + 4 + 9 + 5 + 4 + 7;
+ headers = fillHeaders(headers, currentSize);
+
+ const server = http.createServer(common.mustNotCall());
+
+ server.on('clientError', common.mustCall((err) => {
+ assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW');
+ }));
+
+ server.listen(0, common.mustCall(() => {
+ const client = net.connect(server.address().port);
+ client.on('connect', () => {
+ writeHeaders(client, headers);
+ client.resume();
+ });
+
+ finished(client, common.mustCall((err) => {
+ server.close();
+ setImmediate(test3);
+ }));
+ }));
+});
+
+const test3 = common.mustCall(() => {
+ let headers =
+ 'GET / HTTP/1.1\r\n' +
+ 'Host: localhost\r\n' +
+ 'Agent: node\r\n' +
+ 'X-CRASH: ';
+
+ // /, Host, localhost, Agent, node, X-CRASH, a...
+ const currentSize = 1 + 4 + 9 + 5 + 4 + 7;
+ headers = fillHeaders(headers, currentSize, true);
+
+ const server = http.createServer(common.mustCall((req, res) => {
+ res.end('hello world');
+ setImmediate(server.close.bind(server));
+ }));
+
+ server.listen(0, common.mustCall(() => {
+ const client = net.connect(server.address().port);
+ client.on('connect', () => {
+ writeHeaders(client, headers);
+ client.resume();
+ });
+ }));
+});
+
+test1();