_IOSTRG in stdio.h

Chris Torek chris at mimsy.UUCP
Tue Nov 15 23:54:47 AEST 1988


>In article <14413 at 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 at mcgill-vision.UUCP> mouse at 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 at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list