]> granicus.if.org Git - python/commitdiff
Merged revisions 82204 via svnmerge from
authorAntoine Pitrou <solipsis@pitrou.net>
Thu, 24 Jun 2010 22:49:57 +0000 (22:49 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Thu, 24 Jun 2010 22:49:57 +0000 (22:49 +0000)
svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r82204 | antoine.pitrou | 2010-06-25 00:34:04 +0200 (ven., 25 juin 2010) | 5 lines

  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.
........

Misc/NEWS
Modules/_ssl.c

index e63f26694e488a152477cb19e42c47e1b03931c7..0a1dffd409e9adf8d714a6583004e504745b8225 100644 (file)
--- 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.
index 5bc2e50311ed11901cb81dd915459c2a89401fc9..52fd3f96bbe7fb8e4df7bb9aaf7241758e0526fd 100644 (file)
@@ -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,