]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-84443: SSLSocket.recv_into() now support buffer protocol with itemsize != 1 (GH...
authorZackery Spytz <zspytz@gmail.com>
Mon, 27 Nov 2023 17:15:39 +0000 (09:15 -0800)
committerGitHub <noreply@github.com>
Mon, 27 Nov 2023 17:15:39 +0000 (19:15 +0200)
It is also no longer use __len__().

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/ssl.py
Lib/test/test_ssl.py
Misc/NEWS.d/next/Library/2020-05-21-23-32-46.bpo-40262.z4fQv1.rst [new file with mode: 0644]

index 62e55857141dfca83f264b8e6624e2c8f4f2f2a1..36fca9d4aa93d13f52ddfd0a55b54b7a4c6e382b 100644 (file)
@@ -1270,10 +1270,14 @@ class SSLSocket(socket):
 
     def recv_into(self, buffer, nbytes=None, flags=0):
         self._checkClosed()
-        if buffer and (nbytes is None):
-            nbytes = len(buffer)
-        elif nbytes is None:
-            nbytes = 1024
+        if nbytes is None:
+            if buffer is not None:
+                with memoryview(buffer) as view:
+                    nbytes = view.nbytes
+                if not nbytes:
+                    nbytes = 1024
+            else:
+                nbytes = 1024
         if self._sslobj is not None:
             if flags != 0:
                 raise ValueError(
index 9ade595ef8ae7ee32ec886913d8d3ac6cc242216..aecba89cde1495b7310aa474cef99c942d5e6969 100644 (file)
@@ -10,6 +10,7 @@ from test.support import socket_helper
 from test.support import threading_helper
 from test.support import warnings_helper
 from test.support import asyncore
+import array
 import re
 import socket
 import select
@@ -3517,6 +3518,27 @@ class ThreadedTests(unittest.TestCase):
         self.assertEqual(s.recv(0), b"")
         self.assertEqual(s.recv_into(bytearray()), 0)
 
+    def test_recv_into_buffer_protocol_len(self):
+        server = ThreadedEchoServer(CERTFILE)
+        self.enterContext(server)
+        s = socket.create_connection((HOST, server.port))
+        self.addCleanup(s.close)
+        s = test_wrap_socket(s, suppress_ragged_eofs=False)
+        self.addCleanup(s.close)
+
+        s.send(b"data")
+        buf = array.array('I', [0, 0])
+        self.assertEqual(s.recv_into(buf), 4)
+        self.assertEqual(bytes(buf)[:4], b"data")
+
+        class B(bytearray):
+            def __len__(self):
+                1/0
+        s.send(b"data")
+        buf = B(6)
+        self.assertEqual(s.recv_into(buf), 4)
+        self.assertEqual(bytes(buf), b"data\0\0")
+
     def test_nonblocking_send(self):
         server = ThreadedEchoServer(CERTFILE,
                                     certreqs=ssl.CERT_NONE,
diff --git a/Misc/NEWS.d/next/Library/2020-05-21-23-32-46.bpo-40262.z4fQv1.rst b/Misc/NEWS.d/next/Library/2020-05-21-23-32-46.bpo-40262.z4fQv1.rst
new file mode 100644 (file)
index 0000000..c017a1c
--- /dev/null
@@ -0,0 +1,2 @@
+The :meth:`ssl.SSLSocket.recv_into` method no longer requires the *buffer*
+argument to implement ``__len__`` and supports buffers with arbitrary item size.