[ 
https://issues.apache.org/jira/browse/THRIFT-6266?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jens Geyer updated THRIFT-6266:
-------------------------------
    Description: 
{{lib/py/src/server/THttpServer.py}} parses the header with a bare {{int()}} 
({{:100}}):

{code:python}
length = self.headers['Content-Length']
...
    length = int(length)
...
    self.send_error(400, "Invalid Content-Length")
{code}

The field's grammar in RFC 9110 is one or more digits, and Python's {{int()}} 
accepts more than that:
* a leading sign ({{+12}});
* PEP 515 underscores ({{1_2}});
* whitespace other than spaces and tabs around the number, such as a no-break 
space, a vertical tab or a form feed.

Each of these is read as a length of 12, and the request is served. A peer and 
this server can therefore disagree about whether a message is well formed.

Spaces and tabs around the value are a different case. They are not part of the 
field value (RFC 9110 section 5.5), so {{" 12 "}} is a valid length of 12.

The D binding answered the same question for its HTTP transport in "Read HTTP 
header names and wire numbers against their grammars".

h2. Suggested fix

Strip spaces and tabs, then require what remains to consist of digits only. 
That means a full match of {{[0-9]+}}: a pattern ending in {{$}} would also 
accept a trailing newline. Otherwise, send the 400 that is already prepared for 
the malformed case.

_Drafted with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._


  was:
{{lib/py/src/server/THttpServer.py}} parses the header with a bare {{int()}} 
({{:100}}):

{code:python}
length = self.headers['Content-Length']
...
    length = int(length)
...
    self.send_error(400, "Invalid Content-Length")
{code}

Python's {{int()}} is more permissive than RFC 9110's grammar for the field, 
which is one or more digits and nothing else. It accepts a leading sign 
({{+12}}), surrounding whitespace ({{" 12 "}}) and PEP 515 underscores 
({{1_2}}), so all three are taken as a length of 12 and the request is served. 
A peer and this server can therefore disagree about whether a message is well 
formed.

The D binding answered the same question for its HTTP transport in "Read HTTP 
header names and wire numbers against their grammars".

h2. Suggested fix

Require the field to match {{^[0-9]+$}} before converting, and send the 400 
that is already prepared for the malformed case otherwise.

_Drafted with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._


> Python: THttpServer accepts Content-Length values that are not valid HTTP 
> numbers
> ---------------------------------------------------------------------------------
>
>                 Key: THRIFT-6266
>                 URL: https://issues.apache.org/jira/browse/THRIFT-6266
>             Project: Thrift
>          Issue Type: Bug
>          Components: Python - Library
>            Reporter: Jens Geyer
>            Priority: Minor
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> {{lib/py/src/server/THttpServer.py}} parses the header with a bare {{int()}} 
> ({{:100}}):
> {code:python}
> length = self.headers['Content-Length']
> ...
>     length = int(length)
> ...
>     self.send_error(400, "Invalid Content-Length")
> {code}
> The field's grammar in RFC 9110 is one or more digits, and Python's {{int()}} 
> accepts more than that:
> * a leading sign ({{+12}});
> * PEP 515 underscores ({{1_2}});
> * whitespace other than spaces and tabs around the number, such as a no-break 
> space, a vertical tab or a form feed.
> Each of these is read as a length of 12, and the request is served. A peer 
> and this server can therefore disagree about whether a message is well formed.
> Spaces and tabs around the value are a different case. They are not part of 
> the field value (RFC 9110 section 5.5), so {{" 12 "}} is a valid length of 12.
> The D binding answered the same question for its HTTP transport in "Read HTTP 
> header names and wire numbers against their grammars".
> h2. Suggested fix
> Strip spaces and tabs, then require what remains to consist of digits only. 
> That means a full match of {{[0-9]+}}: a pattern ending in {{$}} would also 
> accept a trailing newline. Otherwise, send the 400 that is already prepared 
> for the malformed case.
> _Drafted with AI assistance (Claude Opus 5); reviewed and filed by Jens 
> Geyer._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to