summaryrefslogtreecommitdiff
path: root/network_io/win32
diff options
context:
space:
mode:
authorEvgeny Kotkov <kotkov@apache.org>2022-10-20 05:57:25 +0000
committerEvgeny Kotkov <kotkov@apache.org>2022-10-20 05:57:25 +0000
commita783ca8b7af24dd3392ce3658acbbf52d18af14e (patch)
tree28a9fd28092adce14775eaa71d47c0051cb14b4a /network_io/win32
parent8929428316cec371b7b621708f19f6d74652e9c2 (diff)
downloadapr-a783ca8b7af24dd3392ce3658acbbf52d18af14e.tar.gz
Win32: Stop apr_socket_sendv() from splitting iovecs into multiple possible
WSABUFs and error out on theoretical cases that cannot be handled with a single WSASend(). WSASend() returns the NumberOfBytesSent as DWORD, so the previous code that splitted overflowing iovecs never worked, as the total number of sent bytes cannot be properly represented by the API. So let's maintain a 1:1 relationship between the iovecs and WSABUFs, and error out on all inputs that exceed MAXDWORD. * network_io/win32/sendrecv.c (apr_socket_sendv): Remove the code that splits iovecs into WSABUFs. Check the sizes of all iovecs and the total size. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1904715 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'network_io/win32')
-rw-r--r--network_io/win32/sendrecv.c52
1 files changed, 21 insertions, 31 deletions
diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c
index 20d802042..e9c5a3952 100644
--- a/network_io/win32/sendrecv.c
+++ b/network_io/win32/sendrecv.c
@@ -90,51 +90,41 @@ APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock,
{
apr_status_t rc = APR_SUCCESS;
apr_ssize_t rv;
- apr_size_t cur_len;
- apr_int32_t nvec = 0;
- int i, j = 0;
+ apr_size_t total_len;
+ apr_int32_t i;
DWORD dwBytes = 0;
WSABUF *pWsaBuf;
+ total_len = 0;
for (i = 0; i < in_vec; i++) {
- cur_len = vec[i].iov_len;
- nvec++;
- while (cur_len > APR_DWORD_MAX) {
- nvec++;
- cur_len -= APR_DWORD_MAX;
- }
+ apr_size_t iov_len = vec[i].iov_len;
+ if (iov_len > MAXDWORD) {
+ /* WSASend() returns NumberOfBytesSent as DWORD, so any iovec
+ should be less than that. */
+ return APR_EINVAL;
+ }
+ total_len += iov_len;
+ if (total_len > MAXDWORD) {
+ /* WSASend() returns NumberOfBytesSent as DWORD, so the total size
+ should be less than that. */
+ return APR_EINVAL;
+ }
}
- pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec))
- : malloc(sizeof(WSABUF) * (nvec));
+ pWsaBuf = (in_vec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (in_vec))
+ : malloc(sizeof(WSABUF) * (in_vec));
if (!pWsaBuf)
return APR_ENOMEM;
for (i = 0; i < in_vec; i++) {
- char * base = vec[i].iov_base;
- cur_len = vec[i].iov_len;
-
- do {
- if (cur_len > APR_DWORD_MAX) {
- pWsaBuf[j].buf = base;
- pWsaBuf[j].len = APR_DWORD_MAX;
- cur_len -= APR_DWORD_MAX;
- base += APR_DWORD_MAX;
- }
- else {
- pWsaBuf[j].buf = base;
- pWsaBuf[j].len = (DWORD)cur_len;
- cur_len = 0;
- }
- j++;
-
- } while (cur_len > 0);
+ pWsaBuf[i].buf = vec[i].iov_base;
+ pWsaBuf[i].len = (ULONG) vec[i].iov_len;
}
- rv = WSASend(sock->socketdes, pWsaBuf, nvec, &dwBytes, 0, NULL, NULL);
+ rv = WSASend(sock->socketdes, pWsaBuf, in_vec, &dwBytes, 0, NULL, NULL);
if (rv == SOCKET_ERROR) {
rc = apr_get_netos_error();
}
- if (nvec > WSABUF_ON_STACK)
+ if (in_vec > WSABUF_ON_STACK)
free(pWsaBuf);
*nbytes = dwBytes;