Package: telepathy-haze Version: 0.2.0-1 Severity: important Tags: patch The currently released version of telepathy-haze may access (and possibly try to free) already-released memory after a connection error occurs. This will be fixed in the next release, but the attached patch fixes the problem with only a few lines of non-boilerplate and -comment code. (It replaces using a flag in libpurple which does not actually have the right semantics with a new flag which does.)
It would be great if this could make it into Lenny! Thanks, Will -- System Information: Debian Release: lenny/sid APT prefers testing APT policy: (900, 'testing'), (800, 'unstable'), (700, 'experimental') Architecture: i386 (i686) Kernel: Linux 2.6.25-2-686 (SMP w/1 CPU core) Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash
commit 41a82cc4e33b646630203223c204ace8ae1d9f49 Author: Will Thompson <[EMAIL PROTECTED]> Date: Thu Aug 14 11:37:38 2008 +0100 Keep track of whether purple_account_disconnect needs to be called. This fixes #14933. When libpurple reports a connection error, it schedules an idle callback for purple_account_disconnect. Haze's implementation of TpBaseConnection->shut_down checked PurpleAccount->disconnecting before calling purple_account_disconnect, but that flag is only set once purple_account_disconnect is actually called. So purple_account_disconnect would be called twice, and if you got unlucky the account have been freed before the second call, causing catastrophe. --- src/connection.c | 24 +++++++++++++++++++++++- 1 files changed, 23 insertions(+), 1 deletions(-) diff --git a/src/connection.c b/src/connection.c index 14a1051..c0863e1 100644 --- a/src/connection.c +++ b/src/connection.c @@ -63,6 +63,11 @@ typedef struct _HazeConnectionPrivate HazeProtocolInfo *protocol_info; + /* Set if purple_account_disconnect has been called or is scheduled to be + * called, so should not be called again. + */ + gboolean disconnecting; + gboolean dispose_has_run; } HazeConnectionPrivate; @@ -115,10 +120,17 @@ haze_report_disconnect_reason (PurpleConnection *gc, const char *text) { PurpleAccount *account = purple_connection_get_account (gc); + HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (account); + HazeConnectionPrivate *priv = HAZE_CONNECTION_GET_PRIVATE (conn); TpBaseConnection *base_conn = ACCOUNT_GET_TP_BASE_CONNECTION (account); TpConnectionStatusReason tp_reason; + /* When a connection error is reported by libpurple, an idle callback to + * purple_account_disconnect is added. + */ + priv->disconnecting = TRUE; + switch (reason) { case PURPLE_CONNECTION_ERROR_NETWORK_ERROR: @@ -196,8 +208,12 @@ void disconnected_cb (PurpleConnection *pc) { PurpleAccount *account = purple_connection_get_account (pc); + HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (account); + HazeConnectionPrivate *priv = HAZE_CONNECTION_GET_PRIVATE (conn); TpBaseConnection *base_conn = ACCOUNT_GET_TP_BASE_CONNECTION (account); + priv->disconnecting = TRUE; + if(base_conn->status != TP_CONNECTION_STATUS_DISCONNECTED) { tp_base_connection_change_status (base_conn, @@ -326,8 +342,12 @@ static void _haze_connection_shut_down (TpBaseConnection *base) { HazeConnection *self = HAZE_CONNECTION(base); - if(!self->account->disconnecting) + HazeConnectionPrivate *priv = HAZE_CONNECTION_GET_PRIVATE (self); + if(!priv->disconnecting) + { + priv->disconnecting = TRUE; purple_account_disconnect(self->account); + } } /* Must be in the same order as HazeListHandle in connection.h */ @@ -452,6 +472,8 @@ haze_connection_constructor (GType type, priv->dispose_has_run = FALSE; + priv->disconnecting = FALSE; + _create_account (self); return (GObject *)self;