[Python-checkins] r82204 - in python/branches/py3k: Misc/NEWS Modules/_ssl.c

antoine.pitrou python-checkins at python.org
Fri Jun 25 00:34:06 CEST 2010


Author: antoine.pitrou
Date: Fri Jun 25 00:34:04 2010
New Revision: 82204

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



Modified:
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/_ssl.c

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Fri Jun 25 00:34:04 2010
@@ -451,6 +451,10 @@
 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.

Modified: python/branches/py3k/Modules/_ssl.c
==============================================================================
--- python/branches/py3k/Modules/_ssl.c	(original)
+++ python/branches/py3k/Modules/_ssl.c	Fri Jun 25 00:34:04 2010
@@ -212,8 +212,11 @@
                     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 @@
                      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 @@
         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 @@
         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 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+error:
+    Py_DECREF(sock);
+    return NULL;
 }
 
 static PyObject *
@@ -1051,9 +1059,12 @@
                      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 @@
         }
     } 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 @@
         return PySSL_SetError(self, len, __FILE__, __LINE__);
 
 error:
+    Py_DECREF(sock);
     PyBuffer_Release(&buf);
     return NULL;
 }
@@ -1159,21 +1172,23 @@
                      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 @@
         goto error;
     }
   done:
+    Py_DECREF(sock);
     if (!buf_passed) {
         PyObject *res = PyBytes_FromStringAndSize(mem, count);
         Py_DECREF(dest);
@@ -1249,8 +1265,9 @@
         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 @@
                      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 @@
             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,


More information about the Python-checkins mailing list