Skip to content

Validate Content-Length format in ClientRequest#12385

Open
jmestwa-coder wants to merge 3 commits intoaio-libs:masterfrom
jmestwa-coder:fix-content-length-validation
Open

Validate Content-Length format in ClientRequest#12385
jmestwa-coder wants to merge 3 commits intoaio-libs:masterfrom
jmestwa-coder:fix-content-length-validation

Conversation

@jmestwa-coder
Copy link
Copy Markdown

What do these changes do?

This change adds strict validation for the Content-Length header in ClientRequest.

Currently, _get_content_length() uses Python’s int() for parsing, which accepts non-RFC-compliant values such as negative numbers or values with whitespace. This patch introduces a DIGITS-only validation to ensure the header follows the same format already enforced by the HTTP parser.

Are there changes in behavior for the user?

Yes, but only for invalid inputs.

  • Valid Content-Length values (e.g., "0", "100") are unaffected.
  • Non-compliant values (e.g., "-100", " 100", "+100") will now raise a ValueError instead of being accepted.

This aligns behavior across send and receive paths and avoids unexpected behavior when invalid values are provided.

Is it a substantial burden for the maintainers to support this?

No.

  • The change is minimal and localized to a single method.
  • It reuses the same validation approach already used in the HTTP parser.
  • No new abstractions or dependencies are introduced.
  • The behavior is consistent with existing expectations for header validation.

This should not increase maintenance overhead.

Related issue number

N/A

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
  • Add a new news fragment into the CHANGES/ folder

@jmestwa-coder jmestwa-coder requested a review from asvetlov as a code owner April 17, 2026 07:03
@Dreamsorcerer
Copy link
Copy Markdown
Member

Could you add an end-to-end test in test_web_functional.py? I think this code is actually unreachable and even the current check can be removed. I'm pretty sure we already validate it in the parser.

@Dreamsorcerer Dreamsorcerer added the pr-unfinished The PR is unfinished and may need a volunteer to complete it label Apr 17, 2026
@jmestwa-coder jmestwa-coder force-pushed the fix-content-length-validation branch 2 times, most recently from 49f902f to 4296e72 Compare April 20, 2026 07:12
Comment thread aiohttp/client_reqrep.py Fixed
@jmestwa-coder jmestwa-coder force-pushed the fix-content-length-validation branch from 4296e72 to dd083ea Compare April 20, 2026 07:19
Reject non-RFC-compliant Content-Length values to align with HTTP parser behavior and ensure consistent validation.
@jmestwa-coder jmestwa-coder force-pushed the fix-content-length-validation branch from dd083ea to a66944d Compare April 20, 2026 07:58
@jmestwa-coder
Copy link
Copy Markdown
Author

Added an end-to-end test in test_web_functional.py to cover this case.
Invalid Content-Length values are now rejected, while valid ones work as before.

Let me know if you'd like any changes.

@github-actions github-actions bot removed the pr-unfinished The PR is unfinished and may need a volunteer to complete it label Apr 20, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.92%. Comparing base (24ed3b3) to head (ee47a1b).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #12385   +/-   ##
=======================================
  Coverage   98.92%   98.92%           
=======================================
  Files         134      134           
  Lines       46616    46641   +25     
  Branches     2429     2430    +1     
=======================================
+ Hits        46114    46139   +25     
  Misses        373      373           
  Partials      129      129           
Flag Coverage Δ
CI-GHA 98.98% <100.00%> (+<0.01%) ⬆️
OS-Linux 98.72% <100.00%> (+<0.01%) ⬆️
OS-Windows 96.98% <100.00%> (+<0.01%) ⬆️
OS-macOS 97.88% <100.00%> (-0.01%) ⬇️
Py-3.10.11 97.39% <100.00%> (+<0.01%) ⬆️
Py-3.10.20 97.86% <100.00%> (+<0.01%) ⬆️
Py-3.11.15 98.11% <100.00%> (+<0.01%) ⬆️
Py-3.11.9 97.65% <100.00%> (-0.01%) ⬇️
Py-3.12.10 97.73% <100.00%> (+<0.01%) ⬆️
Py-3.12.13 98.19% <100.00%> (-0.01%) ⬇️
Py-3.13.13 98.45% <100.00%> (+<0.01%) ⬆️
Py-3.14.4 98.50% <100.00%> (-0.01%) ⬇️
Py-3.14.4t 97.51% <100.00%> (+<0.01%) ⬆️
Py-pypy3.11.15-7.3.21 97.34% <100.00%> (-0.01%) ⬇️
VM-macos 97.88% <100.00%> (-0.01%) ⬇️
VM-ubuntu 98.72% <100.00%> (+<0.01%) ⬆️
VM-windows 96.98% <100.00%> (+<0.01%) ⬆️
cython-coverage 38.20% <63.33%> (+0.01%) ⬆️

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

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

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 20, 2026

Merging this PR will not alter performance

✅ 67 untouched benchmarks
⏩ 4 skipped benchmarks1


Comparing jmestwa-coder:fix-content-length-validation (ee47a1b) with master (24ed3b3)

Open in CodSpeed

Footnotes

  1. 4 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.

with pytest.raises(ValueError, match="Invalid Content-Length header"):
req._get_content_length()

req.headers["Content-Length"] = " 100"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Strictly speaking, this produces a valid header: Content-Length: 100
We probably don't have a real preference on whether it's rejected or not, so probably better to just use another test example. e.g. ५ <- devengali number 5, which would pass through an int() call.

@Dreamsorcerer
Copy link
Copy Markdown
Member

Added an end-to-end test in test_web_functional.py to cover this case. Invalid Content-Length values are now rejected, while valid ones work as before.

Let me know if you'd like any changes.

Sorry, I thought this was validating the response. I've just realised this is validating the request, i.e. the data from the developer. I guess this looks fine as a simple improvement to sanity checking then.

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.

3 participants