Date: Mon, 12 Oct 1998 18:04:22 +0900 (JST) From: Satosi KOBAYASI <kobayasi@north.ad.jp> To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: bin/8281: writev() in libc_r causes loop Message-ID: <199810120904.SAA17994@athena.nextech.co.jp>
next in thread | raw e-mail | index | archive | help
>Number: 8281 >Category: bin >Synopsis: writev() in libc_r causes loop >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Oct 12 02:10:00 PDT 1998 >Last-Modified: >Originator: Satosi KOBAYASI >Organization: NORTH (Network Organization for Research and Technology in Hokkaido) >Release: FreeBSD 2.2.7-RELEASE i386 >Environment: FreeBSD athena 2.2.7-RELEASE FreeBSD 2.2.7-RELEASE #0: Sun Oct 4 17:27:30 JST 1998 kobayasi@athena:/usr/local/src/remote/sys/compile/ASIX i386 >Description: writev() in libc_r causes loop when it's called with the following arguments: * the iovcnt is more than 0 * at the last member of the iovec array, the iov_len set to 0 (Detail) writev() defined in /usr/src/lib/libc_r/uthread/uthread_writev.c, calls _thread_sys_writev() in itself. When _thread_sys_writev() returns 0, writev() does't increment the index of the iovec array. So if the index points to the last member of the array, writev() calls _thread_sys_writev() with the member whose iov_len set to 0. Because there is nothing to write, _thread_sys_writev() returns 0, and writev() doesn't increment the index... >How-To-Repeat: Compile the following code with -lc_r, and run it. #include <stdio.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> static char b1[] = "test"; static char b2[] = "foo"; int main(int argc, char **argv) { int fd; struct iovec buf[2]; if (argc != 2) { fprintf(stderr, "Usage: %s <filename>\n", *argv); exit(1); } if ((fd = open(*(argv + 1), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { perror("open"); exit(1); } buf[0].iov_base = b1; buf[0].iov_len = strlen(b1); buf[1].iov_base = b2; buf[1].iov_len = 0; if (writev(fd, buf, 2) < 0) { perror("writev"); exit(1); } close(fd); exit(0); } >Fix: Apply the following patch or something like this. --- uthread_writev.c.orig Mon Oct 12 17:38:58 1998 +++ uthread_writev.c Mon Oct 12 18:00:02 1998 @@ -83,6 +83,16 @@ /* Perform a non-blocking write syscall: */ n = _thread_sys_writev(fd, &p_iov[idx], iovcnt - idx); + /* To avoid loop */ + if (n == 0) { + while (idx < iovcnt && p_iov[idx].iov_len == 0) + idx++; + if (idx == iovcnt) { + ret = num; + break; + } + } + /* Check if one or more bytes were written: */ if (n > 0) { /* >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199810120904.SAA17994>