summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Lib/http/client.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Lib/http/client.py')
-rw-r--r--contrib/tools/python3/Lib/http/client.py32
1 files changed, 26 insertions, 6 deletions
diff --git a/contrib/tools/python3/Lib/http/client.py b/contrib/tools/python3/Lib/http/client.py
index fb29923d942..dd5f4136e9e 100644
--- a/contrib/tools/python3/Lib/http/client.py
+++ b/contrib/tools/python3/Lib/http/client.py
@@ -111,6 +111,11 @@ responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()}
_MAXLINE = 65536
_MAXHEADERS = 100
+# Data larger than this will be read in chunks, to prevent extreme
+# overallocation.
+_MIN_READ_BUF_SIZE = 1 << 20
+
+
# Header name/value ABNF (http://tools.ietf.org/html/rfc7230#section-3.2)
#
# VCHAR = %x21-7E
@@ -230,7 +235,7 @@ def _read_headers(fp):
def _parse_header_lines(header_lines, _class=HTTPMessage):
"""
- Parses only RFC2822 headers from header lines.
+ Parses only RFC 5322 headers from header lines.
email Parser wants to see strings rather than bytes.
But a TextIOWrapper around self.rfile would buffer too many bytes
@@ -243,7 +248,7 @@ def _parse_header_lines(header_lines, _class=HTTPMessage):
return email.parser.Parser(_class=_class).parsestr(hstring)
def parse_headers(fp, _class=HTTPMessage):
- """Parses only RFC2822 headers from a file pointer."""
+ """Parses only RFC 5322 headers from a file pointer."""
headers = _read_headers(fp)
return _parse_header_lines(headers, _class)
@@ -639,10 +644,25 @@ class HTTPResponse(io.BufferedIOBase):
reading. If the bytes are truly not available (due to EOF), then the
IncompleteRead exception can be used to detect the problem.
"""
- data = self.fp.read(amt)
- if len(data) < amt:
- raise IncompleteRead(data, amt-len(data))
- return data
+ cursize = min(amt, _MIN_READ_BUF_SIZE)
+ data = self.fp.read(cursize)
+ if len(data) >= amt:
+ return data
+ if len(data) < cursize:
+ raise IncompleteRead(data, amt - len(data))
+
+ data = io.BytesIO(data)
+ data.seek(0, 2)
+ while True:
+ # This is a geometric increase in read size (never more than
+ # doubling out the current length of data per loop iteration).
+ delta = min(cursize, amt - cursize)
+ data.write(self.fp.read(delta))
+ if data.tell() >= amt:
+ return data.getvalue()
+ cursize += delta
+ if data.tell() < cursize:
+ raise IncompleteRead(data.getvalue(), amt - data.tell())
def _safe_readinto(self, b):
"""Same as _safe_read, but for reading into a buffer."""