Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP3:GA
nodejs4.12086
CVE-2018-12121.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File CVE-2018-12121.patch of Package nodejs4.12086
ported from: deps,http: http_parser set max header size to 8KB CVE-2018-12121 PR-URL: nodejs-private/node-private#143 Ref: nodejs-private/security#139 Ref: nodejs-private/http-parser-private#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> Index: node-v4.9.1/deps/http_parser/http_parser.gyp =================================================================== --- node-v4.9.1.orig/deps/http_parser/http_parser.gyp +++ node-v4.9.1/deps/http_parser/http_parser.gyp @@ -56,7 +56,7 @@ 'defines': [ 'HTTP_PARSER_STRICT=0' ], 'include_dirs': [ '.' ], }, - 'defines': [ 'HTTP_PARSER_STRICT=0' ], + 'defines': [ 'HTTP_MAX_HEADER_SIZE=8192', 'HTTP_PARSER_STRICT=0' ], 'sources': [ './http_parser.c', ], 'conditions': [ ['OS=="win"', { @@ -79,7 +79,7 @@ 'defines': [ 'HTTP_PARSER_STRICT=1' ], 'include_dirs': [ '.' ], }, - 'defines': [ 'HTTP_PARSER_STRICT=1' ], + 'defines': [ 'HTTP_MAX_HEADER_SIZE=8192', 'HTTP_PARSER_STRICT=1' ], 'sources': [ './http_parser.c', ], 'conditions': [ ['OS=="win"', { Index: node-v4.9.1/src/node_http_parser.cc =================================================================== --- node-v4.9.1.orig/src/node_http_parser.cc +++ node-v4.9.1/src/node_http_parser.cc @@ -611,6 +611,8 @@ class Parser : public AsyncWrap { size_t nparsed = http_parser_execute(&parser_, &settings, data, len); + enum http_errno err = HTTP_PARSER_ERRNO(&parser_); + Save(); // Unassign the 'buffer_' variable @@ -625,9 +627,7 @@ class Parser : public AsyncWrap { Local<Integer> nparsed_obj = Integer::New(env()->isolate(), nparsed); // If there was a parse error in one of the callbacks // TODO(bnoordhuis) What if there is an error on EOF? - if (!parser_.upgrade && nparsed != len) { - enum http_errno err = HTTP_PARSER_ERRNO(&parser_); - + if ((!parser_.upgrade && nparsed != len) || err != HPE_OK) { Local<Value> e = Exception::Error(env()->parse_error_string()); Local<Object> obj = e->ToObject(env()->isolate()); obj->Set(env()->bytes_parsed_string(), nparsed_obj); Index: node-v4.9.1/test/parallel/test-http-max-headers-count.js =================================================================== --- node-v4.9.1.orig/test/parallel/test-http-max-headers-count.js +++ node-v4.9.1/test/parallel/test-http-max-headers-count.js @@ -7,14 +7,14 @@ var requests = 0; var responses = 0; var headers = {}; -var N = 2000; +var N = 100; for (var i = 0; i < N; ++i) { headers['key' + i] = i; } var maxAndExpected = [ // for server [50, 50], - [1500, 1500], + [1500, 102], [0, N + 2] // Host and Connection ]; var max = maxAndExpected[requests][0]; @@ -35,7 +35,7 @@ server.maxHeadersCount = max; server.listen(0, function() { var maxAndExpected = [ // for client [20, 20], - [1200, 1200], + [1200, 103], [0, N + 3] // Connection, Date and Transfer-Encoding ]; doRequest(); Index: node-v4.9.1/test/sequential/test-http-max-http-headers.js =================================================================== --- /dev/null +++ node-v4.9.1/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) { + 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, false); + + 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, false); + + 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();
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor