From owner-freebsd-bugs Sun Sep 13 20:40:04 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id UAA16470 for freebsd-bugs-outgoing; Sun, 13 Sep 1998 20:40:04 -0700 (PDT) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id UAA16463 for ; Sun, 13 Sep 1998 20:40:03 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.8/8.8.5) id UAA03668; Sun, 13 Sep 1998 20:40:01 -0700 (PDT) Received: from whistle.com (s205m131.whistle.com [207.76.205.131]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id UAA16001 for ; Sun, 13 Sep 1998 20:30:58 -0700 (PDT) (envelope-from archie@whistle.com) Received: (from smap@localhost) by whistle.com (8.7.5/8.6.12) id UAA16722 for ; Sun, 13 Sep 1998 20:30:43 -0700 (PDT) Received: from bubba.whistle.com(207.76.205.7) by whistle.com via smap (V1.3) id sma016720; Sun Sep 13 20:30:41 1998 Received: (from archie@localhost) by bubba.whistle.com (8.8.7/8.6.12) id UAA15858; Sun, 13 Sep 1998 20:30:41 -0700 (PDT) Message-Id: <199809140330.UAA15858@bubba.whistle.com> Date: Sun, 13 Sep 1998 20:30:41 -0700 (PDT) From: Archie Cobbs Reply-To: archie@whistle.com To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.2 Subject: bin/7923: scandir(3) does not clean up after itself if it fails Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 7923 >Category: bin >Synopsis: scandir(3) does not clean up after itself if it fails >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun Sep 13 20:40:01 PDT 1998 >Last-Modified: >Originator: Archie Cobbs >Organization: Whistle Communications, Inc. >Release: FreeBSD 2.2.6-RELEASE i386 >Environment: FreeBSD 3.0-current circa July 13, 1998 20:00 GMT >Description: 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! >How-To-Repeat: >Fix: 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 03:29:09 @@ -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,36 @@ * 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 */ + if (nitems + 1 >= arraysz) { + struct dirent **names2; + + if (fstat(dirp->dd_fd, &stb) < 0) { + free(p); + goto fail; /* just might have grown */ + } arraysz = stb.st_size / 12; - names = (struct dirent **)realloc((char *)names, + names2 = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *)); - if (names == NULL) - return(-1); + if (names2 == NULL) { + free(p); + goto fail; + } + names = names2; } - 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; } /* >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message