Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions Lib/test/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -5197,6 +5197,36 @@ def test_got_eof(self):

self.assertEqual(sslsock.pending(), 0)

def test_oserror_does_not_leak_to_other_sockets(self):
# gh-158313: An OSError for one connection must not stay on the
# thread's OpenSSL error queue and be raised for another connection.
client_context, server_context, hostname = testing_context()
server_context.num_tickets = 0

def connect():
csock, ssock = socket.socketpair()
client = client_context.wrap_socket(
csock, server_hostname=hostname, do_handshake_on_connect=False)
server = server_context.wrap_socket(
ssock, server_side=True, do_handshake_on_connect=False)
thread = threading.Thread(target=server.do_handshake)
thread.start()
client.do_handshake()
thread.join()
return client, server

client, server = connect()
client2, server2 = connect()
with client, server, client2, server2:
server.close()
client.settimeout(support.SHORT_TIMEOUT)
with self.assertRaises(OSError):
while True:
client.send(b'x' * 1024)

client2.setblocking(False)
self.assertRaises(ssl.SSLWantReadError, client2.recv, 1)


@unittest.skipUnless(has_tls_version('TLSv1_3') and ssl.HAS_PHA,
"Test needs TLS 1.3 PHA")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix :mod:`ssl` leaving a system error on the OpenSSL error queue of the
thread after raising :exc:`OSError`, which made later I/O on other SSL
sockets in the same thread fail with the same error.
2 changes: 2 additions & 0 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ PySSL_SetError(PySSLSocket *sslsock, _PySSLError err, PyObject *exc,
type = state->PySSLCertVerificationErrorObject;
}
if (ERR_GET_LIB(e) == ERR_LIB_SYS) {
ERR_clear_error();
// A system error is being reported; reason is set to errno
errno = ERR_GET_REASON(e);
return PyErr_SetFromErrno(PyExc_OSError);
Expand Down Expand Up @@ -749,6 +750,7 @@ PySSL_SetError(PySSLSocket *sslsock, _PySSLError err, PyObject *exc,
}
#endif
if (ERR_GET_LIB(e) == ERR_LIB_SYS) {
ERR_clear_error();
// A system error is being reported; reason is set to errno
errno = ERR_GET_REASON(e);
return PyErr_SetFromErrno(PyExc_OSError);
Expand Down
Loading