Skip to content

fix: honor multipart part limits at the boundary - #3713

Open
hansu650 wants to merge 1 commit into
tornadoweb:masterfrom
hansu650:fix/multipart-part-limit
Open

fix: honor multipart part limits at the boundary#3713
hansu650 wants to merge 1 commit into
tornadoweb:masterfrom
hansu650:fix/multipart-part-limit

Conversation

@hansu650

@hansu650 hansu650 commented Sep 6, 2026

Copy link
Copy Markdown

Summary

ParseMultipartConfig.max_parts is documented as the maximum number of accepted parts, but the opening delimiter creates an empty first element in bytes.split(). Counting that element rejects a normal request containing exactly the configured limit (for example, one part with max_parts=1, or 100 parts with the default configuration).

Remove only that leading empty element before checking the limit. The bounded maxsplit and the pre-parse limit check are unchanged. This also permits an empty body containing just the closing boundary when max_parts=0.

Regression coverage

Four new test methods cover:

  • Limits 0, 1, 2, and the default 100, including below/at/above-limit cases.
  • Repeated field names and mixed file/text parts, so the limit counts parts rather than distinct names.
  • Rejection before either output dictionary is populated.
  • Preservation of the limit for a body without an initial delimiter and for repeated empty segments.

Before the production change, the multipart test class reports five subtest errors: the four exact-limit cases and the two-part file/text case. The entire httputil_test module passes after the fix.

Validation

Tested in a dedicated Python 3.13.15 environment on Windows, using the repository's pinned lint/docs dependencies.

  • python -bb -m tornado.test tornado.test.httputil_test: 62 tests passed.
  • python -bb -m tornado.test tornado.test.httpserver_test tornado.test.http1connection_test: 69 passed, 6 platform/configuration skips.
  • black --check --diff tornado demos and flake8: passed. Task-local environment/cache directories were excluded from flake8.
  • All three configured mypy checks passed: Linux and Windows targeting Python 3.11, and Linux targeting Python 3.13.
  • Sphinx coverage and doctest builds with -q -E -n -W: passed; 77 doctests, no failures.

Local platform limitations

The complete python -bb -m tornado.test --fail-if-logs=false run reports 1,249 tests, 112 skips, and 5 IPv6 connection errors. The same five errors occur on an unmodified checkout of 0096f2897c98facdcd9716009ee934a7381af5ef (1,245 tests, 112 skips). A standalone standard-library socket check also fails to connect to ::1 with WinError 10013 while IPv4 loopback succeeds. No tests were newly skipped or changed to hide these errors. The log-handling flag is the repository's Windows CI setting.

Strict Sphinx HTML builds of both the patch and that unmodified baseline report the same warning at docs/releases/v6.5.0.rst:75: unresolved bind_unix_socket on Windows. This unrelated documentation was not changed.

The C extension was not built locally, and the complete tox -e lint,docs,py3 command is not claimed as passing. Cross-platform checks remain for CI.

AI assistance: this patch and its tests were prepared with Codex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant