Repository navigation
Conversation
The octet-stream upload path wrote every chunk to disk without checking the documented maxFileSize/maxTotalFileSize limits, unlike the multipart path in _handlePart. Accumulate per-file and total sizes and abort via _error with the existing FormidableError codes when a cap is exceeded, mirroring the multipart implementation. The over-limit file is removed through the shared _error cleanup, so no partial bytes remain on disk.
The maxFileSize test left a TCPWRAP handle open: formidable aborts the parse mid-body, so the connection never completes on its own and server.close() only stops new ones. Jest reported "did not exit one second after the test run" locally and "A worker process has failed to exit gracefully" on CI, where the leaked socket's late callback surfaced as a failure inside the next test file, test/integration/store-files-option.test.js. Destroying the client request ends the connection. Measured: with the old teardown --detectOpenHandles reports 1 open TCPWRAP at the server.listen line; with this change it reports none, and the full suite is 15/15 suites, 95 passed / 3 skipped of 98, with no worker warning.
|
The The It reproduces locally when the suite runs in a single process. With the test file in its previous form,
Shrinking the body from 256 KB to 4 KB did not fix it, so the leak is the unfinished connection rather than the unsent bytes. Both workflow runs on this push concluded |
Use the named biggerThanMaxFileSize code and drop the explanatory comments.
|
I reproduced this on the published tarball and can confirm the report, plus one thing this fix does not yet cover. Confirmed on
The gap. All five checks live in This PR adds the two size checks. Still uncovered after it: Routing the octet path through I have not opened a competing PR, and I am happy to test a revision if useful. |
|
Thanks for checking this on 3.5.4. I measured the three options on
So I'd keep this PR to the two size limits in its title and send the other checks as a separate PR, unless the maintainers would rather have one change that routes the octet path through |
|
Pushed 6d9e2a0. The two size-limit tests listened on 13537 and 13538, and |
|
Want your agent to iterate on Greptile's feedback? Start a greploop in Codex and it will work through the open comments and keep going until this PR reviews clean. |
The octet-stream upload path does not enforce the documented
maxFileSize/maxTotalFileSizelimits, unlike the multipart path.Steps to reproduce
POST a 256KB body with
Content-Type: application/octet-streamto a form configured withmaxFileSize: 1024:ACTUAL:
errisnull, one file is returned with size 262144, and the over-sized file is committed to disk viafile.end().EXPECTED: an error, no file returned, and nothing left on disk. With this fix the error is
biggerThanMaxFileSize(1016). The multipart path also rejects this request and leaves nothing on disk, but reportsbiggerThanTotalMaxFileSize(1009), because it checks the total while the file streams andmaxFileSizeonly when the part ends.Root cause
The octet-stream plugin's
_parser.on("data", ...)handler insrc/plugins/octetstream.jswrites each chunk straight to the file with no size check, and it bypasses_handlePart()insrc/Formidable.jswhere the multipart size caps are enforced. As a result a raw octet-stream body of any size is accepted regardless of the configured limits.The README documents
maxFileSizeandmaxTotalFileSizeas limiting each file and the batch respectively, with defaults, and does not exempt octet-stream.Fix
Accumulate the per-file and running total sizes before each write and abort via
this._error(...)with the existingFormidableErrorcodesbiggerThanMaxFileSize/biggerThanTotalMaxFileSizethat_handlePartuses. Both caps are checked before each chunk is written, so the body is rejected at the first chunk that crosses a cap. In-limit uploads are unaffected. Because the octet-stream file is tracked inopenedFiles, the shared_errorcleanup callsfile.destroy(), which unlinks the partial file, so no bytes remain on disk (the same cleanup the multipart path relies on).Tests
Two integration cases in
test/integration/octet-stream.test.js: a 256KB octet-stream body withmaxFileSize: 1024must be rejected with code 1016, and a 3000-byte body withmaxFileSize: 4096andmaxTotalFileSize: 2048with code 1009. Both must return no files. Both fail on the current source, where the upload is accepted witherrnull, and pass with the fix.Suite status: 96 passed / 3 skipped across 15 jest suites, and 11/11 node tests.


Confidence Score: 5/5
The PR appears safe to merge; no outstanding issues were found.Summary
Adds
maxFileSizeandmaxTotalFileSizechecks before octet-stream chunks are written.Reviews (11) · Last reviewed commit: "test: give the octet-stream limit tests ..." · Reviewed by Greptile