diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9878532..8995613 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,9 @@ jobs: - Node.js 16.x - Node.js 18.x - Node.js 20.x + - Node.js 22.x + - Node.js 24.x + - Node.js 26.x include: - name: Node.js 0.10 @@ -69,6 +72,15 @@ jobs: - name: Node.js 20.x node-version: "20.2" + - name: Node.js 22.x + node-version: "22.17" + + - name: Node.js 24.x + node-version: "24.4" + + - name: Node.js 26.x + node-version: "26.5" + steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 diff --git a/index.js b/index.js index 178eb1b..c3fbe0f 100644 --- a/index.js +++ b/index.js @@ -753,15 +753,16 @@ function handleField(self, fieldStream) { self.handleError(err); }); fieldStream.on('readable', function() { - var buffer = fieldStream.read(); - if (!buffer) return; + var buffer; + while ((buffer = fieldStream.read()) !== null) { + self.totalFieldSize += buffer.length; + if (self.totalFieldSize > self.maxFieldsSize) { + self.handleError(createError(413, 'maxFieldsSize ' + self.maxFieldsSize + ' exceeded')); + return; + } - self.totalFieldSize += buffer.length; - if (self.totalFieldSize > self.maxFieldsSize) { - self.handleError(createError(413, 'maxFieldsSize ' + self.maxFieldsSize + ' exceeded')); - return; + value += decoder.write(buffer); } - value += decoder.write(buffer); }); fieldStream.on('end', function() { diff --git a/test/test.js b/test/test.js index 07a69f0..738b9bc 100644 --- a/test/test.js +++ b/test/test.js @@ -291,6 +291,42 @@ var standaloneTests = [ }); } }, + { + name: 'multiline field', + fn: function(cb) { + var boundary = 'foo'; + var value = 'first line\r\nsecond line'; + var body = Buffer.from( + '--' + boundary + '\r\n' + + 'Content-Disposition: form-data; name="note"\r\n' + + '\r\n' + + value + '\r\n' + + '--' + boundary + '--\r\n' + ); + var req = new stream.PassThrough(); + var form = new multiparty.Form(); + var fieldEmitted = false; + + req.headers = { + 'content-type': 'multipart/form-data; boundary=' + boundary, + 'content-length': body.length + }; + + form.on('error', cb); + form.on('field', function(name, fieldValue) { + assert.strictEqual(name, 'note'); + assert.strictEqual(fieldValue, value); + fieldEmitted = true; + }); + form.on('close', function() { + assert.ok(fieldEmitted); + cb(); + }); + + form.parse(req); + req.end(body); + } + }, { name: 'epilogue last chunk', fn: function(cb) {