Skip to content

Commit 1dd69c5

Browse files
authored
Raise ValueError if method contains control characters (#1800)
1 parent a46c08c commit 1dd69c5

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

Diff for: CHANGES.rst

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changes
22
=======
33

4+
master (dev)
5+
------------
6+
7+
* Raise ``ValueError`` if control characters are given in
8+
the ``method`` parameter of ``HTTPConnection.request()`` (Pull #1800)
9+
10+
411
1.25.8 (2020-01-20)
512
-------------------
613

Diff for: src/urllib3/connection.py

+14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from __future__ import absolute_import
2+
import re
23
import datetime
34
import logging
45
import os
@@ -58,6 +59,8 @@ class ConnectionError(Exception):
5859
# (ie test_recent_date is failing) update it to ~6 months before the current date.
5960
RECENT_DATE = datetime.date(2019, 1, 1)
6061

62+
_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
63+
6164

6265
class DummyConnection(object):
6366
"""Used to detect a failed ConnectionCls import."""
@@ -184,6 +187,17 @@ def connect(self):
184187
conn = self._new_conn()
185188
self._prepare_conn(conn)
186189

190+
def putrequest(self, method, url, *args, **kwargs):
191+
"""Send a request to the server"""
192+
match = _CONTAINS_CONTROL_CHAR_RE.search(method)
193+
if match:
194+
raise ValueError(
195+
"Method cannot contain non-token characters %r (found at least %r)"
196+
% (method, match.group())
197+
)
198+
199+
return _HTTPConnection.putrequest(self, method, url, *args, **kwargs)
200+
187201
def request_chunked(self, method, url, body=None, headers=None):
188202
"""
189203
Alternative to the common request method, which sends the

Diff for: test/with_dummyserver/test_connectionpool.py

+6
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,12 @@ def test_dns_error(self):
677677
with pytest.raises(MaxRetryError):
678678
pool.request("GET", "/test", retries=2)
679679

680+
@pytest.mark.parametrize("char", [" ", "\r", "\n", "\x00"])
681+
def test_invalid_method_not_allowed(self, char):
682+
with pytest.raises(ValueError):
683+
with HTTPConnectionPool(self.host, self.port) as pool:
684+
pool.request("GET" + char, "/")
685+
680686
def test_percent_encode_invalid_target_chars(self):
681687
with HTTPConnectionPool(self.host, self.port) as pool:
682688
r = pool.request("GET", "/echo_params?q=\r&k=\n \n")

0 commit comments

Comments
 (0)