From f70b884ad70e2ce762842ae469f88bd48fe13998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Tue, 19 Mar 2019 02:56:28 +0100 Subject: bpo-36337: socket.send()/sendall() use Py_ssize_t (GH-12397) Fix buffer overflow in send() and sendall() methods of socket.socket for data larger than 2 GiB. --- .../2019-03-18-10-08-30.bpo-36337.QhJnXy.rst | 3 +++ Modules/socketmodule.c | 29 ++++++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-03-18-10-08-30.bpo-36337.QhJnXy.rst diff --git a/Misc/NEWS.d/next/Library/2019-03-18-10-08-30.bpo-36337.QhJnXy.rst b/Misc/NEWS.d/next/Library/2019-03-18-10-08-30.bpo-36337.QhJnXy.rst new file mode 100644 index 0000000..07cd8e2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-03-18-10-08-30.bpo-36337.QhJnXy.rst @@ -0,0 +1,3 @@ +Fix buffer overflow in :meth:`~socket.socket.send` and +:meth:`~socket.socket.sendall` methods of :func:`socket.socket` for data larger +than 2 GiB. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 0139754..4d5a8f6 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -625,16 +625,16 @@ set_gaierror(int error) #ifdef __VMS /* Function to send in segments */ -static int -sendsegmented(int sock_fd, char *buf, int len, int flags) +static Py_ssize_t +sendsegmented(int sock_fd, char *buf, Py_ssize_t len, int flags) { int n = 0; - int remaining = len; + Py_ssize_t remaining = len; while (remaining > 0) { unsigned int segment; - segment = (remaining >= SEGMENT_SIZE ? SEGMENT_SIZE : remaining); + segment = ((size_t)remaining >= SEGMENT_SIZE ? SEGMENT_SIZE : (unsigned int) remaining); n = send(sock_fd, buf, segment, flags); if (n < 0) { return n; @@ -2797,7 +2797,8 @@ static PyObject * sock_send(PySocketSockObject *s, PyObject *args) { char *buf; - int len, n = -1, flags = 0, timeout; + int flags = 0, timeout; + Py_ssize_t len, n = -1; Py_buffer pbuf; if (!PyArg_ParseTuple(args, "s*|i:send", &pbuf, &flags)) @@ -2813,12 +2814,18 @@ sock_send(PySocketSockObject *s, PyObject *args) BEGIN_SELECT_LOOP(s) Py_BEGIN_ALLOW_THREADS timeout = internal_select_ex(s, 1, interval); - if (!timeout) + if (!timeout) { #ifdef __VMS n = sendsegmented(s->sock_fd, buf, len, flags); +#elif defined(MS_WINDOWS) + if (len > INT_MAX) { + len = INT_MAX; + } + n = send(s->sock_fd, buf, (int)len, flags); #else n = send(s->sock_fd, buf, len, flags); #endif + } Py_END_ALLOW_THREADS if (timeout == 1) { PyBuffer_Release(&pbuf); @@ -2830,7 +2837,7 @@ sock_send(PySocketSockObject *s, PyObject *args) PyBuffer_Release(&pbuf); if (n < 0) return s->errorhandler(); - return PyInt_FromLong((long)n); + return PyInt_FromSsize_t(n); } PyDoc_STRVAR(send_doc, @@ -2847,7 +2854,8 @@ static PyObject * sock_sendall(PySocketSockObject *s, PyObject *args) { char *buf; - int len, n = -1, flags = 0, timeout, saved_errno; + int flags = 0, timeout, saved_errno; + Py_ssize_t len, n = -1; Py_buffer pbuf; if (!PyArg_ParseTuple(args, "s*|i:sendall", &pbuf, &flags)) @@ -2868,6 +2876,11 @@ sock_sendall(PySocketSockObject *s, PyObject *args) if (!timeout) { #ifdef __VMS n = sendsegmented(s->sock_fd, buf, len, flags); +#elif defined(MS_WINDOWS) + if (len > INT_MAX) { + len = INT_MAX; + } + n = send(s->sock_fd, buf, (int)len, flags); #else n = send(s->sock_fd, buf, len, flags); #endif -- cgit v0.12