[comp.lang.c] Network Software Bug

souza@telesoft.UUCP (Steve Souza @eldest) (11/24/87)

We've seen a strange symptom in a network software package that, until 
SunOS version 3.4 (on a Sun 160), functioned normally.  

The basic scenario is a server process that accepts network socket
connection requests from a client process, executes a specified command,
and sends the output back to the client process, not unlike the r-shell 
software.

Under 3.4, huge pieces of /etc/group randomly appear in the output
of the client process, often in a repeating pattern of usernames.

Here are excerpts from the code [pardon the crudity of the i/o -- I'm
still working on it!]:
----------------------------------------------------------------Server:
write_output(s, cmd)
int s;		/* `s' is a socket of type AF_INET */
char *cmd;	/* `cmd' is the command line */
{
	FILE *pp;
	char buf[BUFSIZ];

	pp = popen(cmd, "r");

	...

	while (fgets(buf, BUFSIZ, pp) != NULL)
		if (write(s, buf, BUFSIZ) < 0) {
			pclose(pp);
			return(1<<8);
		}
	return(pclose(pp));
}
----------------------------------------------------------------Client:
read_output()
{
	/* `sock' is the other end of the AF_INET socket */
	extern int sock;	
	char obuf[BUFSIZ];

	while (1) {
		if (read(sock, obuf, BUFSIZ) > 0)
			write(1, obuf, strlen(obuf));
		else
			break;
	}
}
-----------------------------------------------------------------------
Anybody know of changes in 3.4 that might cause this?  We don't run
YP, BTW.  Also, the server process calls initgroups().  Could that 
be related?

Any suggestions would be m u c h appreciated...

Thanks!

Steve Souza				...sdcsvax!telesoft!souza
TELESOFT Inc., San Diego, CA		(619)457-2700 x277

chris@mimsy.UUCP (11/25/87)

In article <126@telesoft.UUCP> souza@telesoft.UUCP (Steve Souza @eldest) writes:
>	FILE *pp;
>	char buf[BUFSIZ];
>	...
>	while (fgets(buf, BUFSIZ, pp) != NULL)
>		if (write(s, buf, BUFSIZ) < 0) {
>			pclose(pp);
>			return(1<<8);
>		}

>	char obuf[BUFSIZ];
>
>	while (1) {
>		if (read(sock, obuf, BUFSIZ) > 0)
>			write(1, obuf, strlen(obuf));
>		else
>			break;
>	}

0. fgets gets a NUL-terminated string, which may be < BUFSIZ bytes.
   Writing BUFSIZ bytes down `s' writes whatever other trash is in
   buf[].
1. read returns a byte count, which you ignore.  It does not guarantee
   that obuf will be NUL-terminated, yet you call strlen on obuf.
2. There is no guarantee that the read(sock) will always read
   exactly as many bytes as the write(s) wrote.  It could read
   fewer; it could read more (although in this case it cannot,
   since writer writes BUFSIZ and reader reads BUFSIZ).
3. You neither check nor cast to void the return value from write(1).
   Clearly you have not used lint.

Four bugs in 15 lines of code ... not bad.  (Well, there were more
lines in the original posting, but they had more bugs too.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris