Package: pidgin
Version: 2.10.6-2
Severity: normal
Tags: upstream patch

Hi,

I reviewed the pidgin source for memory leaks.  I have used cppcheck
to locate possible leaks and then manually tried to verify them.  I am
sending my findings with patches that demonstrate possible ways of
fixing the leaks.
  While I believe them to be good, I have not tested them (not even
compiled tested).  Nor do I have a thorough understanding of the
internals, so a second review of them would be appreciated.

I suspect there is a leak more in zephyr.c[1] that I did not fix.  It
appears in zephyr_join_chat, where classname and instname is mixed
between "must-free" and "must-not-free" strings[2].

The patches are based on top of the Debian git repository (the one
published by the PTS).

Thanks you for considering,
~Niels

[1] libpurple/protocols/zephyr/zephyr.c

[2] Example:

"""
        if (!instname || !strlen(instname))
                instname = "*";
                ^^^^^^^^^^^^^^
"""
constant string must not be freed.

"""
        if (!g_ascii_strcasecmp(instname,"%host%"))
                instname = g_strdup(zephyr->ourhost);
        if (!g_ascii_strcasecmp(instname,"%canon%"))
                instname = g_strdup(zephyr->ourhostcanon);
"""
                           ^^^^^^^^
Result of g_strdup must be passed to g_free eventually.
>From 934829009f8919cc557a405ca76b8a29ce57a375 Mon Sep 17 00:00:00 2001
From: Niels Thykier <[email protected]>
Date: Wed, 12 Dec 2012 13:04:29 +0100
Subject: [PATCH 1/6] auth_scram.c: Fix memleak in jabber_scram_calc_proofs

Signed-off-by: Niels Thykier <[email protected]>
---
 libpurple/protocols/jabber/auth_scram.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/libpurple/protocols/jabber/auth_scram.c b/libpurple/protocols/jabber/auth_scram.c
index a971f09..7263f50 100644
--- a/libpurple/protocols/jabber/auth_scram.c
+++ b/libpurple/protocols/jabber/auth_scram.c
@@ -183,8 +183,13 @@ jabber_scram_calc_proofs(JabberScramData *data, GString *salt, guint iterations)
 	memset(pass->str, 0, pass->allocated_len);
 	g_string_free(pass, TRUE);
 
-	if (!salted_password)
+	if (!salted_password) {
+		g_free(server_key);
+		g_free(client_signature);
+		g_free(stored_key);
+		g_free(client_key);
 		return FALSE;
+	}
 
 	/* client_key = HMAC(salted_password, "Client Key") */
 	hmac(data->hash, client_key, salted_password, "Client Key");
-- 
1.7.10.4

>From 4d5c9911b4848b6b79dc0c41d1728706fd79fa56 Mon Sep 17 00:00:00 2001
From: Niels Thykier <[email protected]>
Date: Wed, 12 Dec 2012 13:05:59 +0100
Subject: [PATCH 2/6] oob.c: Fix memleak in jabber_oob_parse

Signed-off-by: Niels Thykier <[email protected]>
---
 libpurple/protocols/jabber/oob.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/libpurple/protocols/jabber/oob.c b/libpurple/protocols/jabber/oob.c
index 430d17a..0df745a 100644
--- a/libpurple/protocols/jabber/oob.c
+++ b/libpurple/protocols/jabber/oob.c
@@ -211,6 +211,7 @@ void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type,
 	jox = g_new0(JabberOOBXfer, 1);
 	if (!purple_url_parse(url, &jox->address, &jox->port, &jox->page, NULL, NULL)) {
 		g_free(url);
+		g_free(jox);
 		return;
 	}
 	g_free(url);
-- 
1.7.10.4

>From c9bf107c484a24ff7de35376ddaa1f322ce2e7fd Mon Sep 17 00:00:00 2001
From: Niels Thykier <[email protected]>
Date: Wed, 12 Dec 2012 13:12:00 +0100
Subject: [PATCH 3/6] myspace.c: Fix memleaks in msim_uri_handler

Signed-off-by: Niels Thykier <[email protected]>
---
 libpurple/protocols/myspace/myspace.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/libpurple/protocols/myspace/myspace.c b/libpurple/protocols/myspace/myspace.c
index 9cc52f5..d2f1a2a 100644
--- a/libpurple/protocols/myspace/myspace.c
+++ b/libpurple/protocols/myspace/myspace.c
@@ -3579,7 +3579,10 @@ msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params)
 	}
 
 	session = (MsimSession *)account->gc->proto_data;
-	g_return_val_if_fail(session != NULL, FALSE);
+	if (session == NULL) {
+		g_free(cid_str);
+		return FALSE;
+	}
 
 	/* Lookup userid to username. TODO: push this down, to IM sending/contact
 	 * adding functions. */
@@ -3596,7 +3599,7 @@ msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params)
 		g_free(cid_str);
 		return TRUE;
 	}
-
+	g_free(cid_str);
 	return FALSE;
 }
 
-- 
1.7.10.4

>From d1ecfa2bbdb37701c7fc245a84ae19580d89ae74 Mon Sep 17 00:00:00 2001
From: Niels Thykier <[email protected]>
Date: Wed, 12 Dec 2012 13:17:33 +0100
Subject: [PATCH 4/6] util.c: Fix win32-only leak in silcpurple_check_silc_dir

Signed-off-by: Niels Thykier <[email protected]>
---
 libpurple/protocols/silc/util.c   |    8 +++++++-
 libpurple/protocols/silc10/util.c |    7 +++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/libpurple/protocols/silc/util.c b/libpurple/protocols/silc/util.c
index 68eac32..c4f09cf 100644
--- a/libpurple/protocols/silc/util.c
+++ b/libpurple/protocols/silc/util.c
@@ -310,7 +310,13 @@ gboolean silcpurple_check_silc_dir(PurpleConnection *gc)
 
 	if (fd != -1)
 		close(fd);
-
+#ifdef _WIN32
+	/* on win32, we calloc pw so pass it to free
+	 * (see the getpwuid code below)
+	 * NB: cppcheck seems to get this wrong.
+	 */
+	free(pw);
+#endif
 	return TRUE;
 }
 
diff --git a/libpurple/protocols/silc10/util.c b/libpurple/protocols/silc10/util.c
index 792afde..5b80fc3 100644
--- a/libpurple/protocols/silc10/util.c
+++ b/libpurple/protocols/silc10/util.c
@@ -304,6 +304,13 @@ gboolean silcpurple_check_silc_dir(PurpleConnection *gc)
 	if (fd != -1)
 		close(fd);
 
+#ifdef _WIN32
+	/* on win32, we calloc pw so pass it to free
+	 * (see the getpwuid code below)
+	 * NB: cppcheck seems to get this wrong.
+	 */
+	free(pw);
+#endif
 	return TRUE;
 }
 
-- 
1.7.10.4

>From 0c6d721cccf24198d86e308a70a5790014a0173c Mon Sep 17 00:00:00 2001
From: Niels Thykier <[email protected]>
Date: Wed, 12 Dec 2012 13:20:06 +0100
Subject: [PATCH 5/6] yahoo_filexfer.c: Fix memleak in 
 yahoo_p2p_ft_HEAD_GET_cb

Signed-off-by: Niels Thykier <[email protected]>
---
 libpurple/protocols/yahoo/yahoo_filexfer.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/libpurple/protocols/yahoo/yahoo_filexfer.c b/libpurple/protocols/yahoo/yahoo_filexfer.c
index bf87dbe..2d7231c 100644
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c
+++ b/libpurple/protocols/yahoo/yahoo_filexfer.c
@@ -1422,6 +1422,7 @@ static void yahoo_p2p_ft_HEAD_GET_cb(gpointer data, gint source, PurpleInputCond
 		purple_debug_warning("yahoo","p2p-ft: Wrong HEAD/GET request from peer, disconnecting host\n");
 		purple_input_remove(xd->input_event);
 		purple_xfer_cancel_remote(xfer);
+		g_free(url_get);
 		g_free(url_head);
 		return;
 	}
-- 
1.7.10.4

>From 2e6535012e1856f8db68920e2739f6ae9d7f7466 Mon Sep 17 00:00:00 2001
From: Niels Thykier <[email protected]>
Date: Wed, 12 Dec 2012 13:38:56 +0100
Subject: [PATCH 6/6] zephyr.c: Fix multiple leaks (incomplete)

