From c91307c1024fe0a079ae2fa98e825f9fda04490f Mon Sep 17 00:00:00 2001 From: Michael Santos Date: Wed, 30 Jul 2014 11:25:01 -0400 Subject: [PATCH] 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. --- c_src/alcove.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/c_src/alcove.c b/c_src/alcove.c index 2870752..470009c 100644 --- a/c_src/alcove.c +++ b/c_src/alcove.c @@ -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