diff --git a/src/plugins/octetstream.js b/src/plugins/octetstream.js index 8a0b2709..c72166de 100644 --- a/src/plugins/octetstream.js +++ b/src/plugins/octetstream.js @@ -1,6 +1,7 @@ /* eslint-disable no-underscore-dangle */ import OctetStreamParser from "../parsers/OctetStream.js"; +import FormidableError, * as errors from "../FormidableError.js"; export const octetStreamType = "octet-stream"; // the `options` is also available through the `options` / `formidable.options` @@ -47,8 +48,33 @@ async function init(_self, _opts) { // Keep track of writes that haven't finished so we don't emit the file before it's done being written let outstandingWrites = 0; + let fileSize = 0; this._parser.on("data", (buffer) => { + fileSize += buffer.length; + this._totalFileSize += buffer.length; + + if (fileSize > this.options.maxFileSize) { + this._error( + new FormidableError( + `options.maxFileSize (${this.options.maxFileSize} bytes), received ${fileSize} bytes of file data`, + errors.biggerThanMaxFileSize, + 413 + ) + ); + return; + } + if (this._totalFileSize > this.options.maxTotalFileSize) { + this._error( + new FormidableError( + `options.maxTotalFileSize (${this.options.maxTotalFileSize} bytes) exceeded, received ${this._totalFileSize} bytes of file data`, + errors.biggerThanTotalMaxFileSize, + 413 + ) + ); + return; + } + this.pause(); outstandingWrites += 1; diff --git a/test/integration/octet-stream.test.js b/test/integration/octet-stream.test.js index b6b6ab11..d1551b96 100644 --- a/test/integration/octet-stream.test.js +++ b/test/integration/octet-stream.test.js @@ -5,6 +5,7 @@ import url from "node:url"; import assert, { strictEqual, deepStrictEqual } from "node:assert"; import formidable from "../../src/index.js"; +import { biggerThanMaxFileSize } from "../../src/FormidableError.js"; const __filename = url.fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -52,3 +53,43 @@ test("octet stream", (done) => { createReadStream(testFilePath).pipe(request); }); }); + +test("octet stream enforces maxFileSize", (done) => { + const PORT2 = PORT + 1; + let request; + let parsed = false; + const server = createServer((req, res) => { + const form = formidable({ maxFileSize: 1024, maxTotalFileSize: 2048 }); + + form.parse(req, (err, fields, files) => { + assert(err, "expected an error for over-sized octet-stream upload"); + strictEqual(err.code, biggerThanMaxFileSize); + strictEqual(Object.keys(files).length, 0); + + res.end(); + parsed = true; + request.destroy(); + server.close(); + done(); + }); + }); + + server.listen(PORT2, (err) => { + assert(!err, "should not have error, but be falsey"); + + request = _request({ + port: PORT2, + method: "POST", + headers: { + "Content-Type": "application/octet-stream", + }, + }); + + request.on("error", (error) => { + if (parsed) return; + server.close(); + done(error); + }); + request.end(Buffer.alloc(256 * 1024, 0x42)); + }); +});