diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 73d3e3bbcdaeb8..a572cf718e6c13 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -2466,7 +2466,7 @@ def server_params_test(client_context, server_context, indata=b"FOO\n", sys.stdout.write( " client: sending %r...\n" % indata) s.write(arg) - outdata = s.read() + outdata = s.read() if len(arg) > 0 else b'' if connectionchatty: if support.verbose: sys.stdout.write(" client: read %r\n" % outdata) @@ -2578,6 +2578,14 @@ def test_echo(self): chatty=True, connectionchatty=True, sni_name=hostname) + ## Testing that SSLSocket can handle empty input + with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER): + server_params_test(client_context=client_context, + server_context=server_context, + indata = b'', + chatty=True, connectionchatty=True, + sni_name=hostname) + client_context.check_hostname = False with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT): with self.assertRaises(ssl.SSLError) as e: diff --git a/Misc/NEWS.d/next/Library/2018-06-09-17-15-35.bpo-31711.sOj9dl.rst b/Misc/NEWS.d/next/Library/2018-06-09-17-15-35.bpo-31711.sOj9dl.rst new file mode 100644 index 00000000000000..5d761ea9668076 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-06-09-17-15-35.bpo-31711.sOj9dl.rst @@ -0,0 +1,2 @@ +Avoiding triggering undefined behaviour from SSL_write when calling +SSLSocket.send() with empty input. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 2bce4816d26fe7..95743a8bc32e7f 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -2247,6 +2247,13 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) "string longer than %d bytes", INT_MAX); goto error; } + if (b->len == 0) { + /* Sending 0 bytes to SSL_write is undefined behaviour per OpenSSL documentation. + * SSLSocket imitates normal socket in Python. + * We have to guard against empty input here. */ + Py_XDECREF(sock); + return PyLong_FromLong(0); + } if (sock != NULL) { /* just in case the blocking state of the socket has been changed */