]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-112064: Fix incorrect handling of negative read sizes in `HTTPResponse...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 28 Jan 2025 12:00:54 +0000 (13:00 +0100)
committerGitHub <noreply@github.com>
Tue, 28 Jan 2025 12:00:54 +0000 (12:00 +0000)
gh-112064: Fix incorrect handling of negative read sizes in `HTTPResponse.read()` (GH-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.
(cherry picked from commit 4d0d24f6e3dff2864007c3cfd1cf7d49c6ee5317)

Co-authored-by: Yury Manushkin <manushkin@gmail.com>
Lib/http/client.py
Lib/test/test_httplib.py
Misc/NEWS.d/next/Library/2024-12-26-11-00-03.gh-issue-112064.mCcw3B.rst [new file with mode: 0644]

index a353716a8506e65ae9ac9f06581ad17397e2f2a2..fb29923d94274cdf258dd47fc4404112822ae59c 100644 (file)
@@ -472,7 +472,7 @@ class HTTPResponse(io.BufferedIOBase):
         if self.chunked:
             return self._read_chunked(amt)
 
-        if amt is not None:
+        if amt is not None and amt >= 0:
             if self.length is not None and amt > self.length:
                 # clip the read to the "end of response"
                 amt = self.length
@@ -590,6 +590,8 @@ class HTTPResponse(io.BufferedIOBase):
 
     def _read_chunked(self, amt=None):
         assert self.chunked != _UNKNOWN
+        if amt is not None and amt < 0:
+            amt = None
         value = []
         try:
             while (chunk_left := self._get_chunk_left()) is not None:
index 9d853d254db7c6b1f41782e40da5b11efc54633d..0c4214addb9baa8dcae8cf62e031bb49f65f28e8 100644 (file)
@@ -1081,6 +1081,25 @@ class BasicTest(TestCase):
         self.assertEqual(resp.read(), expected)
         resp.close()
 
+        # Explicit full read
+        for n in (-123, -1, None):
+            with self.subTest('full read', n=n):
+                sock = FakeSocket(chunked_start + last_chunk + chunked_end)
+                resp = client.HTTPResponse(sock, method="GET")
+                resp.begin()
+                self.assertTrue(resp.chunked)
+                self.assertEqual(resp.read(n), expected)
+                resp.close()
+
+        # Read first chunk
+        with self.subTest('read1(-1)'):
+            sock = FakeSocket(chunked_start + last_chunk + chunked_end)
+            resp = client.HTTPResponse(sock, method="GET")
+            resp.begin()
+            self.assertTrue(resp.chunked)
+            self.assertEqual(resp.read1(-1), b"hello worl")
+            resp.close()
+
         # Various read sizes
         for n in range(1, 12):
             sock = FakeSocket(chunked_start + last_chunk + chunked_end)
diff --git a/Misc/NEWS.d/next/Library/2024-12-26-11-00-03.gh-issue-112064.mCcw3B.rst b/Misc/NEWS.d/next/Library/2024-12-26-11-00-03.gh-issue-112064.mCcw3B.rst
new file mode 100644 (file)
index 0000000..e885add
--- /dev/null
@@ -0,0 +1,2 @@
+Fix incorrect handling of negative read sizes in :meth:`HTTPResponse.read
+<http.client.HTTPResponse.read>`. Patch by Yury Manushkin.