[Pkg-telepathy-maintainers] Bug#495199: telepathy-haze: often crashes on connection errors, such as an incorrect password

Will Thompson will at willthompson.co.uk
Fri Aug 15 09:43:17 UTC 2008


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
-------------- next part --------------
commit 41a82cc4e33b646630203223c204ace8ae1d9f49
Author: Will Thompson <will.thompson at collabora.co.uk>
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;


More information about the Pkg-telepathy-maintainers mailing list