pidgin: 6de8f788: Use ref-counting to prevent a crash if r...

sadrul at pidgin.im sadrul at pidgin.im
Thu Dec 11 16:10:38 EST 2008


-----------------------------------------------------------------
Revision: 6de8f788571b507b2c76125cc65f88db49c60790
Ancestor: 2b3429067be9bc2eb9be9e8deeeac9c35001f61d
Author: sadrul at pidgin.im
Date: 2008-12-11T21:10:57
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/6de8f788571b507b2c76125cc65f88db49c60790

Modified files:
        libpurple/account.c

ChangeLog: 

Use ref-counting to prevent a crash if request-auth callbacks are called
immediately/synchronously. Thanks a lot to Florian Qu?ze for the initial
patch, and for testing the alternate fix. Closes #7604.

-------------- next part --------------
============================================================
--- libpurple/account.c	d59224845aa473b7aeb4ebc5dbbb0a1dccfa21c3
+++ libpurple/account.c	2d7a963bb5083959e2898e9ad47a372d6c125309
@@ -75,6 +75,7 @@ typedef struct
 	gpointer userdata;
 	PurpleAccountRequestAuthorizationCb auth_cb;
 	PurpleAccountRequestAuthorizationCb deny_cb;
+	guint ref;
 } PurpleAccountRequestInfo;
 
 static PurpleAccountUiOps *account_ui_ops = NULL;
@@ -1211,6 +1212,18 @@ purple_account_request_add(PurpleAccount
 		ui_ops->request_add(account, remote_user, id, alias, message);
 }
 
+static PurpleAccountRequestInfo *
+purple_account_request_info_unref(PurpleAccountRequestInfo *info)
+{
+	if (--info->ref)
+		return info;
+
+	/* TODO: This will leak info->user_data, but there is no callback to just clean that up */
+	g_free(info->user);
+	g_free(info);
+	return NULL;
+}
+
 static void
 purple_account_request_close_info(PurpleAccountRequestInfo *info)
 {
@@ -1221,11 +1234,7 @@ purple_account_request_close_info(Purple
 	if (ops != NULL && ops->close_account_request != NULL)
 		ops->close_account_request(info->ui_handle);
 
-	/* TODO: This will leak info->user_data, but there is no callback to just clean that up */
-
-	g_free(info->user);
-	g_free(info);
-
+	purple_account_request_info_unref(info);
 }
 
 void
@@ -1278,8 +1287,7 @@ request_auth_cb(void *data)
 	purple_signal_emit(purple_accounts_get_handle(),
 			"account-authorization-granted", info->account, info->user);
 
-	g_free(info->user);
-	g_free(info);
+	purple_account_request_info_unref(info);
 }
 
 static void
@@ -1294,8 +1302,7 @@ request_deny_cb(void *data)
 	purple_signal_emit(purple_accounts_get_handle(),
 			"account-authorization-denied", info->account, info->user);
 
-	g_free(info->user);
-	g_free(info);
+	purple_account_request_info_unref(info);
 }
 
 void *
@@ -1332,11 +1339,18 @@ purple_account_request_authorization(Pur
 		info->deny_cb   = deny_cb;
 		info->userdata  = user_data;
 		info->user      = g_strdup(remote_user);
+		info->ref       = 2;  /* We hold an extra ref to make sure info remains valid
+		                         if any of the callbacks are called synchronously. We
+		                         unref it after the function call */
+
 		info->ui_handle = ui_ops->request_authorize(account, remote_user, id, alias, message,
 							    on_list, request_auth_cb, request_deny_cb, info);
 
-		handles = g_list_append(handles, info);
-		return info->ui_handle;
+		info = purple_account_request_info_unref(info);
+		if (info) {
+			handles = g_list_append(handles, info);
+			return info->ui_handle;
+		}
 	}
 
 	return NULL;


More information about the Commits mailing list