HTTP request-line parsing splits on Unicode whitespace #78154
Copy link
Copy link
Closed as not planned
Labels
3.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-unicodetype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
| BPO | 33973 |
|---|---|
| Nosy | @vstinner, @ezio-melotti, @tipabu |
| PRs |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = None
closed_at = None
created_at = <Date 2018-06-26.18:39:29.435>
labels = ['type-bug', '3.8', '3.9', '3.7', 'library', 'expert-unicode']
title = 'HTTP request-line parsing splits on Unicode whitespace'
updated_at = <Date 2020-01-25.13:18:38.086>
user = 'https://github.com/tipabu'bugs.python.org fields:
activity = <Date 2020-01-25.13:18:38.086>
actor = 'cheryl.sabella'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)', 'Unicode']
creation = <Date 2018-06-26.18:39:29.435>
creator = 'tburke'
dependencies = []
files = []
hgrepos = []
issue_num = 33973
keywords = ['patch']
message_count = 2.0
messages = ['320507', '320529']
nosy_count = 3.0
nosy_names = ['vstinner', 'ezio.melotti', 'tburke']
pr_nums = ['7932']
priority = 'normal'
resolution = None
stage = 'patch review'
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue33973'
versions = ['Python 3.7', 'Python 3.8', 'Python 3.9']Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-unicodetype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Activity
tipabu commentedon Jun 26, 2018
This causes (admittedly, buggy) clients that would work with a Python 2 server to stop working when the server upgrades to Python 3. To demonstrate, run
python2.7 -m SimpleHTTPServer 8027in one terminal andcurl -v http://127.0.0.1:8027/你好in another -- curl reports...while repeating the experiment with
python3.6 -m http.server 8036andcurl -v http://127.0.0.1:8036/你好givesGranted, a well-behaved client would have quoted the UTF-8 '你好' as '%E4%BD%A0%E5%A5%BD' (in which case everything would have behaved as expected), but RFC 7230 is pretty clear that the request-line should be SP-delimited. While it notes that "recipients MAY instead parse on whitespace-delimited word boundaries and, aside from the CRLF terminator, treat any form of whitespace as the SP separator", it goes on to say that "such whitespace includes one or more of the following octets: SP, HTAB, VT (%x0B), FF (%x0C), or bare CR" with no mention of characters like the (ISO-8859-1 encoded) non-breaking space that caused the 400 response.
FWIW, there was a similar unicode-separators-are-not-the-right-separators bug in header parsing a while back: https://bugs.python.org/issue22233
vstinner commentedon Jun 27, 2018
isspace() is also true for another non-ASCII character: U+0085 (b'\x85').
tipabu commentedon Jan 25, 2024
Note that this is still an issue; tested anew on 3.10.12, 3.11.7, 3.12.1, and a 3.13 alpha.
encukou commentedon Mar 12, 2024
I'm sorry for only getting to this PR now.
IMO, there are three issues to consider:
Since this is about illegal (unquoted) requests, the first point doesn't cone into play much, except that this with this PR, we lose support for alternate ASCII whitespace (HTAB, VT (%x0B), FF (%x0C), or bare CR) which is mentioned in RFC 9112.
Regarding compatibility with earlier 3.x versions: turning
split()intosplit(' ')meansBoth could break software that relies on those non-standard quirks.
That leaves compatibility with Python 2. However, in 2024, this point has lost its importance. (Again, sorry for getting to this late.)
I would prefer closing this issue and PR. With Python 2 gone, this would be trading one set of non-standard semantics for another.
Or perhaps we could heed the RFC's warning about lenient parsing, and -- with a deprecation period -- make the parsing strict: reject all unexpected characters, including all non-ASCII ones, misplaced spaces, etc.
encukou commentedon Apr 15, 2024
I plan to close the issue and PR in a month if there are no objections.
tipabu commentedon Apr 26, 2024
We can go ahead and close it. Even if I had the bandwidth to rework the PR to tighten parsing rules and follow through on a deprecate-remove cycle, the software I was working on that caused me to discover the issue still wouldn't be able to make use of the change. At some point, it probably needs to just stop relying on stdlib for HTTP parsing all together.
At least this bug doesn't have any (obvious) security implications; if you have a chance, I'd appreciate some thoughts around #81274 / #13788