Skip to content

Commit a6094ee

Browse files
keepworkingserhiy-storchakaencukou
authored andcommitted
00462: Fix PySSL_SetError handling SSL_ERROR_SYSCALL
Python 3.10 changed from using SSL_write() and SSL_read() to SSL_write_ex() and SSL_read_ex(), but did not update handling of the return value. Change error handling so that the return value is not examined. OSError (not EOF) is now returned when retval is 0. This resolves the issue of failing tests when a system is stressed on OpenSSL 3.5. Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Petr Viktorin <encukou@gmail.com>
1 parent 5a6e9d6 commit a6094ee

File tree

3 files changed

+35
-43
lines changed

3 files changed

+35
-43
lines changed

Lib/test/test_ssl.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,16 +2427,18 @@ def run(self):
24272427
self.write(msg.lower())
24282428
except OSError as e:
24292429
# handles SSLError and socket errors
2430+
if isinstance(e, ConnectionError):
2431+
# OpenSSL 1.1.1 sometimes raises
2432+
# ConnectionResetError when connection is not
2433+
# shut down gracefully.
2434+
if self.server.chatty and support.verbose:
2435+
print(f" Connection reset by peer: {self.addr}")
2436+
2437+
self.close()
2438+
self.running = False
2439+
return
24302440
if self.server.chatty and support.verbose:
2431-
if isinstance(e, ConnectionError):
2432-
# OpenSSL 1.1.1 sometimes raises
2433-
# ConnectionResetError when connection is not
2434-
# shut down gracefully.
2435-
print(
2436-
f" Connection reset by peer: {self.addr}"
2437-
)
2438-
else:
2439-
handle_error("Test server failure:\n")
2441+
handle_error("Test server failure:\n")
24402442
try:
24412443
self.write(b"ERROR\n")
24422444
except OSError:
@@ -3148,8 +3150,8 @@ def test_wrong_cert_tls13(self):
31483150
suppress_ragged_eofs=False) as s:
31493151
s.connect((HOST, server.port))
31503152
with self.assertRaisesRegex(
3151-
ssl.SSLError,
3152-
'alert unknown ca|EOF occurred|TLSV1_ALERT_UNKNOWN_CA'
3153+
OSError,
3154+
'alert unknown ca|EOF occurred|TLSV1_ALERT_UNKNOWN_CA|closed by the remote host|Connection reset by peer'
31533155
):
31543156
# TLS 1.3 perform client cert exchange after handshake
31553157
s.write(b'data')
@@ -4422,8 +4424,8 @@ def msg_cb(conn, direction, version, content_type, msg_type, data):
44224424
# test sometimes fails with EOF error. Test passes as long as
44234425
# server aborts connection with an error.
44244426
with self.assertRaisesRegex(
4425-
ssl.SSLError,
4426-
'(certificate required|EOF occurred)'
4427+
OSError,
4428+
'certificate required|EOF occurred|closed by the remote host|Connection reset by peer'
44274429
):
44284430
# receive CertificateRequest
44294431
data = s.recv(1024)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix the :mod:`ssl` module error handling of connection terminate by peer.
2+
It now throws an OSError with the appropriate error code instead of an EOFError.

Modules/_ssl.c

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ PySSL_ChainExceptions(PySSLSocket *sslsock) {
573573
}
574574

575575
static PyObject *
576-
PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
576+
PySSL_SetError(PySSLSocket *sslsock, const char *filename, int lineno)
577577
{
578578
PyObject *type;
579579
char *errstr = NULL;
@@ -586,7 +586,6 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
586586
_sslmodulestate *state = get_state_sock(sslsock);
587587
type = state->PySSLErrorObject;
588588

589-
assert(ret <= 0);
590589
e = ERR_peek_last_error();
591590

592591
if (sslsock->ssl != NULL) {
@@ -619,32 +618,21 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
619618
case SSL_ERROR_SYSCALL:
620619
{
621620
if (e == 0) {
622-
PySocketSockObject *s = GET_SOCKET(sslsock);
623-
if (ret == 0 || (((PyObject *)s) == Py_None)) {
621+
/* underlying BIO reported an I/O error */
622+
ERR_clear_error();
623+
#ifdef MS_WINDOWS
624+
if (err.ws) {
625+
return PyErr_SetFromWindowsErr(err.ws);
626+
}
627+
#endif
628+
if (err.c) {
629+
errno = err.c;
630+
return PyErr_SetFromErrno(PyExc_OSError);
631+
}
632+
else {
624633
p = PY_SSL_ERROR_EOF;
625634
type = state->PySSLEOFErrorObject;
626635
errstr = "EOF occurred in violation of protocol";
627-
} else if (s && ret == -1) {
628-
/* underlying BIO reported an I/O error */
629-
ERR_clear_error();
630-
#ifdef MS_WINDOWS
631-
if (err.ws) {
632-
return PyErr_SetFromWindowsErr(err.ws);
633-
}
634-
#endif
635-
if (err.c) {
636-
errno = err.c;
637-
return PyErr_SetFromErrno(PyExc_OSError);
638-
}
639-
else {
640-
p = PY_SSL_ERROR_EOF;
641-
type = state->PySSLEOFErrorObject;
642-
errstr = "EOF occurred in violation of protocol";
643-
}
644-
} else { /* possible? */
645-
p = PY_SSL_ERROR_SYSCALL;
646-
type = state->PySSLSyscallErrorObject;
647-
errstr = "Some I/O error occurred";
648636
}
649637
} else {
650638
if (ERR_GET_LIB(e) == ERR_LIB_SSL &&
@@ -1007,7 +995,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
1007995
err.ssl == SSL_ERROR_WANT_WRITE);
1008996
Py_XDECREF(sock);
1009997
if (ret < 1)
1010-
return PySSL_SetError(self, ret, __FILE__, __LINE__);
998+
return PySSL_SetError(self, __FILE__, __LINE__);
1011999
if (PySSL_ChainExceptions(self) < 0)
10121000
return NULL;
10131001
Py_RETURN_NONE;
@@ -2424,7 +2412,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
24242412

24252413
Py_XDECREF(sock);
24262414
if (retval == 0)
2427-
return PySSL_SetError(self, retval, __FILE__, __LINE__);
2415+
return PySSL_SetError(self, __FILE__, __LINE__);
24282416
if (PySSL_ChainExceptions(self) < 0)
24292417
return NULL;
24302418
return PyLong_FromSize_t(count);
@@ -2454,7 +2442,7 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
24542442
self->err = err;
24552443

24562444
if (count < 0)
2457-
return PySSL_SetError(self, count, __FILE__, __LINE__);
2445+
return PySSL_SetError(self, __FILE__, __LINE__);
24582446
else
24592447
return PyLong_FromLong(count);
24602448
}
@@ -2577,7 +2565,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len,
25772565
err.ssl == SSL_ERROR_WANT_WRITE);
25782566

25792567
if (retval == 0) {
2580-
PySSL_SetError(self, retval, __FILE__, __LINE__);
2568+
PySSL_SetError(self, __FILE__, __LINE__);
25812569
goto error;
25822570
}
25832571
if (self->exc != NULL)
@@ -2703,7 +2691,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
27032691
}
27042692
if (ret < 0) {
27052693
Py_XDECREF(sock);
2706-
PySSL_SetError(self, ret, __FILE__, __LINE__);
2694+
PySSL_SetError(self, __FILE__, __LINE__);
27072695
return NULL;
27082696
}
27092697
if (self->exc != NULL)

0 commit comments

Comments
 (0)