From 9c3d0e6fe30b5432ab33ba8a5d7551323dd061b0 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 6 Sep 2017 06:51:40 -0700 Subject: [PATCH 1/2] bpo-27340: Use memoryview in SSLSocket.sendall() SSLSocket.sendall() now uses memoryview to create slices of data. This fix support for all bytes-like object. It is also more efficient and avoids costly copies. Signed-off-by: Christian Heimes --- Lib/ssl.py | 3 ++- Lib/test/test_ssl.py | 12 +++++++++++- .../Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst diff --git a/Lib/ssl.py b/Lib/ssl.py index 8ad4a339a933d7..ced1c068bba813 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -961,8 +961,9 @@ def sendall(self, data, flags=0): self.__class__) amount = len(data) count = 0 + view = memoryview(data) while (count < amount): - v = self.send(data[count:]) + v = self.send(view[count:]) count += v else: return socket.sendall(self, data, flags) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 89b4609282f239..747661bc6d0b9c 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -18,6 +18,10 @@ import weakref import platform import functools +try: + import ctypes +except ImportError: + ctypes = None ssl = support.import_module("ssl") @@ -2891,6 +2895,13 @@ def _recvfrom_into(): self.assertEqual(s.read(-1, buffer), len(data)) self.assertEqual(buffer, data) + # sendall accepts bytes-like objects + if ctypes is not None: + ubyte = ctypes.c_ubyte * len(data) + byteslike = ubyte.from_buffer_copy(data) + s.sendall(byteslike) + self.assertEqual(s.read(), data) + # Make sure sendmsg et al are disallowed to avoid # inadvertent disclosure of data and/or corruption # of the encrypted data stream @@ -2898,7 +2909,6 @@ def _recvfrom_into(): self.assertRaises(NotImplementedError, s.recvmsg, 100) self.assertRaises(NotImplementedError, s.recvmsg_into, bytearray(100)) - s.write(b"over\n") self.assertRaises(ValueError, s.recv, -1) diff --git a/Misc/NEWS.d/next/Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst b/Misc/NEWS.d/next/Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst new file mode 100644 index 00000000000000..368518e2d6f9b4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst @@ -0,0 +1,3 @@ +SSLSocket.sendall() now uses memoryview to create slices of data. This fix +support for all bytes-like object. It is also more efficient and avoids +costly copies. From 1dae12fc88daba9645b1388b1d61296b8dd5aa1d Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 6 Sep 2017 15:15:26 -0700 Subject: [PATCH 2/2] Cast view to bytes, fix typo Signed-off-by: Christian Heimes --- Lib/ssl.py | 10 +++++----- .../Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Lib/ssl.py b/Lib/ssl.py index ced1c068bba813..7a574dcb2b1e5a 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -959,12 +959,12 @@ def sendall(self, data, flags=0): raise ValueError( "non-zero flags not allowed in calls to sendall() on %s" % self.__class__) - amount = len(data) count = 0 - view = memoryview(data) - while (count < amount): - v = self.send(view[count:]) - count += v + with memoryview(data) as view, view.cast("B") as byte_view: + amount = len(byte_view) + while count < amount: + v = self.send(byte_view[count:]) + count += v else: return socket.sendall(self, data, flags) diff --git a/Misc/NEWS.d/next/Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst b/Misc/NEWS.d/next/Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst index 368518e2d6f9b4..2d05e10fc14fa7 100644 --- a/Misc/NEWS.d/next/Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst +++ b/Misc/NEWS.d/next/Library/2017-09-06-06-50-41.bpo-27340.GgekV5.rst @@ -1,3 +1,3 @@ -SSLSocket.sendall() now uses memoryview to create slices of data. This fix +SSLSocket.sendall() now uses memoryview to create slices of data. This fixes support for all bytes-like object. It is also more efficient and avoids costly copies.