From 17bf06c97f4289897dffff8ab001ff39f508b7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 10:09:12 +0100 Subject: [PATCH 01/11] bpo-36337: Use ssize_t and size_t for socket.send()/sendall() --- .../next/Library/2019-03-18-10-08-30.bpo-36337.QhJnXy.rst | 3 +++ Modules/socketmodule.c | 8 ++++++-- 2 files changed, 9 insertions(+), 2 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 00000000000000..a624d781a283cf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-03-18-10-08-30.bpo-36337.QhJnXy.rst @@ -0,0 +1,3 @@ +Use ssize_t and size_t instead of int for the send() function (see +http://man7.org/linux/man-pages/man2/send.2.html (Linux) and +https://nixdoc.net/man-pages/FreeBSD/man2/send.2.html (FreeBSD)). diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 013975455c453f..f84f219ea2b803 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2797,7 +2797,9 @@ static PyObject * sock_send(PySocketSockObject *s, PyObject *args) { char *buf; - int len, n = -1, flags = 0, timeout; + int flags = 0, timeout; + ssize_t n = -1; + size_t len; Py_buffer pbuf; if (!PyArg_ParseTuple(args, "s*|i:send", &pbuf, &flags)) @@ -2847,7 +2849,9 @@ 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; + ssize_t len; + size_t n = -1; Py_buffer pbuf; if (!PyArg_ParseTuple(args, "s*|i:sendall", &pbuf, &flags)) From 4c59062f467ac92ca7cc11e0bd99efdd61784f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 12:22:17 +0100 Subject: [PATCH 02/11] On Windows, the type of send() length argument is int, not size_t: backport the solution from 3.x with Py_ssize_t --- Modules/socketmodule.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index f84f219ea2b803..943d978f1d4da5 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2798,8 +2798,7 @@ sock_send(PySocketSockObject *s, PyObject *args) { char *buf; int flags = 0, timeout; - ssize_t n = -1; - size_t len; + Py_ssize_t len, n = -1; Py_buffer pbuf; if (!PyArg_ParseTuple(args, "s*|i:send", &pbuf, &flags)) @@ -2815,12 +2814,17 @@ 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 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); @@ -2850,8 +2854,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) { char *buf; int flags = 0, timeout, saved_errno; - ssize_t len; - size_t n = -1; + Py_ssize_t len, n = -1; Py_buffer pbuf; if (!PyArg_ParseTuple(args, "s*|i:sendall", &pbuf, &flags)) @@ -2872,6 +2875,10 @@ sock_sendall(PySocketSockObject *s, PyObject *args) if (!timeout) { #ifdef __VMS n = sendsegmented(s->sock_fd, buf, len, flags); +#elif 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 From 59c20ea10a97290c886b1136348b1a1c9b3c08f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 12:49:48 +0100 Subject: [PATCH 03/11] Fix on Windows --- Modules/socketmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 943d978f1d4da5..323e2d7c47300b 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2817,7 +2817,7 @@ sock_send(PySocketSockObject *s, PyObject *args) if (!timeout) { #ifdef __VMS n = sendsegmented(s->sock_fd, buf, len, flags); -#elif MS_WINDOWS +#elif defined(MS_WINDOWS) if (len > INT_MAX) len = INT_MAX; n = send(s->sock_fd, buf, (int)len, flags); @@ -2875,7 +2875,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) if (!timeout) { #ifdef __VMS n = sendsegmented(s->sock_fd, buf, len, flags); -#elif MS_WINDOWS +#elif defined(MS_WINDOWS) if (len > INT_MAX) len = INT_MAX; n = send(s->sock_fd, buf, (int)len, flags); From c78ef94275690142003f112089a7990633b79778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 12:52:16 +0100 Subject: [PATCH 04/11] Fix PEP7 --- Modules/socketmodule.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 323e2d7c47300b..4c0d928f1b185c 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2818,8 +2818,9 @@ sock_send(PySocketSockObject *s, PyObject *args) #ifdef __VMS n = sendsegmented(s->sock_fd, buf, len, flags); #elif defined(MS_WINDOWS) - if (len > INT_MAX) + 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); @@ -2876,8 +2877,9 @@ sock_sendall(PySocketSockObject *s, PyObject *args) #ifdef __VMS n = sendsegmented(s->sock_fd, buf, len, flags); #elif defined(MS_WINDOWS) - if (len > INT_MAX) + 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); From b4e16ea3d5bd665cc86d42679b8bc7b6cc79982e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 14:00:59 +0100 Subject: [PATCH 05/11] convert to long from ssize_t --- Modules/socketmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 4c0d928f1b185c..77323b46b83230 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2837,7 +2837,7 @@ sock_send(PySocketSockObject *s, PyObject *args) PyBuffer_Release(&pbuf); if (n < 0) return s->errorhandler(); - return PyInt_FromLong((long)n); + return PyLong_FromSsize_t(n); } PyDoc_STRVAR(send_doc, From 405a5d2cf6cac34cb9bde181507bd2a65ce61026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 14:20:50 +0100 Subject: [PATCH 06/11] On VMS, sendsegmented(), len type is int, not Py_ssize_t --- Modules/socketmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 77323b46b83230..3cfcfc3c9da6d1 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2816,7 +2816,7 @@ sock_send(PySocketSockObject *s, PyObject *args) timeout = internal_select_ex(s, 1, interval); if (!timeout) { #ifdef __VMS - n = sendsegmented(s->sock_fd, buf, len, flags); + n = sendsegmented(s->sock_fd, buf, (int)len, flags); #elif defined(MS_WINDOWS) if (len > INT_MAX) { len = INT_MAX; @@ -2875,7 +2875,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) n = -1; if (!timeout) { #ifdef __VMS - n = sendsegmented(s->sock_fd, buf, len, flags); + n = sendsegmented(s->sock_fd, buf, (int)len, flags); #elif defined(MS_WINDOWS) if (len > INT_MAX) { len = INT_MAX; From 995c41db1e6734ac374de605e793ed78673ff9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 14:21:37 +0100 Subject: [PATCH 07/11] Improve the blurb entry --- .../next/Library/2019-03-18-10-08-30.bpo-36337.QhJnXy.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 index a624d781a283cf..07cd8e2bd6118f 100644 --- 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 @@ -1,3 +1,3 @@ -Use ssize_t and size_t instead of int for the send() function (see -http://man7.org/linux/man-pages/man2/send.2.html (Linux) and -https://nixdoc.net/man-pages/FreeBSD/man2/send.2.html (FreeBSD)). +Fix buffer overflow in :meth:`~socket.socket.send` and +:meth:`~socket.socket.sendall` methods of :func:`socket.socket` for data larger +than 2 GiB. From 3300ad68edfbc2d4bd61ae0bae3315be360b0f12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 14:30:33 +0100 Subject: [PATCH 08/11] avoid a buffer overflow when len is greater than INT_MAX on VMS --- Modules/socketmodule.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 3cfcfc3c9da6d1..65bd6deeb68957 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2816,6 +2816,9 @@ sock_send(PySocketSockObject *s, PyObject *args) timeout = internal_select_ex(s, 1, interval); if (!timeout) { #ifdef __VMS + if (len > INT_MAX) { + len = INT_MAX; + } n = sendsegmented(s->sock_fd, buf, (int)len, flags); #elif defined(MS_WINDOWS) if (len > INT_MAX) { @@ -2875,6 +2878,9 @@ sock_sendall(PySocketSockObject *s, PyObject *args) n = -1; if (!timeout) { #ifdef __VMS + if (len > INT_MAX) { + len = INT_MAX; + } n = sendsegmented(s->sock_fd, buf, (int)len, flags); #elif defined(MS_WINDOWS) if (len > INT_MAX) { From 55f2b36a77202169d4b5da394d72c5eca63df6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 14:45:35 +0100 Subject: [PATCH 09/11] use Py_ssize_t for sendsegmented --- Modules/socketmodule.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 65bd6deeb68957..6ab7ed8a1b4e88 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -625,11 +625,11 @@ 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; @@ -2819,7 +2819,7 @@ sock_send(PySocketSockObject *s, PyObject *args) if (len > INT_MAX) { len = INT_MAX; } - n = sendsegmented(s->sock_fd, buf, (int)len, flags); + n = sendsegmented(s->sock_fd, buf, len, flags); #elif defined(MS_WINDOWS) if (len > INT_MAX) { len = INT_MAX; @@ -2881,7 +2881,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) if (len > INT_MAX) { len = INT_MAX; } - n = sendsegmented(s->sock_fd, buf, (int)len, flags); + n = sendsegmented(s->sock_fd, buf, len, flags); #elif defined(MS_WINDOWS) if (len > INT_MAX) { len = INT_MAX; From 40dbaf42d217cdb627443e893bd2270d7bc95ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 14:54:46 +0100 Subject: [PATCH 10/11] Improvement with Victor --- Modules/socketmodule.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 6ab7ed8a1b4e88..5ffb0d96698db7 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -634,7 +634,7 @@ sendsegmented(int sock_fd, char *buf, Py_ssize_t len, int flags) 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; @@ -2816,9 +2816,6 @@ sock_send(PySocketSockObject *s, PyObject *args) timeout = internal_select_ex(s, 1, interval); if (!timeout) { #ifdef __VMS - if (len > INT_MAX) { - len = INT_MAX; - } n = sendsegmented(s->sock_fd, buf, len, flags); #elif defined(MS_WINDOWS) if (len > INT_MAX) { @@ -2878,9 +2875,6 @@ sock_sendall(PySocketSockObject *s, PyObject *args) n = -1; if (!timeout) { #ifdef __VMS - if (len > INT_MAX) { - len = INT_MAX; - } n = sendsegmented(s->sock_fd, buf, len, flags); #elif defined(MS_WINDOWS) if (len > INT_MAX) { From 84a8d9f036f8840d977436f2e81325fa68a4ecfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 18 Mar 2019 23:55:42 +0100 Subject: [PATCH 11/11] Improvement with the remark of Serhiy --- Modules/socketmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 5ffb0d96698db7..4d5a8f6f01703d 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2837,7 +2837,7 @@ sock_send(PySocketSockObject *s, PyObject *args) PyBuffer_Release(&pbuf); if (n < 0) return s->errorhandler(); - return PyLong_FromSsize_t(n); + return PyInt_FromSsize_t(n); } PyDoc_STRVAR(send_doc,