diff --git a/HISTORY.md b/HISTORY.md index b432583a..b5299325 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ unreleased ========== * Fix error message for json parse whitespace in `strict` + * Fix internal error when inflated body exceeds limit * Prevent loss of async hooks context * Prevent hanging when request already read * deps: depd@2.0.0 diff --git a/lib/read.js b/lib/read.js index c1026095..3be2c31f 100644 --- a/lib/read.js +++ b/lib/read.js @@ -12,9 +12,11 @@ */ var createError = require('http-errors') +var destroy = require('destroy') var getBody = require('raw-body') var iconv = require('iconv-lite') var onFinished = require('on-finished') +var unpipe = require('unpipe') var zlib = require('zlib') /** @@ -89,9 +91,14 @@ function read (req, res, next, parse, debug, options) { _error = createError(400, error) } + // unpipe from stream and destroy + if (stream !== req) { + unpipe(req) + destroy(stream, true) + } + // read off entire request - stream.resume() - onFinished(req, function onfinished () { + dump(req, function onfinished () { next(createError(400, _error)) }) return @@ -179,3 +186,28 @@ function contentstream (req, debug, inflate) { return stream } + +/** + * Dump the contents of a request. + * + * @param {object} req + * @param {function} callback + * @api private + */ + +function dump (req, callback) { + if (onFinished.isFinished(req)) { + callback(null) + } else { + onFinished(req, callback) + req.resume() + } +} + +/** + * Shared reference to no-op function. + * + * @api private + */ + +function noop () {} diff --git a/package.json b/package.json index 768137e2..a0368bfa 100644 --- a/package.json +++ b/package.json @@ -13,12 +13,14 @@ "content-type": "~1.0.4", "debug": "2.6.9", "depd": "2.0.0", + "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.9.7", "raw-body": "2.5.1", - "type-is": "~1.6.18" + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "devDependencies": { "eslint": "7.32.0", diff --git a/test/json.js b/test/json.js index 57cbd7ae..4d686763 100644 --- a/test/json.js +++ b/test/json.js @@ -193,6 +193,15 @@ describe('bodyParser.json()', function () { test.write(buf) test.expect(413, done) }) + + it('should not error when inflating', function (done) { + var server = createServer({ limit: '1kb' }) + var test = request(server).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/json') + test.write(Buffer.from('1f8b080000000000000aab562a2e2952b252d21b05a360148c58a0540b0066f7ce1e0a0400', 'hex')) + test.expect(413, done) + }) }) describe('with inflate option', function () { diff --git a/test/raw.js b/test/raw.js index 8e0b8523..d2ab027f 100644 --- a/test/raw.js +++ b/test/raw.js @@ -149,6 +149,15 @@ describe('bodyParser.raw()', function () { test.write(buf) test.expect(413, done) }) + + it('should not error when inflating', function (done) { + var server = createServer({ limit: '1kb' }) + var test = request(server).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/octet-stream') + test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a147040400', 'hex')) + test.expect(413, done) + }) }) describe('with inflate option', function () { diff --git a/test/text.js b/test/text.js index 3b33684d..c3c55180 100644 --- a/test/text.js +++ b/test/text.js @@ -168,6 +168,17 @@ describe('bodyParser.text()', function () { test.write(buf) test.expect(413, done) }) + + it('should not error when inflating', function (done) { + var server = createServer({ limit: '1kb' }) + var test = request(server).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'text/plain') + test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a1470404', 'hex')) + setTimeout(function () { + test.expect(413, done) + }, 100) + }) }) describe('with inflate option', function () { diff --git a/test/urlencoded.js b/test/urlencoded.js index b2345671..10b8c4d4 100644 --- a/test/urlencoded.js +++ b/test/urlencoded.js @@ -314,6 +314,15 @@ describe('bodyParser.urlencoded()', function () { test.write(buf) test.expect(413, done) }) + + it('should not error when inflating', function (done) { + var server = createServer({ limit: '1kb' }) + var test = request(server).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/x-www-form-urlencoded') + test.write(Buffer.from('1f8b080000000000000a2b2e29b2d51b05a360148c580000a0351f92040400', 'hex')) + test.expect(413, done) + }) }) describe('with parameterLimit option', function () {