Fix some leaks in zephyr.c, but the fix is incomplete for
zephyr_action_get_subs_from_server, where there is still a leak
in some casess (see the FIXME).

Signed-off-by: Niels Thykier <[email protected]>
---
 libpurple/protocols/zephyr/zephyr.c |   22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/libpurple/protocols/zephyr/zephyr.c b/libpurple/protocols/zephyr/zephyr.c
index 69c7113..310cec5 100644
--- a/libpurple/protocols/zephyr/zephyr.c
+++ b/libpurple/protocols/zephyr/zephyr.c
@@ -1495,6 +1495,7 @@ static void process_zsubs(zephyr_account *zephyr)
 		}
 		fclose(f);
 	}
+	g_free(fname);
 }
 
 static void process_anyone(PurpleConnection *gc)
@@ -2159,11 +2160,15 @@ static int zephyr_send_message(zephyr_account *zephyr,char* zclass, char* instan
 		len = strlen(zsendstr);
 		result = write(zephyr->totzc[ZEPHYR_FD_WRITE], zsendstr, len);
 		if (result != len) {
+			g_free(tzc_sig);
+			g_free(tzc_body);
 			g_free(zsendstr);
 			g_free(html_buf2);
 			g_free(html_buf);
 			return errno;
 		}
+		g_free(tzc_sig);
+		g_free(tzc_body);
 		g_free(zsendstr);
 	} else if (use_zeph02(zephyr)) {
 		ZNotice_t notice;
@@ -2583,19 +2588,24 @@ static PurpleCmdRet zephyr_purple_cmd_msg(PurpleConversation *conv,
 				      const char *cmd, char **args, char **error, void *data)
 {
 	char *recipient;
+	PurpleCmdRet ret;
 	zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data;
 	if (!g_ascii_strcasecmp(args[0],"*"))
 		return PURPLE_CMD_RET_FAILED;  /* "*" is not a valid argument */
 	else
 		recipient = local_zephyr_normalize(zephyr,args[0]);
 
-	if (strlen(recipient) < 1)
+	if (strlen(recipient) < 1) {
+		g_free(recipient);
 		return PURPLE_CMD_RET_FAILED; /* a null recipient is a chat message, not an IM */
+	}
 
 	if (zephyr_send_message(zephyr,"MESSAGE","PERSONAL",recipient,args[1],zephyr_get_signature(),""))
-		return PURPLE_CMD_RET_OK;
+		ret = PURPLE_CMD_RET_OK;
 	else
-		return PURPLE_CMD_RET_FAILED;
+		ret = PURPLE_CMD_RET_FAILED;
+	g_free(recipient);
+	return ret;
 }
 
 static PurpleCmdRet zephyr_purple_cmd_zlocate(PurpleConversation *conv,
@@ -2795,10 +2805,12 @@ static void zephyr_action_get_subs_from_server(PurplePluginAction *action)
 		title = g_strdup_printf("Server subscriptions for %s", zephyr->username);
 
 		if (zephyr->port == 0) {
+			g_free(title);
 			purple_debug_error("zephyr", "error while retrieving port\n");
 			return;
 		}
 		if ((retval = ZRetrieveSubscriptions(zephyr->port,&nsubs)) != ZERR_NONE) {
+			g_free(title);
 			/* XXX better error handling */
 			purple_debug_error("zephyr", "error while retrieving subscriptions from server\n");
 			return;
@@ -2807,6 +2819,7 @@ static void zephyr_action_get_subs_from_server(PurplePluginAction *action)
 			one = 1;
 			if ((retval = ZGetSubscriptions(&subs,&one)) != ZERR_NONE) {
 				/* XXX better error handling */
+				g_free(title);
 				purple_debug_error("zephyr", "error while retrieving individual subscription\n");
 				return;
 			}
@@ -2815,6 +2828,9 @@ static void zephyr_action_get_subs_from_server(PurplePluginAction *action)
 					       subs.zsub_recipient);
 		}
 		purple_notify_formatted(gc, title, title, NULL,  subout->str, NULL, NULL);
+		/* FIXME: subout is leaked, title and subout->str might is as well if
+		 * purple_notify_formatted does not "take the it ownership"...
+		 */
 	} else {
 		/* XXX fix */
 		purple_notify_error(gc,"","tzc doesn't support this action",NULL);
-- 
1.7.10.4

Reply via email to