enum py_ssl_server_or_client socket_type;
PyObject *owner; /* Python level "owner" passed to servername callback */
PyObject *server_hostname;
- /* Some SSL callbacks don't have error reporting. Callback wrappers
- * store exception information on the socket. The handshake, read, write,
- * and shutdown methods check for chained exceptions.
- */
- PyObject *exc;
} PySSLSocket;
#define PySSLSocket_CAST(op) ((PySSLSocket *)(op))
PyUnicodeWriter_Discard(writer);
}
-static int
-PySSL_ChainExceptions(PySSLSocket *sslsock) {
- if (sslsock->exc == NULL)
- return 0;
-
- _PyErr_ChainExceptions1(sslsock->exc);
- sslsock->exc = NULL;
- return -1;
-}
-
+// Set the appropriate SSL error exception.
+// err - error information from SSL and libc
+// exc - if not NULL, an exception from _debughelpers.c callback to be chained
static PyObject *
-PySSL_SetError(PySSLSocket *sslsock, _PySSLError err, const char *filename, int lineno)
+PySSL_SetError(PySSLSocket *sslsock, _PySSLError err, PyObject *exc,
+ const char *filename, int lineno)
{
PyObject *type;
char *errstr = NULL;
}
fill_and_set_sslerror(state, sslsock, type, p, errstr, lineno, e);
ERR_clear_error();
- PySSL_ChainExceptions(sslsock);
+ _PyErr_ChainExceptions1(exc); // chain any exceptions from callbacks
return NULL;
}
self->shutdown_seen_zero = 0;
self->owner = NULL;
self->server_hostname = NULL;
- self->exc = NULL;
/* Make sure the SSL error state is initialized */
ERR_clear_error();
{
int ret;
_PySSLError err;
+ PyObject *exc = NULL;
int sockstate, nonblocking;
PySocketSockObject *sock = GET_SOCKET(self);
PyTime_t timeout, deadline = 0;
Py_END_ALLOW_THREADS;
_PySSL_FIX_ERRNO;
+ // Get any exception that occurred in a debughelpers.c callback
+ exc = PyErr_GetRaisedException();
+ if (exc != NULL) {
+ break;
+ }
+
if (PyErr_CheckSignals())
goto error;
Py_XDECREF(sock);
if (ret < 1)
- return PySSL_SetError(self, err, __FILE__, __LINE__);
- if (PySSL_ChainExceptions(self) < 0)
+ return PySSL_SetError(self, err, exc, __FILE__, __LINE__);
+ if (exc != NULL) {
+ PyErr_SetRaisedException(exc);
return NULL;
+ }
Py_RETURN_NONE;
error:
+ assert(exc == NULL);
Py_XDECREF(sock);
- PySSL_ChainExceptions(self);
return NULL;
}
static int
PySSL_traverse(PyObject *op, visitproc visit, void *arg)
{
- PySSLSocket *self = PySSLSocket_CAST(op);
- Py_VISIT(self->exc);
- Py_VISIT(Py_TYPE(self));
- return 0;
-}
-
-static int
-PySSL_clear(PyObject *op)
-{
- PySSLSocket *self = PySSLSocket_CAST(op);
- Py_CLEAR(self->exc);
+ Py_VISIT(Py_TYPE(op));
return 0;
}
Py_ssize_t retval;
int sockstate;
_PySSLError err;
+ PyObject *exc = NULL;
PySocketSockObject *sock = GET_SOCKET(self);
PyTime_t timeout, deadline = 0;
int has_timeout;
Py_END_ALLOW_THREADS;
_PySSL_FIX_ERRNO;
+ exc = PyErr_GetRaisedException();
+ if (exc != NULL) {
+ break;
+ }
+
if (PyErr_CheckSignals()) {
goto error;
}
}
Py_XDECREF(sock);
if (retval < 0) {
- return PySSL_SetError(self, err, __FILE__, __LINE__);
+ return PySSL_SetError(self, err, exc, __FILE__, __LINE__);
}
- if (PySSL_ChainExceptions(self) < 0) {
+ if (exc != NULL) {
+ PyErr_SetRaisedException(exc);
return NULL;
}
return PyLong_FromSize_t(retval);
error:
Py_XDECREF(sock);
- (void)PySSL_ChainExceptions(self);
+ if (exc != NULL) {
+ _PyErr_ChainExceptions1(exc);
+ }
return NULL;
}
#endif /* BIO_get_ktls_send */
int retval;
int sockstate;
_PySSLError err;
+ PyObject *exc = NULL;
int nonblocking;
PySocketSockObject *sock = GET_SOCKET(self);
PyTime_t timeout, deadline = 0;
Py_END_ALLOW_THREADS;
_PySSL_FIX_ERRNO;
+ exc = PyErr_GetRaisedException();
+ if (exc != NULL) {
+ break;
+ }
+
if (PyErr_CheckSignals())
goto error;
Py_XDECREF(sock);
if (retval == 0)
- return PySSL_SetError(self, err, __FILE__, __LINE__);
- if (PySSL_ChainExceptions(self) < 0)
+ return PySSL_SetError(self, err, exc, __FILE__, __LINE__);
+ if (exc != NULL) {
+ PyErr_SetRaisedException(exc);
return NULL;
+ }
return PyLong_FromSize_t(count);
error:
+ assert(exc == NULL);
Py_XDECREF(sock);
- PySSL_ChainExceptions(self);
return NULL;
}
_PySSL_FIX_ERRNO;
if (count < 0)
- return PySSL_SetError(self, err, __FILE__, __LINE__);
+ return PySSL_SetError(self, err, NULL, __FILE__, __LINE__);
else
return PyLong_FromLong(count);
}
int retval;
int sockstate;
_PySSLError err;
+ PyObject *exc = NULL;
int nonblocking;
PySocketSockObject *sock = GET_SOCKET(self);
PyTime_t timeout, deadline = 0;
Py_END_ALLOW_THREADS;
_PySSL_FIX_ERRNO;
+ exc = PyErr_GetRaisedException();
+ if (exc != NULL) {
+ break;
+ }
+
if (PyErr_CheckSignals())
goto error;
err.ssl == SSL_ERROR_WANT_WRITE);
if (retval == 0) {
- PySSL_SetError(self, err, __FILE__, __LINE__);
+ PySSL_SetError(self, err, exc, __FILE__, __LINE__);
+ exc = NULL;
goto error;
}
- if (self->exc != NULL)
+ else if (exc != NULL) {
+ PyErr_SetRaisedException(exc);
+ exc = NULL;
goto error;
+ }
done:
+ assert(exc == NULL);
Py_XDECREF(sock);
if (!group_right_1) {
return PyBytesWriter_FinishWithSize(writer, count);
}
error:
- PySSL_ChainExceptions(self);
+ assert(exc == NULL);
Py_XDECREF(sock);
if (!group_right_1) {
PyBytesWriter_Discard(writer);
/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=98d9635cd4e16514]*/
{
_PySSLError err;
+ PyObject *exc = NULL;
int sockstate, nonblocking, ret;
int zeros = 0;
PySocketSockObject *sock = GET_SOCKET(self);
Py_END_ALLOW_THREADS;
_PySSL_FIX_ERRNO;
+ exc = PyErr_GetRaisedException();
+ if (exc != NULL) {
+ break;
+ }
+
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
if (ret > 0)
break;
}
if (ret < 0) {
Py_XDECREF(sock);
- PySSL_SetError(self, err, __FILE__, __LINE__);
+ PySSL_SetError(self, err, exc, __FILE__, __LINE__);
+ return NULL;
+ }
+ else if (exc != NULL) {
+ Py_XDECREF(sock);
+ PyErr_SetRaisedException(exc);
return NULL;
}
- if (self->exc != NULL)
- goto error;
if (sock)
/* It's already INCREF'ed */
return (PyObject *) sock;
Py_RETURN_NONE;
error:
+ assert(exc == NULL);
Py_XDECREF(sock);
- PySSL_ChainExceptions(self);
return NULL;
}
{Py_tp_getset, ssl_getsetlist},
{Py_tp_dealloc, PySSL_dealloc},
{Py_tp_traverse, PySSL_traverse},
- {Py_tp_clear, PySSL_clear},
{0, 0},
};