From 5b613d117468dfd95f7de0f022628d150b7c9107 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 31 Aug 2011 12:41:48 +0300 Subject: [PATCH] gobex: Protect against user callback freeing internal objects A user callback could potentially do things like g_obex_cancel_request or g_obex_unref while we are inside the IO watch callback. It is therefore important to ensure that we are in a consistent state when the user callback returns. --- gobex/gobex.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/gobex/gobex.c b/gobex/gobex.c index 97fb3c37b..bfcf8b8c0 100644 --- a/gobex/gobex.c +++ b/gobex/gobex.c @@ -625,9 +625,14 @@ static void handle_response(GObex *obex, GError *err, GObexPacket *rsp) err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED, "The operation was cancelled"); - if (p->rsp_func) + if (p->rsp_func) { p->rsp_func(obex, err, rsp, p->rsp_data); + /* Check if user callback removed the request */ + if (p != obex->pending_req) + return; + } + if (p->cancelled) g_error_free(err); @@ -807,19 +812,24 @@ static gboolean incoming_data(GIOChannel *io, GIOCondition cond, if (pkt == NULL) goto failed; + /* Protect against user callback freeing the object */ + g_obex_ref(obex); + if (obex->pending_req) handle_response(obex, NULL, pkt); else handle_request(obex, pkt); + obex->rx_data = 0; + + g_obex_unref(obex); + if (err != NULL) g_error_free(err); if (pkt != NULL) g_obex_packet_free(pkt); - obex->rx_data = 0; - return TRUE; failed: @@ -828,12 +838,17 @@ failed: obex->io_source = 0; obex->rx_data = 0; + /* Protect against user callback freeing the object */ + g_obex_ref(obex); + if (obex->pending_req) handle_response(obex, err, NULL); if (obex->disconn_func) obex->disconn_func(obex, err, obex->disconn_func_data); + g_obex_unref(obex); + g_error_free(err); return FALSE; -- 2.47.3