diff options
author | Evgeny Kotkov <kotkov@apache.org> | 2022-10-20 05:57:25 +0000 |
---|---|---|
committer | Evgeny Kotkov <kotkov@apache.org> | 2022-10-20 05:57:25 +0000 |
commit | a783ca8b7af24dd3392ce3658acbbf52d18af14e (patch) | |
tree | 28a9fd28092adce14775eaa71d47c0051cb14b4a /network_io/win32 | |
parent | 8929428316cec371b7b621708f19f6d74652e9c2 (diff) | |
download | apr-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.c | 52 |
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; |