Free a memory leak in libetpan-backed server connections
authorAndrej Kacian <ticho@claws-mail.org>
Thu, 25 Apr 2019 22:28:58 +0000 (00:28 +0200)
committerAndrej Kacian <ticho@claws-mail.org>
Sat, 4 May 2019 14:44:09 +0000 (16:44 +0200)
We create a connection using our sock_connect() and let
libetpan take over managing it. However, libetpan only
needs the socket file descriptor, so we need to get rid
of the rest of the returned SockInfo struct.

src/common/session.c
src/common/socket.c
src/common/socket.h
src/etpan/imap-thread.c
src/etpan/nntp-thread.c
src/plugins/notification/notification_lcdproc.c

index a6f19ea80bbaf396e9bfa5b95ff950b7f868521b..2da8e16c2ed26af03159f89514aab2005bc1417a 100644 (file)
@@ -388,7 +388,7 @@ static gint session_close(Session *session)
        }
 
        if (session->sock) {
-               sock_close(session->sock);
+               sock_close(session->sock, TRUE);
                session->sock = NULL;
                session->state = SESSION_DISCONNECTED;
                debug_print("session (%p): closed\n", session);
index fdc15894ef66f53dd40117bd2d577741892b7fcb..c5814d777bc6bcca7b91715c3e0d89232dac55fd 100644 (file)
@@ -1486,7 +1486,7 @@ Single-byte send() and recv().
        return bp - buf;
 }
 
