Skip to content

Commit 4d0d24f

Browse files
authored
gh-112064: Fix incorrect handling of negative read sizes in HTTPResponse.read() (#128270)
The parameter `amt` of `HTTPResponse.read()`, which could be a negative integer, has not been handled before and led to waiting for the connection to close for `keep-alive connections`. Now, this has been fixed, and passing negative values to `HTTPResponse().read()` works the same as passing `None` value.
1 parent 8e57877 commit 4d0d24f

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

Lib/http/client.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ def read(self, amt=None):
472472
if self.chunked:
473473
return self._read_chunked(amt)
474474

475-
if amt is not None:
475+
if amt is not None and amt >= 0:
476476
if self.length is not None and amt > self.length:
477477
# clip the read to the "end of response"
478478
amt = self.length
@@ -590,6 +590,8 @@ def _get_chunk_left(self):
590590

591591
def _read_chunked(self, amt=None):
592592
assert self.chunked != _UNKNOWN
593+
if amt is not None and amt < 0:
594+
amt = None
593595
value = []
594596
try:
595597
while (chunk_left := self._get_chunk_left()) is not None:

Lib/test/test_httplib.py

+19
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,25 @@ def test_chunked(self):
10921092
self.assertEqual(resp.read(), expected)
10931093
resp.close()
10941094

1095+
# Explicit full read
1096+
for n in (-123, -1, None):
1097+
with self.subTest('full read', n=n):
1098+
sock = FakeSocket(chunked_start + last_chunk + chunked_end)
1099+
resp = client.HTTPResponse(sock, method="GET")
1100+
resp.begin()
1101+
self.assertTrue(resp.chunked)
1102+
self.assertEqual(resp.read(n), expected)
1103+
resp.close()
1104+
1105+
# Read first chunk
1106+
with self.subTest('read1(-1)'):
1107+
sock = FakeSocket(chunked_start + last_chunk + chunked_end)
1108+
resp = client.HTTPResponse(sock, method="GET")
1109+
resp.begin()
1110+
self.assertTrue(resp.chunked)
1111+
self.assertEqual(resp.read1(-1), b"hello worl")
1112+
resp.close()
1113+
10951114
# Various read sizes
10961115
for n in range(1, 12):
10971116
sock = FakeSocket(chunked_start + last_chunk + chunked_end)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix incorrect handling of negative read sizes in :meth:`HTTPResponse.read
2+
<http.client.HTTPResponse.read>`. Patch by Yury Manushkin.

0 commit comments

Comments
 (0)