summaryrefslogtreecommitdiff
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
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
-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;