This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

scandir leak patch



Attached is the current newlib scandir.c with the "goto cleanup_and_bail" modification from the RTEMS one plus an explicit check for 0 entries from the fstat.

How does this look?

2008-11-24 Joel Sherrill <joel.sherrill@oarcorp.com>

* libc/posix/scandir.c: Fix memory leaks.

--
Joel Sherrill, Ph.D.             Director of Research & Development
joel.sherrill@OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
  Support Available             (256) 722-9985


Index: scandir.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/posix/scandir.c,v
retrieving revision 1.6
diff -u -r1.6 scandir.c
--- scandir.c	31 Oct 2008 21:03:41 -0000	1.6
+++ scandir.c	24 Nov 2008 19:32:17 -0000
@@ -79,17 +79,22 @@
 	long arraysz;
 	DIR *dirp;
 
+	dirp = NULL;
+	names = NULL;
+
 	if ((dirp = opendir(dirname)) == NULL)
 		return(-1);
 #ifdef HAVE_DD_LOCK
 	__lock_acquire_recursive(dirp->dd_lock);
 #endif
-	if (fstat(dirp->dd_fd, &stb) < 0) {
-#ifdef HAVE_DD_LOCK
-		__lock_release_recursive(dirp->dd_lock);
-#endif
-		return(-1);
-	}
+	if (fstat(dirp->dd_fd, &stb) < 0)
+		goto cleanup_and_bail;
+
+	/*
+ 	 * If there were no directory entries, then bail.
+ 	 */
+	if (stb.st_size == 0)
+		goto cleanup_and_bail;
 
 	/*
 	 * estimate the array size by taking the size of the directory file
@@ -97,12 +102,8 @@
 	 */
 	arraysz = (stb.st_size / 24);
 	names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
-	if (names == NULL) {
-#ifdef HAVE_DD_LOCK
-		__lock_release_recursive(dirp->dd_lock);
-#endif
-		return(-1);
-	}
+	if (names == NULL)
+		goto cleanup_and_bail;
 
 	nitems = 0;
 	while ((d = readdir(dirp)) != NULL) {
@@ -112,12 +113,8 @@
 		 * Make a minimum size copy of the data
 		 */
 		p = (struct dirent *)malloc(DIRSIZ(d));
-		if (p == NULL) {
-#ifdef HAVE_DD_LOCK
-			__lock_release_recursive(dirp->dd_lock);
-#endif
-			return(-1);
-		}
+		if (p == NULL)
+			goto cleanup_and_bail;
 		p->d_ino = d->d_ino;
 		p->d_reclen = d->d_reclen;
 #ifdef _DIRENT_HAVE_D_NAMLEN
@@ -131,21 +128,13 @@
 		 * realloc the maximum size.
 		 */
 		if (++nitems >= arraysz) {
-			if (fstat(dirp->dd_fd, &stb) < 0) {
-#ifdef HAVE_DD_LOCK
-				__lock_release_recursive(dirp->dd_lock);
-#endif
-				return(-1);	/* just might have grown */
-			}
+			if (fstat(dirp->dd_fd, &stb) < 0)
+				goto cleanup_and_bail;
 			arraysz = stb.st_size / 12;
 			names = (struct dirent **)realloc((char *)names,
 				arraysz * sizeof(struct dirent *));
-			if (names == NULL) {
-#ifdef HAVE_DD_LOCK
-				__lock_release_recursive(dirp->dd_lock);
-#endif
-				return(-1);
-			}
+			if (names == NULL)
+				goto cleanup_and_bail;
 		}
 		names[nitems-1] = p;
 	}
@@ -157,6 +146,24 @@
 	__lock_release_recursive(dirp->dd_lock);
 #endif
 	return(nitems);
+
+cleanup_and_bail:
+
+	if ( dirp )
+		closedir( dirp );
+
+	if ( names ) {
+		int i;
+		for (i=0; i < nitems; i++ )
+			free( names[i] );
+		free( names );
+	}
+
+#ifdef HAVE_DD_LOCK
+	__lock_release_recursive(dirp->dd_lock);
+#endif
+
+	return(-1);
 }
 
 /*

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]