Memory Leak in rcp

Steven M. Schultz sms at wlv.imsd.contel.com
Wed Sep 6 15:26:12 AEST 1989


Subject: Memory Leak in rcp -r
Index:	bin/rcp.c 2.10BSD

Description:
	rcp does not handle recursive directory copies correctly,
	causing large amounts of memory to be malloc'd but never 
	freed.  on sufficiently large copies 'rcp' complains about
	"no memory".

Repeat-By:
	Do a "rcp -r" on a large directory hierarchy.

	Or, inspect the code.  The old version used 'static' variables
	rather than automatics to hold the size and address of the memory
	malloc'd to hold pathnames.  Also, the 'cursize' variable was
	never set, it remained at zero, causing a complete pathname
	buffer to be allocated for EACH file transferred.

Fix:
	Apply this patch to rcp.c (version 5.20).  If you do not have
	this version of rcp.c, i can mail it to you.

*** rcp.c.old	Tue Sep  5 22:19:07 1989
--- rcp.c	Tue Sep  5 09:10:53 1989
***************
*** 600,608 ****
  	off_t i, j;
  	char ch, *targ, *why;
  	int amt, count, exists, first, mask, mode;
! 	int ofd, setimes, targisdir, wrerr;
  	off_t size;
! 	char *np, *vect[1], buf[BUFSIZ], *malloc();
  
  #define	atime	tv[0]
  #define	mtime	tv[1]
--- 600,608 ----
  	off_t i, j;
  	char ch, *targ, *why;
  	int amt, count, exists, first, mask, mode;
! 	int ofd, setimes, targisdir, wrerr, cursize = 0;
  	off_t size;
! 	char *np, *vect[1], buf[BUFSIZ], *malloc(), *namebuf = NULL;
  
  #define	atime	tv[0]
  #define	mtime	tv[1]
***************
*** 624,631 ****
  		targisdir = 1;
  	for (first = 1;; first = 0) {
  		cp = buf;
! 		if (read(rem, cp, 1) <= 0)
  			return;
  		if (*cp++ == '\n')
  			SCREWUP("unexpected <newline>");
  		do {
--- 624,634 ----
  		targisdir = 1;
  	for (first = 1;; first = 0) {
  		cp = buf;
! 		if (read(rem, cp, 1) <= 0) {
! 			if (namebuf)
! 				free(namebuf);
  			return;
+ 		}
  		if (*cp++ == '\n')
  			SCREWUP("unexpected <newline>");
  		do {
***************
*** 645,650 ****
--- 648,655 ----
  		}
  		if (buf[0] == 'E') {
  			(void)write(rem, "", 1);
+ 			if (namebuf)
+ 				free(namebuf);
  			return;
  		}
  
***************
*** 699,712 ****
  		if (*cp++ != ' ')
  			SCREWUP("size not delimited");
  		if (targisdir) {
- 			static char *namebuf;
- 			static int cursize;
  			int need;
  
  			need = strlen(targ) + strlen(cp) + 250;
  			if (need > cursize) {
  				if (!(namebuf = malloc((u_int)need)))
  					error("out of memory\n");
  			}
  			(void)sprintf(namebuf, "%s%s%s", targ,
  			    *targ ? "/" : "", cp);
--- 704,718 ----
  		if (*cp++ != ' ')
  			SCREWUP("size not delimited");
  		if (targisdir) {
  			int need;
  
  			need = strlen(targ) + strlen(cp) + 250;
  			if (need > cursize) {
+ 				if (namebuf)
+ 					free(namebuf);
  				if (!(namebuf = malloc((u_int)need)))
  					error("out of memory\n");
+ 				cursize = need;
  			}
  			(void)sprintf(namebuf, "%s%s%s", targ,
  			    *targ ? "/" : "", cp);



More information about the Comp.bugs.2bsd mailing list