From ad470e496bbdd404c0192c509db859adaaf10639 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Mon, 13 Jun 2016 20:46:54 -0500 Subject: [PATCH] http: disallow sending obviously invalid status codes Back port of https://github.com/nodejs/node/commit/7e9b0dd6949aaa6afda4da9f41e1d60d9b 3d6225 to v0.12. PR-URL: https://github.com/nodejs/node-private/pull/47 Reviewed-By: Rod Vagg Reviewed-By: Fedor Indutny Reviewed-By: Douglas Wilson --- lib/_http_server.js | 4 + .../parallel/test-http-response-statuscode.js | 92 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/parallel/test-http-response-statuscode.js diff --git a/lib/_http_server.js b/lib/_http_server.js index 81b015cd5c16c2..3489c7b3500445 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -202,6 +202,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..6e2604b42c9b82 --- /dev/null +++ b/test/parallel/test-http-response-statuscode.js @@ -0,0 +1,92 @@ +'use strict'; +var common = require('../common'); +var assert = require('assert'); +var http = require('http'); + +var MAX_REQUESTS = 12; +var reqNum = 0; + +var server = http.Server(common.mustCall(function(req, res) { + switch (reqNum) { + case 0: + assert.throws(common.mustCall(function() { + res.writeHead(-1); + }, /invalid status code/i)); + break; + case 1: + assert.throws(common.mustCall(function() { + res.writeHead(Infinity); + }, /invalid status code/i)); + break; + case 2: + assert.throws(common.mustCall(function() { + res.writeHead(NaN); + }, /invalid status code/i)); + break; + case 3: + assert.throws(common.mustCall(function() { + res.writeHead({}); + }, /invalid status code/i)); + break; + case 4: + assert.throws(common.mustCall(function() { + res.writeHead(99); + }, /invalid status code/i)); + break; + case 5: + assert.throws(common.mustCall(function() { + res.writeHead(1000); + }, /invalid status code/i)); + break; + case 6: + assert.throws(common.mustCall(function() { + res.writeHead('1000'); + }, /invalid status code/i)); + break; + case 7: + assert.throws(common.mustCall(function() { + res.writeHead(null); + }, /invalid status code/i)); + break; + case 8: + assert.throws(common.mustCall(function() { + res.writeHead(true); + }, /invalid status code/i)); + break; + case 9: + assert.throws(common.mustCall(function() { + res.writeHead([]); + }, /invalid status code/i)); + break; + case 10: + assert.throws(common.mustCall(function() { + res.writeHead('this is not valid'); + }, /invalid status code/i)); + break; + case 11: + assert.throws(common.mustCall(function() { + 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() { + var self = this; + http.get({ + port: self.address().port + }, function(res) { + assert.strictEqual(res.statusCode, 200); + res.on('end', function() { + if (++reqNum < MAX_REQUESTS) + makeRequest.call(self); + }); + res.resume(); + }); +});