[2.7] bpo-36337: Use ssize_t and size_t for socket.send()/sendall()#12397
[2.7] bpo-36337: Use ssize_t and size_t for socket.send()/sendall()#12397vstinner merged 11 commits intopython:2.7from
Conversation
|
I don't think that a test is needed: I cannot find a test on master. Your PR is wrong on Windows. Look at the master branch: On Windows, the type of send() length argument is int, not size_t. |
…ckport the solution from 3.x with Py_ssize_t
| char *buf; | ||
| int len, n = -1, flags = 0, timeout; | ||
| int flags = 0, timeout; | ||
| Py_ssize_t len, n = -1; |
There was a problem hiding this comment.
return PyInt_FromLong((long)n); below is wrong
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
|
I have made the requested changes; please review again |
|
Thanks for making the requested changes! @vstinner: please review the changes made to this pull request. |
| if (!timeout) | ||
| if (!timeout) { | ||
| #ifdef __VMS | ||
| n = sendsegmented(s->sock_fd, buf, len, flags); |
There was a problem hiding this comment.
That's wrong: sendsegmented() len type is int, not Py_ssize_t. Don't forget the VMS! :-)
| @@ -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)). | |||
There was a problem hiding this comment.
I propose:
Fix buffer overflow in :meth:~socket.socket.send and :meth:~socket.socket.sendall methods of :func:socket.socket for data larger than 2 GiB.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
|
I have made the requested changes; please review again |
|
Thanks for making the requested changes! @vstinner: please review the changes made to this pull request. |
| if (!timeout) { | ||
| #ifdef __VMS | ||
| n = sendsegmented(s->sock_fd, buf, len, flags); | ||
| n = sendsegmented(s->sock_fd, buf, (int)len, flags); |
There was a problem hiding this comment.
(int)len is unsafe if len is larger than INT_MAX. You should modify sendsegmented() to accept Py_ssize_t rather than int.
There was a problem hiding this comment.
👍 good catch and I was thinking about this problem.
vstinner
left a comment
There was a problem hiding this comment.
LGTM.
The subtle side effect of this change is that send() and sendall() now always return a Python 'long' object, whereas they always returned a Python 'int' object previously. I think that it's acceptable, but it might be risky to push so change late in 2.7 lifetime (EOL scheduled at the beginning of next year).
On the other side, currently, calling sendall() with more than 2 GiB data loose data. But well, who does that with Python 2.7?
I would prefer to have the review of another core dev.
@benjaminp @serhiy-storchaka @pablogsal: Would you mind to review this change? Do you think that it's ok to change send/sendall return type (int => long, supposed to be compatible)?
|
I have made the requested changes; please review again |
|
Thanks for making the requested changes! @vstinner: please review the changes made to this pull request. |
| unsigned int segment; | ||
|
|
||
| segment = (remaining >= SEGMENT_SIZE ? SEGMENT_SIZE : remaining); | ||
| segment = ((size_t)remaining >= SEGMENT_SIZE ? SEGMENT_SIZE : (unsigned int) remaining); |
There was a problem hiding this comment.
Wait, is this cast safe? In C99 ssize_t can be an unsigned long, unless I am missing something. I think you need:
Py_SAFE_DOWNCAST(remaining, Py_ssize_t, unsigned int)
There was a problem hiding this comment.
SEGMENT_SIZE is 32 KiB: remaining is only casted for values between [0; 32 KiB]:
#define SEGMENT_SIZE (32 * 1024 -1)
This PR is not yet completed (missing tests), I have "backported" a patch from 3.x.
https://bugs.python.org/issue36337