Skip to content

Commit 812360f

Browse files
gh-84443: SSLSocket.recv_into() now support buffer protocol with itemsize != 1 (GH-20310)
It is also no longer use __len__(). Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 22e411e commit 812360f

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

Lib/ssl.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,10 +1270,14 @@ def recv(self, buflen=1024, flags=0):
12701270

12711271
def recv_into(self, buffer, nbytes=None, flags=0):
12721272
self._checkClosed()
1273-
if buffer and (nbytes is None):
1274-
nbytes = len(buffer)
1275-
elif nbytes is None:
1276-
nbytes = 1024
1273+
if nbytes is None:
1274+
if buffer is not None:
1275+
with memoryview(buffer) as view:
1276+
nbytes = view.nbytes
1277+
if not nbytes:
1278+
nbytes = 1024
1279+
else:
1280+
nbytes = 1024
12771281
if self._sslobj is not None:
12781282
if flags != 0:
12791283
raise ValueError(

Lib/test/test_ssl.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from test.support import threading_helper
1111
from test.support import warnings_helper
1212
from test.support import asyncore
13+
import array
1314
import re
1415
import socket
1516
import select
@@ -3517,6 +3518,27 @@ def test_recv_zero(self):
35173518
self.assertEqual(s.recv(0), b"")
35183519
self.assertEqual(s.recv_into(bytearray()), 0)
35193520

3521+
def test_recv_into_buffer_protocol_len(self):
3522+
server = ThreadedEchoServer(CERTFILE)
3523+
self.enterContext(server)
3524+
s = socket.create_connection((HOST, server.port))
3525+
self.addCleanup(s.close)
3526+
s = test_wrap_socket(s, suppress_ragged_eofs=False)
3527+
self.addCleanup(s.close)
3528+
3529+
s.send(b"data")
3530+
buf = array.array('I', [0, 0])
3531+
self.assertEqual(s.recv_into(buf), 4)
3532+
self.assertEqual(bytes(buf)[:4], b"data")
3533+
3534+
class B(bytearray):
3535+
def __len__(self):
3536+
1/0
3537+
s.send(b"data")
3538+
buf = B(6)
3539+
self.assertEqual(s.recv_into(buf), 4)
3540+
self.assertEqual(bytes(buf), b"data\0\0")
3541+
35203542
def test_nonblocking_send(self):
35213543
server = ThreadedEchoServer(CERTFILE,
35223544
certreqs=ssl.CERT_NONE,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The :meth:`ssl.SSLSocket.recv_into` method no longer requires the *buffer*
2+
argument to implement ``__len__`` and supports buffers with arbitrary item size.

0 commit comments

Comments
 (0)