-gint sock_close(SockInfo *sock)
+gint sock_close(SockInfo *sock, gboolean close_fd)
 {
        gint ret;
 
@@ -1503,11 +1503,13 @@ gint sock_close(SockInfo *sock)
                g_source_remove(sock->g_source);
        sock->g_source = 0;
 #endif
+       if (close_fd) {
 #ifdef G_OS_WIN32
-       shutdown(sock->sock, 1); /* complete transfer before close */
-       ret = closesocket(sock->sock);
+               shutdown(sock->sock, 1); /* complete transfer before close */
+               ret = closesocket(sock->sock);
 #else
-       ret = fd_close(sock->sock); 
+               ret = fd_close(sock->sock);
+       }
 #endif
 
        g_free(sock->canonical_name);
index 005f5a0ad6c314c11bdae06f31c1bfba4346bbb5..a1b17e5391cfbfe087e105ad117b0d814651999e 100644 (file)
@@ -108,7 +108,7 @@ gint sock_connect_async_cancel              (gint id);
 gint sock_read         (SockInfo *sock, gchar *buf, gint len);
 gint sock_write                (SockInfo *sock, const gchar *buf, gint len);
 gint sock_write_all    (SockInfo *sock, const gchar *buf, gint len);
-gint sock_close                (SockInfo *sock);
+gint sock_close                (SockInfo *sock, gboolean close_fd);
 
 /* Functions to directly work on FD.  They are needed for pipes */
 gint fd_connect_unix   (const gchar *path);
index b68e303f9ea98bec91a77350cee9d6a7ad24a487..eeccac793caeb20721c65ef9bf350904f8f85418 100644 (file)
@@ -78,17 +78,22 @@ static int do_mailimap_socket_connect(mailimap * imap, const char * server,
                return MAILIMAP_ERROR_CONNECTION_REFUSED;
 
        if (proxy_connect(sock, server, port, proxy_info) < 0) {
-               sock_close(sock);
+               sock_close(sock, TRUE);
                return MAILIMAP_ERROR_CONNECTION_REFUSED;
        }
 
        stream = mailstream_socket_open_timeout(sock->sock,
                        imap->imap_timeout);
        if (stream == NULL) {
-               sock_close(sock);
+               sock_close(sock, TRUE);
                return MAILIMAP_ERROR_MEMORY;
        }
 
+       /* Libetpan now has the socket fd, and we're not interested in
+        * rest of the SockInfo struct. Let's free it, while not touching
+        * the socket itself. */
+       sock_close(sock, FALSE);
+
        return mailimap_connect(imap, stream);
 }
 
@@ -119,17 +124,22 @@ static int do_mailimap_ssl_connect_with_callback(mailimap * imap, const char * s
        if (proxy_connect(sock, server, port, proxy_info) < 0) {
                debug_print("Can not make proxy connection via %s:%d\n",
                                proxy_info->proxy_host, proxy_info->proxy_port);
-               sock_close(sock);
+               sock_close(sock, TRUE);
                return MAILIMAP_ERROR_CONNECTION_REFUSED;
        }
 
        stream = mailstream_ssl_open_with_callback_timeout(sock->sock,
                        imap->imap_timeout, callback, data);
        if (stream == NULL) {
-               sock_close(sock);
+               sock_close(sock, TRUE);
                return MAILIMAP_ERROR_SSL;
        }
 
+       /* Libetpan now has the socket fd, and we're not interested in
+        * rest of the SockInfo struct. Let's free it, while not touching
+        * the socket itself. */
+       sock_close(sock, FALSE);
+
        return mailimap_connect(imap, stream);
 }
 
index bf67cd004c0d2fb781392a81e41e8d840394741c..5f5b31b593a1ad5c2a4066ea872023c251ce6b99 100644 (file)
@@ -78,17 +78,22 @@ static int do_newsnntp_socket_connect(newsnntp * imap, const char * server,
                return NEWSNNTP_ERROR_CONNECTION_REFUSED;
 
        if (proxy_connect(sock, server, port, proxy_info) < 0) {
-               sock_close(sock);
+               sock_close(sock, TRUE);
                return NEWSNNTP_ERROR_CONNECTION_REFUSED;
        }
 
        stream = mailstream_socket_open_timeout(sock->sock,
                        imap->nntp_timeout);
        if (stream == NULL) {
-               sock_close(sock);
+               sock_close(sock, TRUE);
                return NEWSNNTP_ERROR_MEMORY;
        }
 
+       /* Libetpan now has the socket fd, and we're not interested in
+        * rest of the SockInfo struct. Let's free it, while not touching
+        * the socket itself. */
+       sock_close(sock, FALSE);
+
        return newsnntp_connect(imap, stream);
 }
 
@@ -114,17 +119,22 @@ static int do_newsnntp_ssl_connect_with_callback(newsnntp * imap, const char * s
                return NEWSNNTP_ERROR_CONNECTION_REFUSED;
 
        if (proxy_connect(sock, server, port, proxy_info) < 0) {
-               sock_close(sock);
+               sock_close(sock, TRUE);
                return NEWSNNTP_ERROR_CONNECTION_REFUSED;
        }
 
        stream = mailstream_ssl_open_with_callback_timeout(sock->sock,
                        imap->nntp_timeout, callback, data);
        if (stream == NULL) {
-               sock_close(sock);
+               sock_close(sock, TRUE);
                return NEWSNNTP_ERROR_SSL;
        }
 
+       /* Libetpan now has the socket fd, and we're not interested in
+        * rest of the SockInfo struct. Let's free it, while not touching
+        * the socket itself. */
+       sock_close(sock, FALSE);
+
        return newsnntp_connect(imap, stream);
 }
 
index 874caa7fce11f88416ce510a36bb4b0fdf9616ee..0f131d107abcc758eb1e86e74c6e34b2b5e481be 100644 (file)
@@ -61,7 +61,7 @@ void notification_lcdproc_connect(void)
   if(sock == NULL || sock->state == CONN_FAILED) {
     debug_print("Could not connect to LCDd\n");
     if(sock && sock->state == CONN_FAILED) {
-      sock_close(sock);
+      sock_close(sock, TRUE);
       sock = NULL;
     }
     return;
@@ -116,7 +116,7 @@ void notification_lcdproc_disconnect(void)
 #ifndef G_OS_WIN32
     shutdown(sock->sock, SHUT_RDWR);
 #endif
-    sock_close(sock);
+    sock_close(sock, TRUE);
     sock = NULL;
   }
 }