Issue #23804: Fix SSL zero-length recv() calls to not block and raise EOF

This commit is contained in:
Martin Panter 2016-07-11 00:17:13 +00:00
parent c95300aceb
commit bed7f1a512
3 changed files with 32 additions and 8 deletions

View File

@ -2793,20 +2793,13 @@ else:
# consume data
s.read()
data = b"data"
# read(-1, buffer) is supported, even though read(-1) is not
data = b"data"
s.send(data)
buffer = bytearray(len(data))
self.assertEqual(s.read(-1, buffer), len(data))
self.assertEqual(buffer, data)
# recv/read(0) should return no data
s.send(data)
self.assertEqual(s.recv(0), b"")
self.assertEqual(s.read(0), b"")
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
@ -2822,6 +2815,26 @@ else:
s.close()
def test_recv_zero(self):
server = ThreadedEchoServer(CERTFILE)
server.__enter__()
self.addCleanup(server.__exit__, None, None)
s = socket.create_connection((HOST, server.port))
self.addCleanup(s.close)
s = ssl.wrap_socket(s, suppress_ragged_eofs=False)
self.addCleanup(s.close)
# recv/read(0) should return no data
s.send(b"data")
self.assertEqual(s.recv(0), b"")
self.assertEqual(s.read(0), b"")
self.assertEqual(s.read(), b"data")
# Should not block if the other end sends no data
s.setblocking(False)
self.assertEqual(s.recv(0), b"")
self.assertEqual(s.recv_into(bytearray()), 0)
def test_nonblocking_send(self):
server = ThreadedEchoServer(CERTFILE,
certreqs=ssl.CERT_NONE,

View File

@ -19,6 +19,9 @@ Core and Builtins
Library
-------
- Issue #23804: Fix SSL zero-length recv() calls to not block and not raise
an error about unclean EOF.
- Issue #27466: Change time format returned by http.cookie.time2netscape,
confirming the netscape cookie format and making it consistent with
documentation.

View File

@ -1913,6 +1913,10 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
dest = PyBytes_FromStringAndSize(NULL, len);
if (dest == NULL)
goto error;
if (len == 0) {
Py_XDECREF(sock);
return dest;
}
mem = PyBytes_AS_STRING(dest);
}
else {
@ -1924,6 +1928,10 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
"maximum length can't fit in a C 'int'");
goto error;
}
if (len == 0) {
count = 0;
goto done;
}
}
}