Skip to content

fix: harden HTTP message framing on request and response paths - #2665

Open
zyuhao7 wants to merge 4 commits into
drogonframework:masterfrom
zyuhao7:fix/http-framing-hardening
Open

zyuhao7 wants to merge 4 commits into
drogonframework:masterfrom
zyuhao7:fix/http-framing-hardening

Conversation

@zyuhao7

@zyuhao7 zyuhao7 commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Summary

This combines and supersedes #2652 and #2653, rebased onto current master.

Content-Length parsing is validated in one shared helper (parseContentLength). A value that is not 1*DIGIT — empty, signed, containing whitespace, with trailing junk, or overflowing — is now a framing error instead of being silently reinterpreted. Repeated values must agree, and Content-Length with Transfer-Encoding is rejected. All of these let two peers disagree about where a body ends, which desynchronizes keep-alive and pipelined connections.

Request side (RFC 9110 §8.6, RFC 9112 §5.1, §6.3)

  • Reject a Content-Length that is not 1*DIGIT.
  • Reject a repeated Content-Length whose value differs from the first.
  • Reject whitespace between a field name and its colon.
  • Reject a malformed header line instead of treating it as end-of-headers.

Response side (RFC 9112 §6.3, §7.1)

  • Reject a malformed or repeated Content-Length.
  • Reject Content-Length together with Transfer-Encoding.
  • Recognize the final transfer coding case-insensitively and accept parameters on it.
  • Consume the whole chunked trailer section instead of a single line.
  • Treat 204, 304 and informational responses as bodyless.
  • Never read a body for a response to HEAD.
  • Skip 1xx responses in the HTTP client and keep waiting for the final response.

Tests

  • New response-parser unit tests cover malformed/overflowing/repeated Content-Length, CL+TE, case-insensitive chunked coding with parameters, trailers, bodyless statuses, informational responses and HEAD.
  • New raw-socket integration tests exercise the request framing rules end to end (ContentLengthFramingTest.cc).
  • unittest: 1986 assertions in 112 test cases, all passing.
  • Framing integration tests: 6/6 passing against integration_test_server.

Fixes #2648

Validate Content-Length as 1*DIGIT in one shared helper and use it on both
sides. An empty value, a sign, embedded whitespace, trailing junk or an
overflow is now a framing error instead of being silently reinterpreted,
which previously let peers disagree about where a body ends.

Request side (RFC 9110 section 8.6, RFC 9112 sections 5.1 and 6.3):
- reject a Content-Length that is not 1*DIGIT
- reject a repeated value that differs from the first one
- reject whitespace between a field name and its colon
- reject a malformed header line instead of treating it as end-of-headers

Response side (RFC 9112 sections 6.3 and 7.1):
- reject a malformed or repeated Content-Length
- reject Content-Length together with Transfer-Encoding
- recognize the final transfer coding case-insensitively and allow
  parameters on it
- consume the whole chunked trailer section
- treat 204, 304 and informational responses as bodyless
- never read a body for a response to HEAD
- skip 1xx responses in the HTTP client and keep waiting for the final one

Adds response parser unit tests and raw-socket integration tests that
exercise the request framing rules end to end.

Fixes drogonframework#2648

This branch has not been deployed

No deployments
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.

HTTP request parsing: remaining Content-Length framing gaps after #2646

1 participant