eio__scandir() leaks memory when opendir() returns NULL. It sets
req->result == -1 but doesn't free the memory it allocates.

Attached are two patches (different takes, same solution) that fix
that: one tries to be brief, the other minimally intrusive. The brief
one has a return statement in the middle of the function. Not all
people like that, hence the two takes. Pick the one you like best.

Apropos, two things I noticed about eio__scandir() is that it:

1. doesn't set req->errorno when opendir() fails (both patches fix that), and

2. uses readdir(), which is not guaranteed to be thread-safe. glibc
wraps it in a mutex and I think sunos's libc does so too but
readdir_r() is what should be used, really.
From a2a801cacd2c26ec7bf9bce00cee68f0317bc2c6 Mon Sep 17 00:00:00 2001
From: Ben Noordhuis <i...@bnoordhuis.nl>
Date: Mon, 12 Sep 2011 16:29:56 +0200
Subject: [PATCH] Fix memory leak in eio__scandir()

---
 eio.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/eio.c b/eio.c
index d59db3e..c62535c 100644
--- a/eio.c
+++ b/eio.c
@@ -1737,6 +1737,9 @@ eio__scandir (eio_req *req, etp_worker *self)
   dirp = opendir (req->ptr1);
 #endif
 
+  if (!dirp)
+    req->errorno = errno;
+
   if (req->flags & EIO_FLAG_PTR1_FREE)
     free (req->ptr1);
 
@@ -1929,6 +1932,15 @@ eio__scandir (eio_req *req, etp_worker *self)
           }
 #endif
       }
+
+  if (req->result == -1)
+    {
+      req->flags &= ~(EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE);
+      free(req->ptr1);
+      free(req->ptr2);
+      req->ptr1 = NULL;
+      req->ptr2 = NULL;
+    }
 }
 
 /*****************************************************************************/
-- 
1.7.6

From b2347858500431caff9cb66491cab10e9c6302c3 Mon Sep 17 00:00:00 2001
From: Ben Noordhuis <i...@bnoordhuis.nl>
Date: Mon, 12 Sep 2011 17:14:46 +0200
Subject: [PATCH] Fix memory leak in eio__scandir()

---
 eio.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/eio.c b/eio.c
index d59db3e..6add505 100644
--- a/eio.c
+++ b/eio.c
@@ -1738,7 +1738,17 @@ eio__scandir (eio_req *req, etp_worker *self)
 #endif
 
   if (req->flags & EIO_FLAG_PTR1_FREE)
-    free (req->ptr1);
+    {
+      req->flags &= ~EIO_FLAG_PTR1_FREE;
+      free (req->ptr1);
+      req->ptr1 = NULL;
+    }
+
+  if (!dirp)
+    {
+      req->errorno = errno;
+      return;
+    }
 
   req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE;
   req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0;
-- 
1.7.6

_______________________________________________
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev

Reply via email to