summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkotkov <kotkov@13f79535-47bb-0310-9956-ffa450edef68>2022-10-20 05:57:25 +0000
committerkotkov <kotkov@13f79535-47bb-0310-9956-ffa450edef68>2022-10-20 05:57:25 +0000
commit5f87152ee7a3d7e8c7348fa5f5cc574263c08858 (patch)
tree28a9fd28092adce14775eaa71d47c0051cb14b4a
parentf0de40ece46dfb80a81878eebf32b56e08344563 (diff)
downloadlibapr-5f87152ee7a3d7e8c7348fa5f5cc574263c08858.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
-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;