mouse@mcgill-vision.UUCP (der Mouse) (11/15/88)
In article <14413@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes: > In article <1004@cps3xx.UUCP> usenet@cps3xx.UUCP (Usenet file owner) writes: >> Could someone tell me what the _IOSTRG parameter in stdio.h on BSD >> controls? > Absolutely nothing. It is never tested. You can expect it to vanish > in the future. [Reality check time: I'm about to disagree with Chris.] From flsbuf.c: fclose(iop) register FILE *iop; { .... if (iop->_flag&(_IOREAD|_IOWRT|_IORW) && (iop->_flag&_IOSTRG)==0) { From filbuf.c: _filbuf(iop) register FILE *iop; { .... if (iop->_flag&(_IOSTRG|_IOEOF)) (And yes, Chris, this is the distribution stdio, not my stdio.) To answer what the original poster probably wanted to know, _IOSTRG indicates that the stream is a fake stream for I/O to a string: sprintf or sscanf. As for what it actually *controls*, Chris is almost correct; I think _doprnt doesn't check this flag at all [VAX version], and (bug alert!) neither does _flsbuf. If you sprintf more than 32K, sprintf will make mistakes. Initially, the mistakes are (relatively) benign (the sprintffed output past 32K gets stuffed in malloc()ed memory which is then lost), but if you push it to 40K, it will start flushing stuff to a random file descriptor ("random" = "stack trash"), which in my tests happened to be 0, the standard input. Examination of the code indicates that potential exists for it to drop core if it gets the wrong stack trash. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
chris@mimsy.UUCP (Chris Torek) (11/15/88)
>In article <14413@mimsy.UUCP> I claimed: >>... It is never tested. You can expect it to vanish in the future. [what, Never? well, Hardly Ever :-) ] In article <1353@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse) writes: >[Reality check time: I'm about to disagree with Chris.] [Yipes, that was my third egregious netnews error in the last few weeks. What *is* the world coming to? ... Must have been the worm! :-) ] >flsbuf.c: > fclose(iop) >.... > (iop->_flag&_IOSTRG)==0 This one is actually rather amusing, as the routines which set _IOSTRG never call fclose(), and the FILE blocks in which _IOSTRG is set are not on the regular list, so an exit() in a signal handler will never see them. In other words, this test is always true. >filbuf.c: > if (iop->_flag&(_IOSTRG|_IOEOF)) This one is probably actually necessary in the current implementation. (Actually, there is an easy hack to make it unnecessary.) The last time I actually ran `grep _IOSTRG' on the source was for 4.1BSD, as I had just run into an interesting bug in (Gosling) Emacs. >To answer what the original poster probably wanted to know, _IOSTRG >indicates that the stream is a fake stream for I/O to a string: sprintf >or sscanf. As for what it actually *controls*, Chris is almost >correct; I think _doprnt doesn't check this flag at all [VAX version], >and (bug alert!) neither does _flsbuf. Right. This led to the bug I was investigating when I found this. >If you sprintf more than 32K, sprintf will make mistakes. Initially, >the mistakes are (relatively) benign (the sprintffed output past 32K >gets stuffed in malloc()ed memory which is then lost), but if you push >it to 40K, it will start flushing stuff to a random file descriptor .... I was using a routine called `sprintfl', which took a length parameter and `guaranteed' not to write past the end of that length. The code was (before varargs cleanup) char * sprintfl(buf, len, fmt, a1) char *buf; int len; char *fmt; { FILE f; f._flag = _IOWRT|_IOSTRG; f._ptr = buf; f._cnt = len - 1; _doprnt(fmt, &a1, &f); putc('\0', &f); buf[len-1] = '\0'; return (buf); } It misbehaved terribly (along the lines der Mouse indicated). The `fix' was to change the first code line to f._flag = _IOSTRG; ! -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris