Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 Sep 1998 14:10:01 -0700 (PDT)
From:      Archie Cobbs <archie@whistle.com>
To:        freebsd-bugs@FreeBSD.ORG
Subject:   Re: bin/7923: scandir(3) does not clean up after itself if it fails
Message-ID:  <199809142110.OAA09416@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/7923; it has been noted by GNATS.

From: Archie Cobbs <archie@whistle.com>
To: freebsd-gnats-submit@freebsd.org
Cc:  Subject: Re: bin/7923: scandir(3) does not clean up after itself if it fails
Date: Mon, 14 Sep 1998 14:02:39 -0700 (PDT)

 Wait! There's also another bug in that sometime (esp when scanning /proc)
 it fails to realloc() the correct amount. Please use this patch instead.
 
 Thanks,
 -Archie
 
 ___________________________________________________________________________
 Archie Cobbs   *   Whistle Communications, Inc.  *   http://www.whistle.com
 
 Index: scandir.c
 ===================================================================
 RCS file: /cvs/freebsd/src/lib/libc/gen/scandir.c,v
 retrieving revision 1.3
 diff -c -u -r1.3 scandir.c
 --- scandir.c	1995/05/30 05:40:23	1.3
 +++ scandir.c	1998/09/14 21:02:08
 @@ -66,8 +66,8 @@
  	int (*select) __P((struct dirent *));
  	int (*dcomp) __P((const void *, const void *));
  {
 -	register struct dirent *d, *p, **names;
 -	register size_t nitems;
 +	register struct dirent *d, *p, **names = NULL;
 +	register size_t nitems = 0;
  	struct stat stb;
  	long arraysz;
  	DIR *dirp;
 @@ -75,7 +75,7 @@
  	if ((dirp = opendir(dirname)) == NULL)
  		return(-1);
  	if (fstat(dirp->dd_fd, &stb) < 0)
 -		return(-1);
 +		goto fail;
  
  	/*
  	 * estimate the array size by taking the size of the directory file
 @@ -84,9 +84,8 @@
  	arraysz = (stb.st_size / 24);
  	names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
  	if (names == NULL)
 -		return(-1);
 +		goto fail;
  
 -	nitems = 0;
  	while ((d = readdir(dirp)) != NULL) {
  		if (select != NULL && !(*select)(d))
  			continue;	/* just selected names */
 @@ -95,7 +94,7 @@
  		 */
  		p = (struct dirent *)malloc(DIRSIZ(d));
  		if (p == NULL)
 -			return(-1);
 +			goto fail;
  		p->d_fileno = d->d_fileno;
  		p->d_type = d->d_type;
  		p->d_reclen = d->d_reclen;
 @@ -105,22 +104,33 @@
  		 * Check to make sure the array has space left and
  		 * realloc the maximum size.
  		 */
 -		if (++nitems >= arraysz) {
 -			if (fstat(dirp->dd_fd, &stb) < 0)
 -				return(-1);	/* just might have grown */
 -			arraysz = stb.st_size / 12;
 -			names = (struct dirent **)realloc((char *)names,
 -				arraysz * sizeof(struct dirent *));
 -			if (names == NULL)
 -				return(-1);
 +		if (nitems >= arraysz) {
 +			const int inc = 10;	/* increase by this much */
 +			struct dirent **names2;
 +
 +			names2 = (struct dirent **)realloc((char *)names,
 +				(arraysz + inc) * sizeof(struct dirent *));
 +			if (names2 == NULL) {
 +				free(p);
 +				goto fail;
 +			}
 +			names = names2;
 +			arraysz += inc;
  		}
 -		names[nitems-1] = p;
 +		names[nitems++] = p;
  	}
  	closedir(dirp);
  	if (nitems && dcomp != NULL)
  		qsort(names, nitems, sizeof(struct dirent *), dcomp);
  	*namelist = names;
  	return(nitems);
 +
 +fail:
 +	while (nitems > 0)
 +		free(names[--nitems]);
 +	free(names);
 +	closedir(dirp);
 +	return -1;
  }
  
  /*

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199809142110.OAA09416>