From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14210 invoked by alias); 16 Sep 2003 23:43:53 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 14193 invoked from network); 16 Sep 2003 23:43:52 -0000 Received: from unknown (HELO sunsite.ms.mff.cuni.cz) (195.113.19.66) by sources.redhat.com with SMTP; 16 Sep 2003 23:43:52 -0000 Received: from sunsite.ms.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8) with ESMTP id h8GLfwlt020012; Tue, 16 Sep 2003 23:41:58 +0200 Received: (from jakub@localhost) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8/Submit) id h8GLfwAU020010; Tue, 16 Sep 2003 23:41:58 +0200 Date: Tue, 16 Sep 2003 23:43:00 -0000 From: Jakub Jelinek To: Ulrich Drepper , Roland McGrath Cc: Glibc hackers Subject: [PATCH] scandir cleanups Message-ID: <20030916214158.GV12344@sunsite.ms.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2003-09/txt/msg00062.txt.bz2 Hi! If one of the scandir* callbacks (select or cmp) either pthread_exit's, throws an exception or calls some cancellation point, dp might be unclosed and some memory might leak. 2003-09-17 Jakub Jelinek * dirent/scandir.c: Include bits/libc-lock.h. (struct scandir_cancel_struct): New type. (cancel_handler): New function. (SCANDIR): Add __libc_cleanup_{push,pop}, save state into scandir_cancel_struct. --- libc/dirent/scandir.c.jj 2003-06-11 22:03:31.000000000 -0400 +++ libc/dirent/scandir.c 2003-09-16 16:12:49.000000000 -0400 @@ -20,6 +20,7 @@ #include #include #include +#include #ifndef SCANDIR #define SCANDIR scandir @@ -27,6 +28,29 @@ #define DIRENT_TYPE struct dirent #endif +#ifndef SCANDIR_CANCEL +#define SCANDIR_CANCEL +struct scandir_cancel_struct +{ + DIR *dp; + void *v; + size_t cnt; +}; + +static void +cancel_handler (void *arg) +{ + struct scandir_cancel_struct *cp = arg; + size_t i; + void **v = cp->v; + + for (i = 0; i < cp->cnt; ++i) + free (v[i]); + free (v); + (void) __closedir (cp->dp); +} +#endif + int SCANDIR (dir, namelist, select, cmp) @@ -37,7 +61,8 @@ SCANDIR (dir, namelist, select, cmp) { DIR *dp = __opendir (dir); DIRENT_TYPE **v = NULL; - size_t vsize = 0, i; + size_t vsize = 0; + struct scandir_cancel_struct c; DIRENT_TYPE *d; int save; @@ -47,7 +72,11 @@ SCANDIR (dir, namelist, select, cmp) save = errno; __set_errno (0); - i = 0; + c.dp = dp; + c.v = NULL; + c.cnt = 0; + __libc_cleanup_push (cancel_handler, &c); + while ((d = READDIR (dp)) != NULL) { int use_it = select == NULL; @@ -69,7 +98,7 @@ SCANDIR (dir, namelist, select, cmp) /* Ignore errors from select or readdir */ __set_errno (0); - if (__builtin_expect (i == vsize, 0)) + if (__builtin_expect (c.cnt == vsize, 0)) { DIRENT_TYPE **new; if (vsize == 0) @@ -80,6 +109,7 @@ SCANDIR (dir, namelist, select, cmp) if (new == NULL) break; v = new; + c.v = (void *) v; } dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d; @@ -87,7 +117,7 @@ SCANDIR (dir, namelist, select, cmp) if (vnew == NULL) break; - v[i++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize); + v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize); } } @@ -95,23 +125,24 @@ SCANDIR (dir, namelist, select, cmp) { save = errno; - while (i > 0) - free (v[--i]); + while (c.cnt > 0) + free (v[--c.cnt]); free (v); - - i = -1; + c.cnt = -1; } else { /* Sort the list if we have a comparison function to sort with. */ if (cmp != NULL) - qsort (v, i, sizeof (*v), cmp); + qsort (v, c.cnt, sizeof (*v), cmp); *namelist = v; } + __libc_cleanup_pop (0); + (void) __closedir (dp); __set_errno (save); - return i; + return c.cnt; } Jakub