diff --git a/Lib/ssl.py b/Lib/ssl.py index 96b62815853..8c2cdf1bb41 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -184,14 +184,16 @@ class SSLSocket(socket): else: return v else: - return socket.send(self, data, flags) + return self._sock.send(data, flags) - def sendto(self, data, addr, flags=0): + def sendto(self, data, flags_or_addr, addr=None): if self._sslobj: raise ValueError("sendto not allowed on instances of %s" % self.__class__) + elif addr is None: + return self._sock.sendto(data, flags_or_addr) else: - return socket.sendto(self, data, addr, flags) + return self._sock.sendto(data, flags_or_addr, addr) def sendall(self, data, flags=0): if self._sslobj: @@ -216,7 +218,7 @@ class SSLSocket(socket): self.__class__) return self.read(buflen) else: - return socket.recv(self, buflen, flags) + return self._sock.recv(buflen, flags) def recv_into(self, buffer, nbytes=None, flags=0): if buffer and (nbytes is None): @@ -233,21 +235,21 @@ class SSLSocket(socket): buffer[:v] = tmp_buffer return v else: - return socket.recv_into(self, buffer, nbytes, flags) + return self._sock.recv_into(buffer, nbytes, flags) - def recvfrom(self, addr, buflen=1024, flags=0): + def recvfrom(self, buflen=1024, flags=0): if self._sslobj: raise ValueError("recvfrom not allowed on instances of %s" % self.__class__) else: - return socket.recvfrom(self, addr, buflen, flags) + return self._sock.recvfrom(buflen, flags) def recvfrom_into(self, buffer, nbytes=None, flags=0): if self._sslobj: raise ValueError("recvfrom_into not allowed on instances of %s" % self.__class__) else: - return socket.recvfrom_into(self, buffer, nbytes, flags) + return self._sock.recvfrom_into(buffer, nbytes, flags) def pending(self): if self._sslobj: diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index d6f1fce7a77..37261554bc4 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -179,6 +179,19 @@ class BasicSocketTests(unittest.TestCase): del ss self.assertEqual(wr(), None) + def test_wrapped_unconnected(self): + # The _delegate_methods in socket.py are correctly delegated to by an + # unconnected SSLSocket, so they will raise a socket.error rather than + # something unexpected like TypeError. + s = socket.socket(socket.AF_INET) + ss = ssl.wrap_socket(s) + self.assertRaises(socket.error, ss.recv, 1) + self.assertRaises(socket.error, ss.recv_into, bytearray(b'x')) + self.assertRaises(socket.error, ss.recvfrom, 1) + self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1) + self.assertRaises(socket.error, ss.send, b'x') + self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0)) + class NetworkedTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index 657e9911489..2b97d633e8e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -43,6 +43,12 @@ Core and Builtins Library ------- +- Issue #9729: Fix the signature of SSLSocket.recvfrom() and + SSLSocket.sendto() to match the corresponding socket methods. Also, + fix various SSLSocket methods to raise socket.error rather than an + unhelpful TypeError when called on an unconnected socket. Original patch + by Andrew Bennetts. + - Issue #9826: OrderedDict.__repr__ can now handle self-referential values: d['x'] = d.