Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/plugins/octetstream.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable no-underscore-dangle */

import OctetStreamParser from "../parsers/OctetStream.js";
import * as errors from "../FormidableError.js";
import FormidableError from "../FormidableError.js";
Comment on lines +4 to +5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The two separate import statements can be merged into a single combined import, which is the pattern used throughout the codebase (e.g. import FormidableError, * as errors from "./FormidableError.js" in Formidable.js).

Suggested change
import * as errors from "../FormidableError.js";
import FormidableError from "../FormidableError.js";
import FormidableError, * as errors from "../FormidableError.js";

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code


export const octetStreamType = "octet-stream";
// the `options` is also available through the `options` / `formidable.options`
Expand Down Expand Up @@ -47,8 +49,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;

Expand Down
32 changes: 32 additions & 0 deletions test/integration/octet-stream.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,35 @@ test("octet stream", (done) => {
createReadStream(testFilePath).pipe(request);
});
});

test("octet stream enforces maxFileSize", (done) => {
const PORT2 = PORT + 1;
const server = createServer((req, res) => {
const form = formidable({ maxFileSize: 1024, maxTotalFileSize: 2048 });

form.parse(req, (err, fields, files) => {
// a 256KB octet-stream body must be rejected, not written to disk
assert(err, "expected an error for over-sized octet-stream upload");
strictEqual(err.code, 1016); // biggerThanMaxFileSize
strictEqual(Object.keys(files).length, 0);

res.end();
server.close();
done();
});
});

server.listen(PORT2, (err) => {
assert(!err, "should not have error, but be falsey");

const request = _request({
port: PORT2,
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
},
});

request.end(Buffer.alloc(256 * 1024, 0x42));
});
});
Comment on lines +56 to +86

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 maxTotalFileSize branch is never exercised

The test sets maxFileSize: 1024 and maxTotalFileSize: 2048, then sends 256 KB. Because fileSize > maxFileSize fires first (on the very first chunk), the _totalFileSize > maxTotalFileSize branch in octetstream.js lines 68-77 is never reached. The new error code 1009 (biggerThanTotalMaxFileSize) path has zero test coverage. A second case — e.g. maxFileSize: 4096, maxTotalFileSize: 1024 with a 2 KB body — would exercise it and guard against a future regression there.

Fix in Codex Fix in Claude Code