talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 9bb650480eaeb335c51b3127f78f0e71db309df6
parent 82d9246acc83aa8e94e9d1585b38f7ee4cc8180d
Author: Andrej Kacian <ticho@claws-mail.org>
Date:   Fri, 26 Apr 2019 00:28:58 +0200

Free a memory leak in libetpan-backed server connections

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.

Diffstat:
Msrc/common/session.c | 2+-
Msrc/common/socket.c | 10++++++----
Msrc/common/socket.h | 2+-
Msrc/etpan/imap-thread.c | 18++++++++++++++----
Msrc/etpan/nntp-thread.c | 18++++++++++++++----
Msrc/plugins/notification/notification_lcdproc.c | 4++--
6 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/src/common/session.c b/src/common/session.c @@ -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); diff --git a/src/common/socket.c b/src/common/socket.c @@ -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); diff --git a/src/common/socket.h b/src/common/socket.h @@ -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); diff --git a/src/etpan/imap-thread.c b/src/etpan/imap-thread.c @@ -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); } diff --git a/src/etpan/nntp-thread.c b/src/etpan/nntp-thread.c @@ -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); } diff --git a/src/plugins/notification/notification_lcdproc.c b/src/plugins/notification/notification_lcdproc.c @@ -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; } }