Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!philabs!cmcl2!harvard!seismo!utah-cs!utah-gr!stride!bruce From: bruce@stride.UUCP (Bruce Robertson) Newsgroups: net.bugs.usg Subject: Bug with multiple stdio streams on one descriptor, FIX Message-ID: <562@stride.stride.UUCP> Date: Wed, 26-Mar-86 00:41:18 EST Article-I.D.: stride.562 Posted: Wed Mar 26 00:41:18 1986 Date-Received: Sun, 20-Apr-86 10:19:36 EST Reply-To: bruce@stride.UUCP (Bruce Robertson) Organization: Stride Micro, Reno, NV. Lines: 89 Description: There is a bug in Standard I/O for System V Release 2 Version 2. If you have more than one FILE stream open on a single file descriptor, bad things to your malloc() heap space happen. Throughout the stdio code, the end of the buffer associated with a stream is referenced by the macro _bufend(). This macro is defined in /usr/include/stdio.h, and references a table of pointers the end of the buffers. The problem is, the table is referenced like this: _bufendtab[(p)->_file] where `p' is your FILE pointer. This is wrong. What you really want to do is reference the table like this: _bufendtab[(p) - &_iob[0]] which associates slots in the table of pointers with slots in the table of _iob structures. Repeat-By: int fd; FILE *fp1, *fp2; fd = open("/dev/tty", 2); fp1 = fdopen(fd, "r"); fp2 = fdopen(fd, "w"); Subsequent fputs() calls to `fp2' will cause random areas of memory to be modified, because the data structures that describe the length of the buffer have been clobbered. Fix: Two fixes - one to /usr/include/stdio.h, and another to /usr/src/lib/libc/port/print/doprnt.c, which also references the table incorrectly, without using the macro. Note that after making the change to /usr/include/stdio.h, you must recompile everything in /usr/src/lib/libc/port/stdio. *** /usr/include/stdio.h-old Mon Jul 2 19:32:20 1984 --- /usr/include/stdio.h Tue Mar 4 22:14:47 1986 *************** *** 54,60 #define stdout (&_iob[1]) #define stderr (&_iob[2]) ! #define _bufend(p) _bufendtab[(p)->_file] #define _bufsiz(p) (_bufend(p) - (p)->_base) #ifndef lint --- 54,60 ----- #define stdout (&_iob[1]) #define stderr (&_iob[2]) ! #define _bufend(p) _bufendtab[(p) - &_iob[0]] #define _bufsiz(p) (_bufend(p) - (p)->_base) #ifndef lint *** /usr/src/lib/libc/port/print/doprnt.c-old Tue Mar 25 21:26:41 1986 --- /usr/src/lib/libc/port/print/doprnt.c Tue Mar 25 21:26:43 1986 *************** *** 159,165 bufptr = iop->_ptr; bufferend = (fno == _NFILE) ? (unsigned char *)((long) bufptr | (-1L & ~HIBITL)) ! : _bufendtab[fno]; } /* --- 159,165 ----- bufptr = iop->_ptr; bufferend = (fno == _NFILE) ? (unsigned char *)((long) bufptr | (-1L & ~HIBITL)) ! : _bufend(iop); } /* -- Bruce Robertson UUCP: cbosgd!utah-cs!utah-gr!stride!bruce ARPA: stride!bruce@utah-gr.arpa