Commit 5133b3a8 authored by Benjamin Peterson's avatar Benjamin Peterson

#4967 fix buggy read()

parent e729230d
...@@ -1244,9 +1244,12 @@ pending on the connection.\n"); ...@@ -1244,9 +1244,12 @@ pending on the connection.\n");
static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
{ {
PyObject *buf = NULL; PyObject *dest = NULL;
Py_buffer buf;
int buf_passed = 0; int buf_passed = 0;
int count = -1; int count = -1;
char *mem;
/* XXX this should use Py_ssize_t */
int len = 1024; int len = 1024;
int sockstate; int sockstate;
int err; int err;
...@@ -1260,19 +1263,22 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) ...@@ -1260,19 +1263,22 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
return NULL; return NULL;
} }
if (!PyArg_ParseTuple(args, "|Oi:read", &buf, &count)) if (!PyArg_ParseTuple(args, "|Oi:read", &dest, &count))
return NULL; return NULL;
if ((buf == NULL) || (buf == Py_None)) { if ((dest == NULL) || (dest == Py_None)) {
if (!(buf = PyByteArray_FromStringAndSize((char *) 0, len))) if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
return NULL; return NULL;
} else if (PyLong_Check(buf)) { mem = PyByteArray_AS_STRING(dest);
len = PyLong_AS_LONG(buf); } else if (PyLong_Check(dest)) {
if (!(buf = PyByteArray_FromStringAndSize((char *) 0, len))) len = PyLong_AS_LONG(dest);
if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
return NULL; return NULL;
mem = PyByteArray_AS_STRING(dest);
} else { } else {
if (!PyByteArray_Check(buf)) if (PyObject_GetBuffer(dest, &buf, PyBUF_CONTIG) < 0)
return NULL; return NULL;
len = PyByteArray_Size(buf); mem = buf.buf;
len = buf.len;
if ((count > 0) && (count <= len)) if ((count > 0) && (count <= len))
len = count; len = count;
buf_passed = 1; buf_passed = 1;
...@@ -1293,18 +1299,11 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) ...@@ -1293,18 +1299,11 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
if (sockstate == SOCKET_HAS_TIMED_OUT) { if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject, PyErr_SetString(PySSLErrorObject,
"The read operation timed out"); "The read operation timed out");
if (!buf_passed) { goto error;
Py_DECREF(buf);
}
return NULL;
} 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().");
if (!buf_passed) { goto error;
Py_DECREF(buf);
}
Py_DECREF(buf);
return NULL;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
count = 0; count = 0;
goto done; goto done;
...@@ -1313,15 +1312,11 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) ...@@ -1313,15 +1312,11 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
do { do {
err = 0; err = 0;
PySSL_BEGIN_ALLOW_THREADS 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); err = SSL_get_error(self->ssl, count);
PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS
if(PyErr_CheckSignals()) { if (PyErr_CheckSignals())
if (!buf_passed) { goto error;
Py_DECREF(buf);
}
return NULL;
}
if (err == SSL_ERROR_WANT_READ) { if (err == SSL_ERROR_WANT_READ) {
sockstate = sockstate =
check_socket_and_wait_for_timeout(sock, 0); check_socket_and_wait_for_timeout(sock, 0);
...@@ -1340,29 +1335,31 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) ...@@ -1340,29 +1335,31 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
if (sockstate == SOCKET_HAS_TIMED_OUT) { if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject, PyErr_SetString(PySSLErrorObject,
"The read operation timed out"); "The read operation timed out");
if (!buf_passed) { goto error;
Py_DECREF(buf);
}
return NULL;
} 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);
if (count <= 0) { if (count <= 0) {
if (!buf_passed) { PySSL_SetError(self, count, __FILE__, __LINE__);
Py_DECREF(buf); goto error;
}
return PySSL_SetError(self, count, __FILE__, __LINE__);
} }
done: done:
if (!buf_passed) { if (!buf_passed) {
PyObject *res = PyBytes_FromStringAndSize( PyObject *res = PyBytes_FromStringAndSize(mem, count);
PyByteArray_AS_STRING(buf), count); Py_DECREF(dest);
Py_DECREF(buf);
return res; return res;
} else { } else {
PyBuffer_Release(&buf);
return PyLong_FromLong(count); return PyLong_FromLong(count);
} }
error:
if (!buf_passed) {
Py_DECREF(dest);
} else {
PyBuffer_Release(&buf);
}
return NULL;
} }
PyDoc_STRVAR(PySSL_SSLread_doc, PyDoc_STRVAR(PySSL_SSLread_doc,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment