summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkotkov <kotkov@13f79535-47bb-0310-9956-ffa450edef68>2022-10-20 06:09:04 +0000
committerkotkov <kotkov@13f79535-47bb-0310-9956-ffa450edef68>2022-10-20 06:09:04 +0000
commitde674c356f5ea2d89da40a3ed5af48e3eef4491e (patch)
treee5d09b0b292440a015ac9fdca887b2cf577e93e2
parent965bfd16b61d1aa902d2ba3935314ba7a1e78b16 (diff)
downloadlibapr-de674c356f5ea2d89da40a3ed5af48e3eef4491e.tar.gz
On 1.8.x branch: Merge r1904715 from trunk:
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(). git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.8.x@1904716 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--network_io/win32/sendrecv.c54
1 files changed, 22 insertions, 32 deletions
diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c
index 3fa0c8dda..f5f23d2c7 100644
--- a/network_io/win32/sendrecv.c
+++ b/network_io/win32/sendrecv.c
@@ -100,53 +100,43 @@ 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;
}
#ifndef _WIN32_WCE
- 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();
}
#else
- for (i = 0; i < nvec; i++) {
+ for (i = 0; i < in_vec; i++) {
rv = send(sock->socketdes, pWsaBuf[i].buf, pWsaBuf[i].len, 0);
if (rv == SOCKET_ERROR) {
rc = apr_get_netos_error();
@@ -155,7 +145,7 @@ APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock,
dwBytes += rv;
}
#endif
- if (nvec > WSABUF_ON_STACK)
+ if (in_vec > WSABUF_ON_STACK)
free(pWsaBuf);
*nbytes = dwBytes;