diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-06-24 22:34:04 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-06-24 22:34:04 (GMT) |
commit | 8bae4ec62211bb71e4bad87b1a912301f616fb37 (patch) | |
tree | bd95da31043abf63608ad8ad91451df2eb2de717 /Modules/_ssl.c | |
parent | 3c9e6e9375954e9911ceddb65a98c3e58986e9a7 (diff) | |
download | cpython-8bae4ec62211bb71e4bad87b1a912301f616fb37.zip cpython-8bae4ec62211bb71e4bad87b1a912301f616fb37.tar.gz cpython-8bae4ec62211bb71e4bad87b1a912301f616fb37.tar.bz2 |
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.
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r-- | Modules/_ssl.c | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index a9c772a..31bf626 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -212,8 +212,11 @@ PySSL_SetError(PySSLSocket *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"; @@ -334,6 +337,7 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *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); @@ -348,9 +352,8 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *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) { @@ -361,19 +364,20 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *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; @@ -386,6 +390,10 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self) Py_INCREF(Py_None); return Py_None; + +error: + Py_DECREF(sock); + return NULL; } static PyObject * @@ -1051,9 +1059,12 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args) PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } + Py_INCREF(sock); - if (!PyArg_ParseTuple(args, "y*:write", &buf)) + if (!PyArg_ParseTuple(args, "y*:write", &buf)) { + Py_DECREF(sock); return NULL; + } /* just in case the blocking state of the socket has been changed */ nonblocking = (sock->sock_timeout >= 0.0); @@ -1103,6 +1114,7 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args) } } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); + Py_DECREF(sock); PyBuffer_Release(&buf); if (len > 0) return PyLong_FromLong(len); @@ -1110,6 +1122,7 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args) return PySSL_SetError(self, len, __FILE__, __LINE__); error: + Py_DECREF(sock); PyBuffer_Release(&buf); return NULL; } @@ -1159,21 +1172,23 @@ static PyObject *PySSL_SSLread(PySSLSocket *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)) @@ -1240,6 +1255,7 @@ static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args) goto error; } done: + Py_DECREF(sock); if (!buf_passed) { PyObject *res = PyBytes_FromStringAndSize(mem, count); Py_DECREF(dest); @@ -1249,8 +1265,9 @@ static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args) return PyLong_FromLong(count); } error: + Py_DECREF(sock); if (!buf_passed) { - Py_DECREF(dest); + Py_XDECREF(dest); } else { PyBuffer_Release(&buf); } @@ -1275,6 +1292,7 @@ static PyObject *PySSL_SSLshutdown(PySSLSocket *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); @@ -1324,24 +1342,29 @@ static PyObject *PySSL_SSLshutdown(PySSLSocket *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, |