pjfanning opened a new pull request, #1266:
URL: https://github.com/apache/pekko-http/pull/1266

   ### Motivation
   
   `BodyPartParser` had no limit on how many body parts one multipart entity 
may contain. Each part costs a set of parsed headers and an entity of its own, 
so a body packed with minimal parts — a boundary, a short `Content-Disposition` 
and an empty body, on the order of 40–60 bytes each — amplifies the work and 
allocation a request of a given size causes. A body at the default 
`max-content-length` of 8m runs to **well over a hundred thousand parts**, all 
of which the strict and form-field paths materialise (a `VectorBuilder`, a 
field map, a `HttpEntity.Strict` per part).
   
   `max-content-length` bounds the bytes but not that amplification. Peer 
frameworks grew an explicit part limit for the same reason — Commons 
FileUpload's `FileCountLimit` (FILEUPLOAD-279), Spring's `maxParts`, Jetty's 
`maxFormKeys`.
   
   ### Modification
   
   Add a `max-part-count` parser setting, enforced where the parser starts the 
headers of a new part, failing the entity once it is exceeded. The three call 
sites that begin a part now go through `parsePartHeaderLines`; the recursive 
calls that continue the current part's headers are unaffected, as is the 
closing boundary, which does not start a part.
   
   ### On the default
   
   **10000 is deliberately generous, and I'd welcome a steer on it.** It is 
chosen to stay above the largest part count the test suite exercises — an 
existing case, "many small parts received in one go", that parses **5000** 
parts — rather than to be the tightest useful bound. It still cuts the worst 
case by more than an order of magnitude, and an application that knows its 
forms are small can set it far lower.
   
   I did not want to silently drop a documented capability for a low-severity 
amplification issue, which is why I sized the default around that test rather 
than adjusting the test. If you'd rather have a tighter default (1000 would 
match Jetty's form-key limit and is ample for real forms), that test can raise 
its own limit via config instead — say the word and I'll flip it.
   
   ### Result
   
   A multipart body can no longer be packed with an unbounded number of parts; 
the count is bounded by configuration.
   
   ### Tests
   
   - `sbt "http-tests/testOnly ...MultipartUnmarshallersSpec* 
...MarshallingSpec ...FileUploadDirectivesSpec"` — pass (95 tests), including 
the existing 5000-part case. A new test configures a limit of 2, sends 3 parts 
and expects the entity to fail; verified it fails with the limit check 
disabled, in both the CRLF and LF variants.
   - `sbt http-core/mimaReportBinaryIssues`, `sbt http/mimaReportBinaryIssues` 
— pass, with an exclude for the new method on the internal 
`BodyPartParser.Settings` (following the existing `max-chunk-count.excludes` 
precedent).
   - `sbt "+http-core/compile"` — pass on 2.13.18 and 3.3.8.
   - Native `scalafmt` clean.
   
   ### References
   
   None - bounds the number of parts in a multipart entity
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to