summaryrefslogtreecommitdiffstats
path: root/Modules/_ssl.c
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2009-02-28 19:06:54 (GMT)
committerBenjamin Peterson <benjamin@python.org>2009-02-28 19:06:54 (GMT)
commit56420b406d0aa039c1a2476e520990635696136f (patch)
treef4d695a9405cae3a9e6e90b1ad2f20fcb453f932 /Modules/_ssl.c
parent1bd2e29d82778ad37f6d038db6d23321abaa8f9b (diff)
downloadcpython-56420b406d0aa039c1a2476e520990635696136f.zip
cpython-56420b406d0aa039c1a2476e520990635696136f.tar.gz
cpython-56420b406d0aa039c1a2476e520990635696136f.tar.bz2
#4967 fix buggy read()
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r--Modules/_ssl.c69
1 files changed, 33 insertions, 36 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 37a14b1..3c9dd61 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -1244,9 +1244,12 @@ pending on the connection.\n");
static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
{
- PyObject *buf = NULL;
+ PyObject *dest = NULL;
+ Py_buffer buf;
int buf_passed = 0;
int count = -1;
+ char *mem;
+ /* XXX this should use Py_ssize_t */
int len = 1024;
int sockstate;
int err;
@@ -1260,19 +1263,22 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
return NULL;
}
- if (!PyArg_ParseTuple(args, "|Oi:read", &buf, &count))
+ if (!PyArg_ParseTuple(args, "|Oi:read", &dest, &count))
return NULL;
- if ((buf == NULL) || (buf == Py_None)) {
- if (!(buf = PyByteArray_FromStringAndSize((char *) 0, len)))
+ if ((dest == NULL) || (dest == Py_None)) {
+ if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
return NULL;
- } else if (PyLong_Check(buf)) {
- len = PyLong_AS_LONG(buf);
- if (!(buf = PyByteArray_FromStringAndSize((char *) 0, len)))
+ mem = PyByteArray_AS_STRING(dest);
+ } else if (PyLong_Check(dest)) {
+ len = PyLong_AS_LONG(dest);
+ if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
return NULL;
+ mem = PyByteArray_AS_STRING(dest);
} else {
- if (!PyByteArray_Check(buf))
+ if (PyObject_GetBuffer(dest, &buf, PyBUF_CONTIG) < 0)
return NULL;
- len = PyByteArray_Size(buf);
+ mem = buf.buf;
+ len = buf.len;
if ((count > 0) && (count <= len))
len = count;
buf_passed = 1;
@@ -1293,18 +1299,11 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
"The read operation timed out");
- if (!buf_passed) {
- Py_DECREF(buf);
- }
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
PyErr_SetString(PySSLErrorObject,
"Underlying socket too large for select().");
- if (!buf_passed) {
- Py_DECREF(buf);
- }
- Py_DECREF(buf);
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
count = 0;
goto done;
@@ -1313,15 +1312,11 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
do {
err = 0;
PySSL_BEGIN_ALLOW_THREADS
- count = SSL_read(self->ssl, PyByteArray_AsString(buf), len);
+ count = SSL_read(self->ssl, mem, len);
err = SSL_get_error(self->ssl, count);
PySSL_END_ALLOW_THREADS
- if(PyErr_CheckSignals()) {
- if (!buf_passed) {
- Py_DECREF(buf);
- }
- return NULL;
- }
+ if (PyErr_CheckSignals())
+ goto error;
if (err == SSL_ERROR_WANT_READ) {
sockstate =
check_socket_and_wait_for_timeout(sock, 0);
@@ -1340,29 +1335,31 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
"The read operation timed out");
- if (!buf_passed) {
- Py_DECREF(buf);
- }
- return NULL;
+ goto error;
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
break;
}
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
if (count <= 0) {
- if (!buf_passed) {
- Py_DECREF(buf);
- }
- return PySSL_SetError(self, count, __FILE__, __LINE__);
+ PySSL_SetError(self, count, __FILE__, __LINE__);
+ goto error;
}
done:
if (!buf_passed) {
- PyObject *res = PyBytes_FromStringAndSize(
- PyByteArray_AS_STRING(buf), count);
- Py_DECREF(buf);
+ PyObject *res = PyBytes_FromStringAndSize(mem, count);
+ Py_DECREF(dest);
return res;
} else {
+ PyBuffer_Release(&buf);
return PyLong_FromLong(count);
}
+ error:
+ if (!buf_passed) {
+ Py_DECREF(dest);
+ } else {
+ PyBuffer_Release(&buf);
+ }
+ return NULL;
}
PyDoc_STRVAR(PySSL_SSLread_doc,