Skip to content

THRIFT-6266: Read the THttpServer Content-Length against its grammar - #3864

Merged
Jens-G merged 1 commit into
apache:masterfrom
Jens-G:THRIFT-6266
Sep 17, 2026
Merged

Jens-G merged 1 commit into
apache:masterfrom
Jens-G:THRIFT-6266

Conversation

@Jens-G

@Jens-G Jens-G commented Sep 16, 2026

Copy link
Copy Markdown
Member

JIRA: THRIFT-6266
Client: py

THttpServer converted Content-Length with a bare int(). The field's grammar is 1*DIGIT (RFC 9110 §8.6), but int() also accepts:

  • a leading sign (+17);
  • underscores between digits (1_7);
  • whitespace of kinds a header value can carry around the number: no-break space \xa0, vertical tab, form feed, NEL. http.server decodes headers as Latin-1, so all of these reach the handler.

Each of these was taken as a length of 17 and the request was served. -0 passed as zero, and the request then failed without a response.

Change

The value is stripped of spaces and tabs, which surround a field value without being part of it (RFC 9110 §5.5). What remains has to match [0-9]+; anything else gets the existing 400 Invalid Content-Length. The ValueError handler stays: from Python 3.11 on, int() refuses more than 4300 digits.

A note on the ticket's examples: " 12 " is still accepted, because the whitespace around a field value is not part of the value. http.server already drops the leading part. The D binding does the same since 2f7714ebf. A list form such as 17, 17 is refused, which RFC 9110 permits.

Tests

New lib/py/test/test_http_server_content_length.py, registered in both lists in lib/py/Makefile.am. It sends raw requests to a running THttpServer and checks the status and whether the processor ran.

  • Served: 17, 017, and 17 with spaces or tabs on either side.
  • Refused with 400: a sign; underscores; \xa0, \x0b, \x0c or \x85 before or after the digits; an empty value, 0x11, 1e1, 17.0, 1 7, -0; a list of lengths.
  • Refused with 400 or 413: a 5000-digit length (the status depends on the Python version).

Results:

  • Against the unmodified server, the sign, underscore, whitespace and -0 cases fail.
  • Three mutations each fail one case:
    • stripping all whitespace instead of spaces and tabs;
    • not stripping at all;
    • dropping the ValueError handler (on Python 3.12).
  • The new tests and the existing test_http_server_body_size.py pass on Python 3.10, 3.12 and 3.14.
  • flake8 is clean.

🤖 Generated with Claude Code

Client: py

THttpServer converted Content-Length with int(), which accepts more than the
field's grammar of one or more decimal digits (RFC 9110 8.6). int() takes a
leading sign, underscores between digits, and whitespace such as a no-break
space, a vertical tab or a form feed around the number. Each of these was
read as a valid length, and the request was served. "-0" passed as zero, and
the request then failed without a response.

The value is now stripped of the spaces and tabs that surround a field value
without being part of it (RFC 9110 5.5). What remains must consist of digits
only. Anything else is answered with the 400 already sent for a malformed
length.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Jens-G
Jens-G requested a review from mhlakhani as a code owner September 16, 2026 20:47
@mergeable mergeable Bot added python build and general CI cmake, automake and build system changes labels Sep 16, 2026
@Jens-G Jens-G self-assigned this Sep 16, 2026
@Jens-G
Jens-G merged commit 4937856 into apache:master Sep 17, 2026
101 of 102 checks passed
@Jens-G
Jens-G deleted the THRIFT-6266 branch September 17, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build and general CI cmake, automake and build system changes python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant