summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1998-10-07 01:30:02 +0000
committerjulian <julian@FreeBSD.org>1998-10-07 01:30:02 +0000
commit7ae06315295ae0d16f7a0aeec3eaae9ae43ab2e1 (patch)
tree076b06da3b09c3b9ab27255a43d088587cf655b8 /lib
parent6d718e342c3ef45c17af49a7b5e6b95c88440b75 (diff)
downloadFreeBSD-src-7ae06315295ae0d16f7a0aeec3eaae9ae43ab2e1.zip
FreeBSD-src-7ae06315295ae0d16f7a0aeec3eaae9ae43ab2e1.tar.gz
Fix a memory leak
PR: 7923 Submitted by: Archie Cobbs <archie@whistle.com> The scandir() function returns -1 if it fails. In many cases when this happens, it does not free the memory that it allocated, resulting in a memory leak, or close the directory opened with opendir(). BAD DOG, BAD!
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/gen/scandir.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
index 8a8b7d2..5c64b29 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -66,8 +66,8 @@ scandir(dirname, namelist, select, dcomp)
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 @@ scandir(dirname, namelist, select, dcomp)
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 @@ scandir(dirname, namelist, select, dcomp)
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 @@ scandir(dirname, namelist, select, dcomp)
*/
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 @@ scandir(dirname, namelist, select, dcomp)
* 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 **)reallocf((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;
}
/*
OpenPOWER on IntegriCloud