Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8bae4ec

Browse files
committed
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.
1 parent 3c9e6e9 commit 8bae4ec

2 files changed

Lines changed: 46 additions & 19 deletions

File tree

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,10 @@ C-API
451451
Library
452452
-------
453453

454+
- Issue #8682: The ssl module now temporary increments the reference count of
455+
a socket object got through ``PyWeakref_GetObject``, so as to avoid possible
456+
deallocation while the object is still being used.
457+
454458
- Issue #1368368: FancyURLOpener class changed to throw an Exception on wrong
455459
password instead of presenting an interactive prompt. Older behavior can be
456460
obtained by passing retry=True to http_error_xxx methods of FancyURLOpener.

Modules/_ssl.c

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,11 @@ PySSL_SetError(PySSLSocket *obj, int ret, char *filename, int lineno)
212212
errstr = "EOF occurred in violation of protocol";
213213
} else if (ret == -1) {
214214
/* underlying BIO reported an I/O error */
215+
Py_INCREF(s);
215216
ERR_clear_error();
216-
return s->errorhandler();
217+
v = s->errorhandler();
218+
Py_DECREF(s);
219+
return v;
217220
} else { /* possible? */
218221
p = PY_SSL_ERROR_SYSCALL;
219222
errstr = "Some I/O error occurred";
@@ -334,6 +337,7 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
334337
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
335338
return NULL;
336339
}
340+
Py_INCREF(sock);
337341

338342
/* just in case the blocking state of the socket has been changed */
339343
nonblocking = (sock->sock_timeout >= 0.0);
@@ -348,9 +352,8 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
348352
ret = SSL_do_handshake(self->ssl);
349353
err = SSL_get_error(self->ssl, ret);
350354
PySSL_END_ALLOW_THREADS
351-
if(PyErr_CheckSignals()) {
352-
return NULL;
353-
}
355+
if (PyErr_CheckSignals())
356+
goto error;
354357
if (err == SSL_ERROR_WANT_READ) {
355358
sockstate = check_socket_and_wait_for_timeout(sock, 0);
356359
} else if (err == SSL_ERROR_WANT_WRITE) {
@@ -361,19 +364,20 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
361364
if (sockstate == SOCKET_HAS_TIMED_OUT) {
362365
PyErr_SetString(PySSLErrorObject,
363366
ERRSTR("The handshake operation timed out"));
364-
return NULL;
367+
goto error;
365368
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
366369
PyErr_SetString(PySSLErrorObject,
367370
ERRSTR("Underlying socket has been closed."));
368-
return NULL;
371+
goto error;
369372
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
370373
PyErr_SetString(PySSLErrorObject,
371374
ERRSTR("Underlying socket too large for select()."));
372-
return NULL;
375+
goto error;
373376
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
374377
break;
375378
}
376379
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
380+
Py_DECREF(sock);
377381
if (ret < 1)
378382
return PySSL_SetError(self, ret, __FILE__, __LINE__);
379383
self->ssl->debug = 1;
@@ -386,6 +390,10 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
386390

387391
Py_INCREF(Py_None);
388392
return Py_None;
393+
394+
error:
395+
Py_DECREF(sock);
396+
return NULL;
389397
}
390398

391399
static PyObject *
@@ -1051,9 +1059,12 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args)
10511059
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
10521060
return NULL;
10531061
}
1062+
Py_INCREF(sock);
10541063

1055-
if (!PyArg_ParseTuple(args, "y*:write", &buf))
1064+
if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1065+
Py_DECREF(sock);
10561066
return NULL;
1067+
}
10571068

10581069
/* just in case the blocking state of the socket has been changed */
10591070
nonblocking = (sock->sock_timeout >= 0.0);
@@ -1103,13 +1114,15 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args)
11031114
}
11041115
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
11051116

1117+
Py_DECREF(sock);
11061118
PyBuffer_Release(&buf);
11071119
if (len > 0)
11081120
return PyLong_FromLong(len);
11091121
else
11101122
return PySSL_SetError(self, len, __FILE__, __LINE__);
11111123

11121124
error:
1125+
Py_DECREF(sock);
11131126
PyBuffer_Release(&buf);
11141127
return NULL;
11151128
}
@@ -1159,21 +1172,23 @@ static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args)
11591172
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
11601173
return NULL;
11611174
}
1175+
Py_INCREF(sock);
11621176

11631177
if (!PyArg_ParseTuple(args, "|Oi:read", &dest, &count))
1164-
return NULL;
1178+
goto error;
1179+
11651180
if ((dest == NULL) || (dest == Py_None)) {
11661181
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
1167-
return NULL;
1182+
goto error;
11681183
mem = PyByteArray_AS_STRING(dest);
11691184
} else if (PyLong_Check(dest)) {
11701185
len = PyLong_AS_LONG(dest);
11711186
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
1172-
return NULL;
1187+
goto error;
11731188
mem = PyByteArray_AS_STRING(dest);
11741189
} else {
11751190
if (PyObject_GetBuffer(dest, &buf, PyBUF_CONTIG) < 0)
1176-
return NULL;
1191+
goto error;
11771192
mem = buf.buf;
11781193
len = buf.len;
11791194
if ((count > 0) && (count <= len))
@@ -1240,6 +1255,7 @@ static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args)
12401255
goto error;
12411256
}
12421257
done:
1258+
Py_DECREF(sock);
12431259
if (!buf_passed) {
12441260
PyObject *res = PyBytes_FromStringAndSize(mem, count);
12451261
Py_DECREF(dest);
@@ -1249,8 +1265,9 @@ static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args)
12491265
return PyLong_FromLong(count);
12501266
}
12511267
error:
1268+
Py_DECREF(sock);
12521269
if (!buf_passed) {
1253-
Py_DECREF(dest);
1270+
Py_XDECREF(dest);
12541271
} else {
12551272
PyBuffer_Release(&buf);
12561273
}
@@ -1275,6 +1292,7 @@ static PyObject *PySSL_SSLshutdown(PySSLSocket *self)
12751292
PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
12761293
return NULL;
12771294
}
1295+
Py_INCREF(sock);
12781296

12791297
/* Just in case the blocking state of the socket has been changed */
12801298
nonblocking = (sock->sock_timeout >= 0.0);
@@ -1324,24 +1342,29 @@ static PyObject *PySSL_SSLshutdown(PySSLSocket *self)
13241342
else
13251343
PyErr_SetString(PySSLErrorObject,
13261344
"The write operation timed out");
1327-
return NULL;
1345+
goto error;
13281346
}
13291347
else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
13301348
PyErr_SetString(PySSLErrorObject,
13311349
"Underlying socket too large for select().");
1332-
return NULL;
1350+
goto error;
13331351
}
13341352
else if (sockstate != SOCKET_OPERATION_OK)
13351353
/* Retain the SSL error code */
13361354
break;
13371355
}
13381356

1339-
if (err < 0)
1357+
if (err < 0) {
1358+
Py_DECREF(sock);
13401359
return PySSL_SetError(self, err, __FILE__, __LINE__);
1341-
else {
1342-
Py_INCREF(sock);
1343-
return (PyObject *) sock;
13441360
}
1361+
else
1362+
/* It's already INCREF'ed */
1363+
return (PyObject *) sock;
1364+
1365+
error:
1366+
Py_DECREF(sock);
1367+
return NULL;
13451368
}
13461369

13471370
PyDoc_STRVAR(PySSL_SSLshutdown_doc,

0 commit comments

Comments
 (0)