mirror of
https://github.com/python/cpython.git
synced 2025-08-31 22:18:28 +00:00
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.
This commit is contained in:
parent
3c9e6e9375
commit
8bae4ec622
2 changed files with 46 additions and 19 deletions
|
@ -451,6 +451,10 @@ C-API
|
||||||
Library
|
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
|
- Issue #1368368: FancyURLOpener class changed to throw an Exception on wrong
|
||||||
password instead of presenting an interactive prompt. Older behavior can be
|
password instead of presenting an interactive prompt. Older behavior can be
|
||||||
obtained by passing retry=True to http_error_xxx methods of FancyURLOpener.
|
obtained by passing retry=True to http_error_xxx methods of FancyURLOpener.
|
||||||
|
|
|
@ -212,8 +212,11 @@ PySSL_SetError(PySSLSocket *obj, int ret, char *filename, int lineno)
|
||||||
errstr = "EOF occurred in violation of protocol";
|
errstr = "EOF occurred in violation of protocol";
|
||||||
} else if (ret == -1) {
|
} else if (ret == -1) {
|
||||||
/* underlying BIO reported an I/O error */
|
/* underlying BIO reported an I/O error */
|
||||||
|
Py_INCREF(s);
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
return s->errorhandler();
|
v = s->errorhandler();
|
||||||
|
Py_DECREF(s);
|
||||||
|
return v;
|
||||||
} else { /* possible? */
|
} else { /* possible? */
|
||||||
p = PY_SSL_ERROR_SYSCALL;
|
p = PY_SSL_ERROR_SYSCALL;
|
||||||
errstr = "Some I/O error occurred";
|
errstr = "Some I/O error occurred";
|
||||||
|
@ -334,6 +337,7 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
|
||||||
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
|
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Py_INCREF(sock);
|
||||||
|
|
||||||
/* just in case the blocking state of the socket has been changed */
|
/* just in case the blocking state of the socket has been changed */
|
||||||
nonblocking = (sock->sock_timeout >= 0.0);
|
nonblocking = (sock->sock_timeout >= 0.0);
|
||||||
|
@ -348,9 +352,8 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
|
||||||
ret = SSL_do_handshake(self->ssl);
|
ret = SSL_do_handshake(self->ssl);
|
||||||
err = SSL_get_error(self->ssl, ret);
|
err = SSL_get_error(self->ssl, ret);
|
||||||
PySSL_END_ALLOW_THREADS
|
PySSL_END_ALLOW_THREADS
|
||||||
if(PyErr_CheckSignals()) {
|
if (PyErr_CheckSignals())
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
|
||||||
if (err == SSL_ERROR_WANT_READ) {
|
if (err == SSL_ERROR_WANT_READ) {
|
||||||
sockstate = check_socket_and_wait_for_timeout(sock, 0);
|
sockstate = check_socket_and_wait_for_timeout(sock, 0);
|
||||||
} else if (err == SSL_ERROR_WANT_WRITE) {
|
} else if (err == SSL_ERROR_WANT_WRITE) {
|
||||||
|
@ -361,19 +364,20 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
|
||||||
if (sockstate == SOCKET_HAS_TIMED_OUT) {
|
if (sockstate == SOCKET_HAS_TIMED_OUT) {
|
||||||
PyErr_SetString(PySSLErrorObject,
|
PyErr_SetString(PySSLErrorObject,
|
||||||
ERRSTR("The handshake operation timed out"));
|
ERRSTR("The handshake operation timed out"));
|
||||||
return NULL;
|
goto error;
|
||||||
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
|
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
|
||||||
PyErr_SetString(PySSLErrorObject,
|
PyErr_SetString(PySSLErrorObject,
|
||||||
ERRSTR("Underlying socket has been closed."));
|
ERRSTR("Underlying socket has been closed."));
|
||||||
return NULL;
|
goto error;
|
||||||
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
|
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
|
||||||
PyErr_SetString(PySSLErrorObject,
|
PyErr_SetString(PySSLErrorObject,
|
||||||
ERRSTR("Underlying socket too large for select()."));
|
ERRSTR("Underlying socket too large for select()."));
|
||||||
return NULL;
|
goto error;
|
||||||
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
|
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
|
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
|
||||||
|
Py_DECREF(sock);
|
||||||
if (ret < 1)
|
if (ret < 1)
|
||||||
return PySSL_SetError(self, ret, __FILE__, __LINE__);
|
return PySSL_SetError(self, ret, __FILE__, __LINE__);
|
||||||
self->ssl->debug = 1;
|
self->ssl->debug = 1;
|
||||||
|
@ -386,6 +390,10 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
|
|
||||||
|
error:
|
||||||
|
Py_DECREF(sock);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1051,9 +1059,12 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args)
|
||||||
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
|
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Py_INCREF(sock);
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "y*:write", &buf))
|
if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
|
||||||
|
Py_DECREF(sock);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* just in case the blocking state of the socket has been changed */
|
/* just in case the blocking state of the socket has been changed */
|
||||||
nonblocking = (sock->sock_timeout >= 0.0);
|
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);
|
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
|
||||||
|
|
||||||
|
Py_DECREF(sock);
|
||||||
PyBuffer_Release(&buf);
|
PyBuffer_Release(&buf);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
return PyLong_FromLong(len);
|
return PyLong_FromLong(len);
|
||||||
|
@ -1110,6 +1122,7 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args)
|
||||||
return PySSL_SetError(self, len, __FILE__, __LINE__);
|
return PySSL_SetError(self, len, __FILE__, __LINE__);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
Py_DECREF(sock);
|
||||||
PyBuffer_Release(&buf);
|
PyBuffer_Release(&buf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1159,21 +1172,23 @@ static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args)
|
||||||
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
|
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Py_INCREF(sock);
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|Oi:read", &dest, &count))
|
if (!PyArg_ParseTuple(args, "|Oi:read", &dest, &count))
|
||||||
return NULL;
|
goto error;
|
||||||
|
|
||||||
if ((dest == NULL) || (dest == Py_None)) {
|
if ((dest == NULL) || (dest == Py_None)) {
|
||||||
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
|
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
|
||||||
return NULL;
|
goto error;
|
||||||
mem = PyByteArray_AS_STRING(dest);
|
mem = PyByteArray_AS_STRING(dest);
|
||||||
} else if (PyLong_Check(dest)) {
|
} else if (PyLong_Check(dest)) {
|
||||||
len = PyLong_AS_LONG(dest);
|
len = PyLong_AS_LONG(dest);
|
||||||
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
|
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
|
||||||
return NULL;
|
goto error;
|
||||||
mem = PyByteArray_AS_STRING(dest);
|
mem = PyByteArray_AS_STRING(dest);
|
||||||
} else {
|
} else {
|
||||||
if (PyObject_GetBuffer(dest, &buf, PyBUF_CONTIG) < 0)
|
if (PyObject_GetBuffer(dest, &buf, PyBUF_CONTIG) < 0)
|
||||||
return NULL;
|
goto error;
|
||||||
mem = buf.buf;
|
mem = buf.buf;
|
||||||
len = buf.len;
|
len = buf.len;
|
||||||
if ((count > 0) && (count <= len))
|
if ((count > 0) && (count <= len))
|
||||||
|
@ -1240,6 +1255,7 @@ static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
Py_DECREF(sock);
|
||||||
if (!buf_passed) {
|
if (!buf_passed) {
|
||||||
PyObject *res = PyBytes_FromStringAndSize(mem, count);
|
PyObject *res = PyBytes_FromStringAndSize(mem, count);
|
||||||
Py_DECREF(dest);
|
Py_DECREF(dest);
|
||||||
|
@ -1249,8 +1265,9 @@ static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args)
|
||||||
return PyLong_FromLong(count);
|
return PyLong_FromLong(count);
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
|
Py_DECREF(sock);
|
||||||
if (!buf_passed) {
|
if (!buf_passed) {
|
||||||
Py_DECREF(dest);
|
Py_XDECREF(dest);
|
||||||
} else {
|
} else {
|
||||||
PyBuffer_Release(&buf);
|
PyBuffer_Release(&buf);
|
||||||
}
|
}
|
||||||
|
@ -1275,6 +1292,7 @@ static PyObject *PySSL_SSLshutdown(PySSLSocket *self)
|
||||||
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
|
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Py_INCREF(sock);
|
||||||
|
|
||||||
/* Just in case the blocking state of the socket has been changed */
|
/* Just in case the blocking state of the socket has been changed */
|
||||||
nonblocking = (sock->sock_timeout >= 0.0);
|
nonblocking = (sock->sock_timeout >= 0.0);
|
||||||
|
@ -1324,24 +1342,29 @@ static PyObject *PySSL_SSLshutdown(PySSLSocket *self)
|
||||||
else
|
else
|
||||||
PyErr_SetString(PySSLErrorObject,
|
PyErr_SetString(PySSLErrorObject,
|
||||||
"The write operation timed out");
|
"The write operation timed out");
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
|
else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
|
||||||
PyErr_SetString(PySSLErrorObject,
|
PyErr_SetString(PySSLErrorObject,
|
||||||
"Underlying socket too large for select().");
|
"Underlying socket too large for select().");
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
else if (sockstate != SOCKET_OPERATION_OK)
|
else if (sockstate != SOCKET_OPERATION_OK)
|
||||||
/* Retain the SSL error code */
|
/* Retain the SSL error code */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
Py_DECREF(sock);
|
||||||
return PySSL_SetError(self, err, __FILE__, __LINE__);
|
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,
|
PyDoc_STRVAR(PySSL_SSLshutdown_doc,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue