8000 00462: Fix PySSL_SetError handling SSL_ERROR_SYSCALL · fedora-python/cpython@d777360 · GitHub
[go: up one dir, main page]

Skip to content

Commit d777360

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 dbde14a commit d777360

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
@@ -2633,16 +2633,18 @@ def run(self):
26332633
self.write(msg.lower())
26342634
except OSError as e:
26352635
# handles SSLError and socket errors
2636+
if isinstance(e, ConnectionError):
2637+
# OpenSSL 1.1.1 sometimes raises
2638+
# ConnectionResetError when connection is not
2639+
# shut down gracefully.
2640+
if self.server.chatty and support.verbose:
2641+
print(f" Connection reset by peer: {self.addr}")
2642+
2643+
self.close()
2644+
self.running = False
2645+
return
26362646
if self.server.chatty and support.verbose:
2637-
if isinstance(e, ConnectionError):
2638-
# OpenSSL 1.1.1 sometimes raises
2639-
# ConnectionResetError when connection is not
2640-
# shut down gracefully.
2641-
print(
2642-
f" Connection reset by peer: {self.addr}"
2643-
)
2644-
else:
2645-
handle_error("Test server failure:\n")
2647+
handle_error("Test server failure:\n")
26462648
try:
26472649
self.write(b"ERROR\n")
26482650
except OSError:
@@ -3337,8 +3339,8 @@ def test_wrong_cert_tls13(self):
33373339
suppress_ragged_eofs=False) as s:
33383340
s.connect((HOST, server.port))
33393341
with self.assertRaisesRegex(
3340-
ssl.SSLError,
3341-
'alert unknown ca|EOF occurred'
3342+
OSError,
3343+
'alert unknown ca|EOF occurred|TLSV1_ALERT_UNKNOWN_CA|closed by the remote host|Connection reset by peer'
33423344
):
33433345
# TLS 1.3 perform client cert exchange after handshake
33443346
s.write(b'data')
@@ -4610,8 +4612,8 @@ def msg_cb(conn, direction, version, content_type, msg_type, data):
46104612
# test sometimes fails with EOF error. Test passes as long as
46114613
# server aborts connection with an error.
46124614
with self.assertRaisesRegex(
4613-
ssl.SSLError,
4614-
'(certificate required|EOF occurred)'
4615+
OSError,
4616+
'certificate required|EOF occurred|closed by the remote host|Connection reset by peer'
46154617
):
46164618
# receive CertificateRequest
46174619
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
@@ -576,7 +576,7 @@ PySSL_ChainExceptions(PySSLSocket *sslsock) {
576576
}
577577

578578
static PyObject *
579-
PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
579+
PySSL_SetError(PySSLSocket *sslsock, const char *filename, int lineno)
580580
{
581581
PyObject *type;
582582
char *errstr = NULL;
@@ -589,7 +589,6 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
589589
_sslmodulestate *state = get_state_sock(sslsock);
590590
type = state->PySSLErrorObject;
591591

592-
assert(ret <= 0);
593592
e = ERR_peek_last_error();
594593

595594
if (sslsock->ssl != NULL) {
@@ -622,32 +621,21 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
622621
case SSL_ERROR_SYSCALL:
623622
{
624623
if (e == 0) {
625-
PySocketSockObject *s = GET_SOCKET(sslsock);
626-
if (ret == 0 || (((PyObject *)s) == Py_None)) {
624+
/* underlying BIO reported an I/O error */
625+
ERR_clear_error();
626+
#ifdef MS_WINDOWS
627+
if (err.ws) {
628+
return PyErr_SetFromWindowsErr(err.ws);
629+
}
630+
#endif
631+
if (err.c) {
632+
errno = err.c;
633+
return PyErr_SetFromErrno(PyExc_OSError);
634+
}
635+
else {
627636
p = PY_SSL_ERROR_EOF;
628637
type = state->PySSLEOFErrorObject;
629638
errstr = "EOF occurred in violation of protocol";
630-
} else if (s && ret == -1) {
631-
/* underlying BIO reported an I/O error */
632-
ERR_clear_error();
633-
#ifdef MS_WINDOWS
634-
if (err.ws) {
635-
return PyErr_SetFromWindowsErr(err.ws);
636-
}
637-
#endif
638-
if (err.c) {
639-
errno = err.c;
640-
return PyErr_SetFromErrno(PyExc_OSError);
641-
}
642-
else {
643-
p = PY_SSL_ERROR_EOF;
644-
type = state->PySSLEOFErrorObject;
645-
errstr = "EOF occurred in violation of protocol";
646-
}
647-
} else { /* possible? */
648-
p = PY_SSL_ERROR_SYSCALL;
649-
type = state->PySSLSyscallErrorObject;
650-
errstr = "Some I/O error occurred";
651639
}
652640
} else {
653641
if (ERR_GET_LIB(e) == ERR_LIB_SSL &&
@@ -1013,7 +1001,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
10131001
err.ssl == SSL_ERROR_WANT_WRITE);
10141002
Py_XDECREF(sock);
10151003
if (ret < 1)
1016-
return PySSL_SetError(self, ret, __FILE__, __LINE__);
1004+
return PySSL_SetError(self, __FILE__, __LINE__);
10171005
if (PySSL_ChainExceptions(self) < 0)
10181006
return NULL;
10191007
Py_RETURN_NONE;
@@ -2434,7 +2422,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
24342422

24352423
Py_XDECREF(sock);
24362424
if (retval == 0)
2437-
return PySSL_SetError(self, retval, __FILE__, __LINE__);
2425+
return PySSL_SetError(self, __FILE__, __LINE__);
24382426
if (PySSL_ChainExceptions(self) < 0)
24392427
return NULL;
24402428
return PyLong_FromSize_t(count);
@@ -2464,7 +2452,7 @@ _ssl__SSLSoc D0B5 ket_pending_impl(PySSLSocket *self)
24642452
self->err = err;
24652453

24662454
if (count < 0)
2467-
return PySSL_SetError(self, count, __FILE__, __LINE__);
2455+
return PySSL_SetError(self, __FILE__, __LINE__);
24682456
else
24692457
return PyLong_FromLong(count);
24702458
}
@@ -2587,7 +2575,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len,
25872575
err.ssl == SSL_ERROR_WANT_WRITE);
25882576

25892577
if (retval == 0) {
2590-
PySSL_SetError(self, retval, __FILE__, __LINE__);
2578+
PySSL_SetError(self, __FILE__, __LINE__);
25912579
goto error;
25922580
}
25932581
if (self->exc_type != NULL)
@@ -2713,7 +2701,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
27132701
}
27142702
if (ret < 0) {
27152703
Py_XDECREF(sock);
2716-
PySSL_SetError(self, ret, __FILE__, __LINE__);
2704+
PySSL_SetError(self, __FILE__, __LINE__);
27172705
return NULL;
27182706
}
27192707
if (self->exc_type != NULL)

0 commit comments

Comments
 (0)
0