alcove_write: fix end of array check

This code looked fishy to me but I couldn't pinpoint why and it worked on
Ubuntu 12.04/armv7l, Ubuntu 12.04/amd64, OpenBSD 5.5/amd64 and FreeBSD
10/amd64. I forgot to test on Ubuntu 14.04/amd64 of course and
thankfully it failed there.

The code compares the number of bytes written by writev against each of
the iov_len fields in the iovec array and decrements the value
accordingly. So an iovec array that looks like:

    iov[0].iov_len = 4
    iov[1].iov_len = 6

    number of bytes written = 10 bytes

Would be computed as follows:

    count = 2

    0: 10 >= iov[0].iov_len (4) -> 6
    1: 6 >= iov[1].iov_len (6) -> 0
    2: 0 >= iov[2].iov_len (undefined) -> ???
    3: ...

Limit iteration to the size of the iovec array. Although this commit fixes
this issue, this code should either be further simplified or re-written.
This commit is contained in:
Michael Santos
2014-07-30 11:25:01 -04:00
parent 4ec1a4640e
commit c91307c102

View File

@@ -511,24 +511,24 @@ alcove_write(int fd, struct iovec *iov, int count)
{
ssize_t written = 0;
ssize_t n = 0;
int cur = 0;
int offset = 0;
for ( ; ; ) {
written = writev(fd, iov+cur, count-cur);
do {
iov[offset].iov_base = (char *)iov[offset].iov_base + written;
iov[offset].iov_len -= written;
written = writev(fd, iov+offset, count-offset);
if (written <= 0)
return written;
n += written;
while (written >= iov[cur].iov_len)
written -= iov[cur++].iov_len;
for ( ; offset < count && written >= iov[offset].iov_len; offset++)
written -= iov[offset].iov_len;
if (cur == count)
return n;
} while (offset < count);
iov[cur].iov_base = (char *)iov[cur].iov_base + written;
iov[cur].iov_len -= written;
}
return n;
}
int