summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Misc/NEWS4
-rw-r--r--Modules/_ssl.c80
2 files changed, 57 insertions, 27 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index e63f266..0a1dffd 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -72,6 +72,10 @@ C-API
Library
-------
+- Issue #8682: The ssl module now temporary increments the reference count of
+ a socket object got through ``PyWeakref_GetObject``, so as to avoid possible
+ deallocation while the object is still being used.
+
- Issue #1368368: FancyURLOpener class changed to throw an Exception on wrong
password instead of presenting an interactive prompt. Older behavior can be
obtained by passing retry=True to http_error_xxx methods of FancyURLOpener.
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 5bc2e50..52fd3f9 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -199,8 +199,11 @@ PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno)
errstr = "EOF occurred in violation of protocol";
} else if (ret == -1) {
/* underlying BIO reported an I/O error */
+ Py_INCREF(s);
ERR_clear_error();
- return s->errorhandler();
+ v = s->errorhandler();
+ Py_DECREF(s);
+ return v;
} else { /* possible? */
p = PY_SSL_ERROR_SYSCALL;
errstr = "Some I/O error occurred";
@@ -454,6 +457,7 @@ static PyObject *PySSL_SSLdo_handshake(PySSLObject *self)
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
return NULL;
}
+ Py_INCREF(sock);
/* just in case the blocking state of the socket has been changed */
nonblocking = (sock->sock_timeout >= 0.0);
@@ -468,9 +472,8 @@ static PyObject *PySSL_SSLdo_handshake(PySSLObject *self)
ret = SSL_do_handshake(self->ssl);
err = SSL_get_error(self->ssl, ret);
PySSL_END_ALLOW_THREADS
- if(PyErr_CheckSignals()) {
- return NULL;
- }
+ if (PyErr_CheckSignals())
+ goto error;
if (err == SSL_ERROR_WANT_READ) {
sockstate = check_socket_and_wait_for_timeout(sock, 0);
} else if (err == SSL_ERROR_WANT_WRITE) {
@@ -481,19 +484,20 @@ static PyObject *PySSL_SSLdo_handshake(PySSLObject *self)
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
ERRSTR("The handshake operation timed out"));
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
PyErr_SetString(PySSLErrorObject,
ERRSTR("Underlying socket has been closed."));
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
PyErr_SetString(PySSLErrorObject,
ERRSTR("Underlying socket too large for select()."));
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
break;
}
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
+ Py_DECREF(sock);
if (ret < 1)
return PySSL_SetError(self, ret, __FILE__, __LINE__);
self->ssl->debug = 1;
@@ -506,6 +510,10 @@ static PyObject *PySSL_SSLdo_handshake(PySSLObject *self)
Py_INCREF(Py_None);
return Py_None;
+
+error:
+ Py_DECREF(sock);
+ return NULL;
}
static PyObject *
@@ -1175,9 +1183,12 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
return NULL;
}
+ Py_INCREF(sock);
- if (!PyArg_ParseTuple(args, "y#:write", &data, &count))
+ if (!PyArg_ParseTuple(args, "y#:write", &data, &count)) {
+ Py_DECREF(sock);
return NULL;
+ }
/* just in case the blocking state of the socket has been changed */
nonblocking = (sock->sock_timeout >= 0.0);
@@ -1188,15 +1199,15 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
"The write operation timed out");
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
PyErr_SetString(PySSLErrorObject,
"Underlying socket has been closed.");
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
PyErr_SetString(PySSLErrorObject,
"Underlying socket too large for select().");
- return NULL;
+ goto error;
}
do {
err = 0;
@@ -1204,9 +1215,8 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
len = SSL_write(self->ssl, data, count);
err = SSL_get_error(self->ssl, len);
PySSL_END_ALLOW_THREADS
- if(PyErr_CheckSignals()) {
- return NULL;
- }
+ if (PyErr_CheckSignals())
+ goto error;
if (err == SSL_ERROR_WANT_READ) {
sockstate = check_socket_and_wait_for_timeout(sock, 0);
} else if (err == SSL_ERROR_WANT_WRITE) {
@@ -1217,19 +1227,25 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
"The write operation timed out");
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
PyErr_SetString(PySSLErrorObject,
"Underlying socket has been closed.");
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
break;
}
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
+
+ Py_DECREF(sock);
if (len > 0)
return PyLong_FromLong(len);
else
return PySSL_SetError(self, len, __FILE__, __LINE__);
+
+error:
+ Py_DECREF(sock);
+ return NULL;
}
PyDoc_STRVAR(PySSL_SSLwrite_doc,
@@ -1277,21 +1293,23 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
return NULL;
}
+ Py_INCREF(sock);
if (!PyArg_ParseTuple(args, "|Oi:read", &dest, &count))
- return NULL;
+ goto error;
+
if ((dest == NULL) || (dest == Py_None)) {
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
- return NULL;
+ goto error;
mem = PyByteArray_AS_STRING(dest);
} else if (PyLong_Check(dest)) {
len = PyLong_AS_LONG(dest);
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
- return NULL;
+ goto error;
mem = PyByteArray_AS_STRING(dest);
} else {
if (PyObject_GetBuffer(dest, &buf, PyBUF_CONTIG) < 0)
- return NULL;
+ goto error;
mem = buf.buf;
len = buf.len;
if ((count > 0) && (count <= len))
@@ -1358,6 +1376,7 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
goto error;
}
done:
+ Py_DECREF(sock);
if (!buf_passed) {
PyObject *res = PyBytes_FromStringAndSize(mem, count);
Py_DECREF(dest);
@@ -1367,8 +1386,9 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
return PyLong_FromLong(count);
}
error:
+ Py_DECREF(sock);
if (!buf_passed) {
- Py_DECREF(dest);
+ Py_XDECREF(dest);
} else {
PyBuffer_Release(&buf);
}
@@ -1393,6 +1413,7 @@ static PyObject *PySSL_SSLshutdown(PySSLObject *self)
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
return NULL;
}
+ Py_INCREF(sock);
/* Just in case the blocking state of the socket has been changed */
nonblocking = (sock->sock_timeout >= 0.0);
@@ -1442,24 +1463,29 @@ static PyObject *PySSL_SSLshutdown(PySSLObject *self)
else
PyErr_SetString(PySSLErrorObject,
"The write operation timed out");
- return NULL;
+ goto error;
}
else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
PyErr_SetString(PySSLErrorObject,
"Underlying socket too large for select().");
- return NULL;
+ goto error;
}
else if (sockstate != SOCKET_OPERATION_OK)
/* Retain the SSL error code */
break;
}
- if (err < 0)
+ if (err < 0) {
+ Py_DECREF(sock);
return PySSL_SetError(self, err, __FILE__, __LINE__);
- else {
- Py_INCREF(sock);
- return (PyObject *) sock;
}
+ else
+ /* It's already INCREF'ed */
+ return (PyObject *) sock;
+
+error:
+ Py_DECREF(sock);
+ return NULL;
}
PyDoc_STRVAR(PySSL_SSLshutdown_doc,