From 620a261240a20ec1ba00cfc1cfcd9a7ead84c0bf Mon Sep 17 00:00:00 2001 From: Brian White Date: Tue, 19 Apr 2016 20:49:45 -0400 Subject: [PATCH] http: disallow sending obviously invalid status codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/6291 Reviewed-By: James M Snell Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Fedor Indutny Reviewed-By: Benjamin Gruenbaum Reviewed-By: Colin Ihrig --- lib/_http_server.js | 4 + .../parallel/test-http-response-statuscode.js | 91 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 test/parallel/test-http-response-statuscode.js diff --git a/lib/_http_server.js b/lib/_http_server.js index 63ac615e6ebf8c..399f9d49e1d4b0 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -187,6 +187,10 @@ ServerResponse.prototype.writeHead = function(statusCode, reason, obj) { headers = obj; } + statusCode |= 0; + if (statusCode < 100 || statusCode > 999) + throw new RangeError(`Invalid status code: ${statusCode}`); + var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' + this.statusMessage + CRLF; diff --git a/test/parallel/test-http-response-statuscode.js b/test/parallel/test-http-response-statuscode.js new file mode 100644 index 00000000000000..3314506339b564 --- /dev/null +++ b/test/parallel/test-http-response-statuscode.js @@ -0,0 +1,91 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +const MAX_REQUESTS = 12; +var reqNum = 0; + +const server = http.Server(common.mustCall(function(req, res) { + switch (reqNum) { + case 0: + assert.throws(common.mustCall(() => { + res.writeHead(-1); + }, /invalid status code/i)); + break; + case 1: + assert.throws(common.mustCall(() => { + res.writeHead(Infinity); + }, /invalid status code/i)); + break; + case 2: + assert.throws(common.mustCall(() => { + res.writeHead(NaN); + }, /invalid status code/i)); + break; + case 3: + assert.throws(common.mustCall(() => { + res.writeHead({}); + }, /invalid status code/i)); + break; + case 4: + assert.throws(common.mustCall(() => { + res.writeHead(99); + }, /invalid status code/i)); + break; + case 5: + assert.throws(common.mustCall(() => { + res.writeHead(1000); + }, /invalid status code/i)); + break; + case 6: + assert.throws(common.mustCall(() => { + res.writeHead('1000'); + }, /invalid status code/i)); + break; + case 7: + assert.throws(common.mustCall(() => { + res.writeHead(null); + }, /invalid status code/i)); + break; + case 8: + assert.throws(common.mustCall(() => { + res.writeHead(true); + }, /invalid status code/i)); + break; + case 9: + assert.throws(common.mustCall(() => { + res.writeHead([]); + }, /invalid status code/i)); + break; + case 10: + assert.throws(common.mustCall(() => { + res.writeHead('this is not valid'); + }, /invalid status code/i)); + break; + case 11: + assert.throws(common.mustCall(() => { + res.writeHead('404 this is not valid either'); + }, /invalid status code/i)); + this.close(); + break; + default: + throw new Error('Unexpected request'); + } + res.statusCode = 200; + res.end(); +}, MAX_REQUESTS)); +server.listen(); + +server.on('listening', function makeRequest() { + http.get({ + port: this.address().port + }, (res) => { + assert.strictEqual(res.statusCode, 200); + res.on('end', () => { + if (++reqNum < MAX_REQUESTS) + makeRequest.call(this); + }); + res.resume(); + }); +});