diff options
author | Yann Ylavic <ylavic@apache.org> | 2022-06-28 11:23:22 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2022-06-28 11:23:22 +0000 |
commit | 443a5314045169047070ad3a32e5134227d837dd (patch) | |
tree | 7e2f9ec838b67e797d4e05a6cbe258d17b4c5796 /network_io | |
parent | 27046d793026738b08478b86e29060a8a0533b32 (diff) | |
download | apr-443a5314045169047070ad3a32e5134227d837dd.tar.gz |
apr_socket_sendv: unix: APR_INCOMPLETE_WRITE pre to post processing.
Rather than precomputing requested_len before writev() and later comparing with
what has been sent, we can walk the iovec after only to see if it's exhausted.
This saves useless precomputation on error (e.g. nonblocking EAGAIN) and avoids
a poteential invalid/overflowed requested_len should the iovec point to more
than SIZE_MAX bytes.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1902314 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'network_io')
-rw-r--r-- | network_io/unix/sendrecv.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c index b9e580b1b..1b965af50 100644 --- a/network_io/unix/sendrecv.c +++ b/network_io/unix/sendrecv.c @@ -196,13 +196,8 @@ apr_status_t apr_socket_sendv(apr_socket_t * sock, const struct iovec *vec, { #ifdef HAVE_WRITEV apr_ssize_t rv; - apr_size_t requested_len = 0; apr_int32_t i; - for (i = 0; i < nvec; i++) { - requested_len += vec[i].iov_len; - } - if (sock->options & APR_INCOMPLETE_WRITE) { sock->options &= ~APR_INCOMPLETE_WRITE; goto do_select; @@ -231,8 +226,16 @@ do_select: *len = 0; return errno; } - if ((sock->timeout > 0) && (rv < requested_len)) { - sock->options |= APR_INCOMPLETE_WRITE; + if (sock->timeout > 0) { + apr_size_t rv_len = rv; + for (i = 0; i < nvec; ++i) { + apr_size_t iov_len = vec[i].iov_len; + if (rv_len < iov_len) { + sock->options |= APR_INCOMPLETE_WRITE; + break; + } + rv_len -= iov_len; + } } (*len) = rv; return APR_SUCCESS; |