Memory leak in __res_vinit when gethostbyname is invoked?

198 views
Skip to first unread message

Freepine

unread,
Jan 21, 2010, 9:54:34 PM1/21/10
to andro...@googlegroups.com
Hi,

In Bionic C, if we invokes gethostbyname from the thread first time, _res_thread_get actually invokes res_ninit twice (one in _res_thread_alloc and another in the function itself) which would result in malloc twice in __res_vinit, /platform/bionic/libc/netbsd/resolv/res_init.c:269 and memory leaks.

I have a draft fix as following, where I moved the conditional check above preinit block, so res_ndestroy could be executed first if __res_vinit is entered second time, and free the memory chunk allocated in the previous call. Please kindly review it, thanks.

==============================================
diff --git a/libc/netbsd/resolv/res_init.c b/libc/netbsd/resolv/res_init.c
index 751603d..2c80b28 100644
--- a/libc/netbsd/resolv/res_init.c
+++ b/libc/netbsd/resolv/res_init.c
@@ -223,6 +223,9 @@ __res_vinit(res_state statp, int preinit) {
        char dnsProperty[PROP_VALUE_MAX];
 #endif

+        if ((statp->options & RES_INIT) != 0U)
+                res_ndestroy(statp);
+
        if (!preinit) {
                statp->retrans = RES_TIMEOUT;
                statp->retry = RES_DFLRETRY;
@@ -230,9 +233,6 @@ __res_vinit(res_state statp, int preinit) {
                statp->id = res_randomid();
        }

-       if ((statp->options & RES_INIT) != 0U)
-               res_ndestroy(statp);
-
        memset(u, 0, sizeof(u));
 #ifdef USELOOPBACK
        u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
diff --git a/libc/netbsd/resolv/res_state.c b/libc/netbsd/resolv/res_state.c
index 3a2301d..92bfab3 100644
--- a/libc/netbsd/resolv/res_state.c
+++ b/libc/netbsd/resolv/res_state.c
@@ -53,6 +53,7 @@ static _res_thread*
 _res_thread_alloc(void)
 {
     _res_thread*  rt = malloc(sizeof(*rt));
+    memset(rt, 0, sizeof(*rt));

     if (rt) {
         rt->_h_errno = 0;



Or maybe I can simply remove below two statements from _res_thread_get to avoid res_ninit twice? Which one is better? Personally I would prefer the first one as it also works when res_ninit invoked multiple times somewhere else.

===============
diff --git a/libc/netbsd/resolv/res_state.c b/libc/netbsd/resolv/res_state.c
index 92bfab3..8d33ea4 100644
--- a/libc/netbsd/resolv/res_state.c
+++ b/libc/netbsd/resolv/res_state.c
@@ -113,8 +113,6 @@ _res_thread_get(void)
         if ((rt = _res_thread_alloc()) == NULL) {
             return NULL;
         }
-        rt->_h_errno = 0;
-        rt->_serial = 0;
         pthread_setspecific( _res_key, rt );
     }
     /* Check the serial value for any chanes to net.* properties. */==


BTW: I submitted the issue 6134 several days ago but seems no feedback there, so I re-post the issue here:)

-Freepine

Reply all
Reply to author
Forward
0 new messages