From f2433430cab27144222b96096c64fe3757fe93d1 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Mon, 13 Jun 2016 21:00:15 -0500 Subject: [PATCH] http: disallow sending obviously invalid status codes Back port of https://github.com/nodejs/node/commit/7e9b0dd6949aaa6afda4da9f41e1d60d9b to v0.12 PR-URL: https://github.com/nodejs/node-private/pull/48 Reviewed-By: Fedor Indutny Reviewed-By: Rod Vagg --- lib/http.js | 4 + test/simple/test-http-response-statuscode.js | 92 ++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/simple/test-http-response-statuscode.js diff --git a/lib/http.js b/lib/http.js index 3175992fc4ab4a..2814f6b43a5eab 100644 --- a/lib/http.js +++ b/lib/http.js @@ -1229,6 +1229,10 @@ ServerResponse.prototype.writeHead = function(statusCode) { headers = obj; } + statusCode |= 0; + if (statusCode < 100 || statusCode > 999) + throw new RangeError('Invalid status code: ' + statusCode); + var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' + reasonPhrase + CRLF; diff --git a/test/simple/test-http-response-statuscode.js b/test/simple/test-http-response-statuscode.js new file mode 100644 index 00000000000000..6e2604b42c9b82 --- /dev/null +++ b/test/simple/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(); + }); +});