Skip to content

[PR #13760/ced8133e backport][3.14] Fix read_chunk() on body parts with a zero Content-Length - #13854

Merged
Dreamsorcerer merged 2 commits into
3.14from
patchback/backports/3.14/ced8133ea466a3bbe39d01a42bef79a5d2dbf1b5/pr-13760
Sep 29, 2026
Merged

Dreamsorcerer merged 2 commits into
3.14from
patchback/backports/3.14/ced8133ea466a3bbe39d01a42bef79a5d2dbf1b5/pr-13760

Conversation

@patchback

@patchback patchback Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

This is a backport of PR #13760 as merged into master (ced8133).

What do these changes do?

BodyPartReader.read_chunk() chose its read strategy by testing
self._length for truthiness. A part with an explicit Content-Length: 0 (legal
outside multipart/form-data, where the RFC 7578 special case nulls the
length out) therefore fell through to _read_chunk_from_stream(), whose
minimum chunk size assertion then failed for chunk sizes below the boundary
length:

AssertionError: Chunk size must be greater or equal than boundary length + 2

The truthiness test now checks against None instead, so an empty part takes
the length-based path: read_chunk() returns an immediate empty chunk and the
part reaches EOF, like any other part with a known length. The line dates back
to 2016 (f1351a3), when the stream fallback was introduced.

Are there changes in behavior for developers?

  • read_chunk(size) on a Content-Length: 0 part returns b"" for any size
    instead of raising AssertionError when size < len(boundary) + 2.
  • read() / release() on such parts already worked with the default chunk
    size (which satisfies the assertion by accident) and are unaffected beyond
    now being correct for small configured chunk sizes too.
  • multipart/form-data parts are unchanged: their Content-Length header is
    ignored per RFC 7578 §4.8, _length stays None, and the stream fallback
    still applies.
  • Streaming parts (no Content-Length) are unchanged: _length is None routes
    them to _read_chunk_from_stream() exactly as before.

Passing a negative chunk size remains a preexisting wart of the length-based
path (it makes the underlying read() drain the remaining stream before
failing); it affects parts with a positive Content-Length on master the
same way and is out of scope here.

Checklist

  • I think the code is well written
  • Unit tests for the changes exist
  • Documentation reflects the changes
  • If you provide code modification, please add yourself to CONTRIBUTORS.txt (added in this PR)
  • Add a news fragment in the CHANGES/ folder (PR number will follow once opened)

Fixes #13758.

Comment thread tests/test_multipart.py Outdated
@codecov

codecov Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.31%. Comparing base (be84682) to head (6888809).
⚠️ Report is 1 commits behind head on 3.14.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             3.14   #13854   +/-   ##
=======================================
  Coverage   96.31%   96.31%           
=======================================
  Files         160      160           
  Lines       52311    52318    +7     
  Branches     2840     2840           
=======================================
+ Hits        50381    50388    +7     
  Misses       1752     1752           
  Partials      178      178           
Flag Coverage Δ
Autobahn 21.39% <12.50%> (-0.01%) ⬇️
CI-GHA 96.14% <100.00%> (+<0.01%) ⬆️
OS-Linux 95.93% <100.00%> (+<0.01%) ⬆️
OS-Windows 94.01% <100.00%> (+<0.01%) ⬆️
OS-macOS 95.45% <100.00%> (+<0.01%) ⬆️
Py-3.10 95.41% <100.00%> (+<0.01%) ⬆️
Py-3.11 95.64% <100.00%> (+<0.01%) ⬆️
Py-3.12 95.72% <100.00%> (+<0.01%) ⬆️
Py-3.13 95.71% <100.00%> (+<0.01%) ⬆️
Py-3.14 95.74% <100.00%> (+<0.01%) ⬆️
Py-3.14t 95.11% <100.00%> (+<0.01%) ⬆️
Py-pypy-3.12 93.95% <100.00%> (+<0.01%) ⬆️
VM-macos 95.45% <100.00%> (+<0.01%) ⬆️
VM-ubuntu 95.93% <100.00%> (+<0.01%) ⬆️
VM-windows 94.01% <100.00%> (+<0.01%) ⬆️
cython-coverage 79.43% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Fixes a crash in multipart body reading with zero content length.

No blocking issues identified; safe to merge based on the reviewed change.

What we checked:

  • Fed multipart data in three-byte pieces and read empty parts at the first, middle, and last positions, then read subsequent length-delimited and stream-delimited parts and verify the closing delimiter and stream EOF. T-Rex
  • After the change, all seven scenarios passed and four short-read scenarios failed before. T-Rex
  • Ran the targeted regression and the multipart test file; the run finished with 142 passed and 2 skipped. T-Rex
  • No permanent source files were edited. T-Rex

Reviews (1) · Last reviewed commit: "Apply suggestion from @Dreamsorcerer"

@codspeed

codspeed Bot commented Sep 29, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 82 untouched benchmarks
⏩ 7 skipped benchmarks1


Comparing patchback/backports/3.14/ced8133ea466a3bbe39d01a42bef79a5d2dbf1b5/pr-13760 (6888809) with 3.14 (be84682)2

Open in CodSpeed

Footnotes

  1. 7 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

  2. No successful run was found on 3.14 (333f601) during the generation of this report, so be84682 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@Dreamsorcerer
Dreamsorcerer merged commit ec77a07 into 3.14 Sep 29, 2026
47 checks passed
@Dreamsorcerer
Dreamsorcerer deleted the patchback/backports/3.14/ced8133ea466a3bbe39d01a42bef79a5d2dbf1b5/pr-13760 branch September 29, 2026 02:11
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.

2 participants