[comp.bugs.sys5] Serious bug in stdio on some ``System V'' derivatives

bin@minster.york.ac.uk (09/29/88)

Some System V systems, particularly those that include Berkeley networking,
are afflicted with a fairly nasty bug if the following happens.

<stdio.h.>:
	#define	_NFILE	20
<sys/param.h>:
	#define	NOFILE	30	/* anything > _NFILE */
and <stdio.h> again:
	#define _bufend(p)      _bufendtab[(p)->_file]

The trouble starts if a process opens some files with stdio, and others
directly, using open, pipe, or whatever.  Eventually, a stdio file
can be opened that has a _file >= _NFILE.  There are two problems:

	1. _file == _NFILE
		System V stdio uses this as a flag for IO to and from
		a string buffer; this convention is used by sprintf/sscanf.
		The internal buffering functions, _filbuf and _flsbuf,
		will then mess up buffer filling & flushing.

		Actually, there is another bug here:  _filbuf
		incorrectly makes a system call for string IO,
		which can slow sscanf down a little...

	2. _file > _NFILE
		_bufendtab is declared _bufendtab[_NFILE+1], to allow
		for the convention mentioned above.  The array entries
		are supposed to give the pointer to the end of the buffer
		for each stdio file.  Unfortunately, in order to allow
		older binary files to be used without recompilation,
		this pointer was not made part of the FILE structure.
		Provided NOFILE <= _NFILE, this is merely inelegant.
		Otherwise, it is a disaster, since the pointer value
		for _file > _NFILE will be whatever junk appears after
		the array in memory, often the stdio buffers.

Berkeley networking has nothing to do with this, of course, except
that ``System V'' systems that have sockets (and perhaps NFS) seem
to be more likely to increase NOFILE.

It's interesting that programs affected by this will often work quite
differently under the control of a debugger.  Careless debuggers leave
some extra file descriptors open to the executable image, core file, etc.

Berkeley systems, including Suns, are unaffected, since they sensibly
put the extra value in the FILE structure.

rpw3@amdcad.AMD.COM (Rob Warnock) (10/05/88)

In article <591535074.12423@minster.york.ac.uk> bin@minster.york.ac.uk writes:
+---------------
| Berkeley networking has nothing to do with this, of course, except
| that ``System V'' systems that have sockets (and perhaps NFS) seem
| to be more likely to increase NOFILE...
| Berkeley systems, including Suns, are unaffected, since they sensibly
| put the extra value in the FILE structure.
+---------------

Well, having just done a port of the Berkeley networking code into a System-V,
let me point out that whoever ported your stuff had to fix a related problem
I ran into over and over, a problem due to the *#&^$*#& "_bufendtab[]" which
(as you say) does not exist in Berkeley systems:

If you do an "freopen" of a file descriptor which is already open in
an stdio stream, since the "_bufendtab[]" is indexed by *file descriptor*
your new FILE will stuff *its* bufend over the *old* FILE's. This will
cause illegal memory references and other assorted mayhem if you ever
use the old FILE for anything!  (*Hack* solution: change all cases of such
"freopen(s,...) to "freopen(dup(s),...)", so as to get a new bufend entry.)

Having _bufend be in a table indexed by f.d. instead of FILE* was  a ghastly
mistake. I certainly hope more recent versions of System-V have fixed it.


Rob Warnock
Systems Architecture Consultant

UUCP:	  {amdcad,fortune,sun}!redwood!rpw3
ATTmail:  !rpw3
DDD:	  (415)572-2607
USPS:	  627 26th Ave, San Mateo, CA  94403

john@polyof.UUCP ( John Buck ) (10/07/88)

Aside from the NOFILE vs. _NFILE size problems, fdopen() introduces
another little (possibly confusing) side effect to stdio.  Namely,

	fd = open("somefile", 2);
	...
	fp1 = fdopen(fd, "r");
	fp2 = fdopen(fd, "r+");

	Problem here is that fp1 and fp2 SHARE the same IO buffer, since
the way "stdio" determines the buffer is via the bufendtab[file_descriptor].
If two "file handles" (FILE *'s) are open to the same file descriptor,
buffer clashing will occur.

This is something to watch out for, because I have been stung by it a couple
of times.

john@polyof.poly.edu
john@polygraf.bitnet
john@[128.238.10.100]   (polyof.poly.edu)

trixie!polyof!john