dovecot-2.2: lib-imap-urlauth: Fixed deinitialization of the URL...

dovecot at dovecot.org dovecot at dovecot.org
Tue May 21 22:55:45 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/5a36736445e9
changeset: 16385:5a36736445e9
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Tue May 21 22:55:23 2013 +0300
description:
lib-imap-urlauth: Fixed deinitialization of the URLAUTH fetch handler.
Added reference counting to make sure callbacks will not deinitialize the
handler prematurely.

diffstat:

 src/imap/cmd-urlfetch.c                   |   1 -
 src/lib-imap-urlauth/imap-urlauth-fetch.c |  57 +++++++++++++++++++++++++++---
 src/lib-imap-urlauth/imap-urlauth-fetch.h |   5 +-
 3 files changed, 52 insertions(+), 11 deletions(-)

diffs (192 lines):

diff -r 9dbcd10cac28 -r 5a36736445e9 src/imap/cmd-urlfetch.c
--- a/src/imap/cmd-urlfetch.c	Tue May 21 22:55:17 2013 +0300
+++ b/src/imap/cmd-urlfetch.c	Tue May 21 22:55:23 2013 +0300
@@ -284,7 +284,6 @@
 
 	if ((last && cmd->state == CLIENT_COMMAND_STATE_WAIT_EXTERNAL) ||
 	    ret < 0) {
-		ctx->ufetch = NULL;
 		cmd_urlfetch_finish(cmd);
 		client_command_free(&cmd);
 	}
diff -r 9dbcd10cac28 -r 5a36736445e9 src/lib-imap-urlauth/imap-urlauth-fetch.c
--- a/src/lib-imap-urlauth/imap-urlauth-fetch.c	Tue May 21 22:55:17 2013 +0300
+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c	Tue May 21 22:55:23 2013 +0300
@@ -22,6 +22,7 @@
 };
 
 struct imap_urlauth_fetch {
+	unsigned int refcount;
 	struct imap_urlauth_context *uctx;
 
 	imap_urlauth_fetch_callback_t *callback;
@@ -100,17 +101,28 @@
 	struct imap_urlauth_fetch *ufetch;
 
 	ufetch = i_new(struct imap_urlauth_fetch, 1);
+	ufetch->refcount = 1;
 	ufetch->uctx = uctx;
 	ufetch->callback = callback;
 	ufetch->context = context;
 	return ufetch;
 }
 
-void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch)
+static void imap_urlauth_fetch_ref(struct imap_urlauth_fetch *ufetch)
+{
+	i_assert(ufetch->refcount > 0);
+	ufetch->refcount++;
+}
+
+static void imap_urlauth_fetch_unref(struct imap_urlauth_fetch **_ufetch)
 {
 	struct imap_urlauth_fetch *ufetch = *_ufetch;
 
+	i_assert(ufetch->refcount > 0);
+
 	*_ufetch = NULL;
+	if (--ufetch->refcount > 0)
+		return;
 
 	imap_urlauth_fetch_abort(ufetch);
 
@@ -120,6 +132,11 @@
 	i_free(ufetch);
 }
 
+void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch)
+{
+	imap_urlauth_fetch_unref(_ufetch);
+}
+
 static void
 imap_urlauth_fetch_error(struct imap_urlauth_fetch *ufetch, const char *url,
 			 enum imap_urlauth_fetch_flags url_flags,
@@ -232,6 +249,8 @@
 	}
 
 	if (!success && ret < 0) {
+		if (mpurl != NULL)
+			imap_msgpart_url_free(&mpurl);
 		ufetch->pending_requests--;
 		(void)ufetch->callback(NULL, TRUE, ufetch->context);
 		imap_urlauth_fetch_fail(ufetch);
@@ -292,6 +311,8 @@
 	ufetch->waiting_local = FALSE;
 	ufetch->pending_requests--;
 
+	imap_urlauth_fetch_ref(ufetch);
+
 	if (!ufetch->failed) {
 		bool last = ufetch->pending_requests == 0 || reply == NULL;
 		ret = ufetch->callback(reply, last, ufetch->context);
@@ -305,8 +326,8 @@
 	} else if (ret == 0) {
 		ufetch->waiting_service = TRUE;
 	}
-	if (ret != 0)
-		imap_urlauth_fetch_deinit(&ufetch);
+	
+	imap_urlauth_fetch_unref(&ufetch);
 	return ret;
 }
 
@@ -319,6 +340,7 @@
 	struct mail_user *mail_user = uctx->user;
 	struct imap_url *imap_url;
 	const char *error, *errormsg;
+	int ret = 0;
 
 	/* parse the url */
 	if (imap_url_parse(url, NULL, url_parse_flags, &imap_url, &error) < 0) {
@@ -327,13 +349,17 @@
 		if (mail_user->mail_debug)
 			i_debug("%s", errormsg);
 		ufetch->pending_requests++;
+		imap_urlauth_fetch_ref(ufetch);
 		imap_urlauth_fetch_error(ufetch, url, url_flags, errormsg);
+		imap_urlauth_fetch_unref(&ufetch);
 		return 1;
 	}
 
 	ufetch->failed = FALSE;
 	ufetch->pending_requests++;
 
+	imap_urlauth_fetch_ref(ufetch);
+
 	/* if access user and target user match, handle fetch request locally */
 	if (imap_url->userid != NULL &&
 		strcmp(mail_user->username, imap_url->userid) == 0) {
@@ -364,17 +390,22 @@
 
 	/* create request for url */
 	if (imap_url != NULL && imap_url->userid != NULL) {
+		i_assert(uctx->conn != NULL);
 		(void)imap_urlauth_request_new(uctx->conn, imap_url->userid,
 				url, url_flags,
 				imap_urlauth_fetch_request_callback, ufetch);
 		i_assert(uctx->conn != NULL);
 		if (imap_urlauth_connection_connect(uctx->conn) < 0)
-			return -1;
+			ret = -1;
 	}
-	return (ufetch->pending_requests > 0 ? 0 : 1);
+	if (ret >= 0)
+		ret = (ufetch->pending_requests > 0 ? 0 : 1);
+
+	imap_urlauth_fetch_unref(&ufetch);
+	return ret;
 }
 
-bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch)
+static bool imap_urlauth_fetch_do_continue(struct imap_urlauth_fetch *ufetch)
 {
 	struct imap_urlauth_fetch_url *url, *url_next;
 	int ret;
@@ -390,7 +421,7 @@
 		ufetch->waiting_service = FALSE;
 		imap_urlauth_connection_continue(ufetch->uctx->conn);
 		return ufetch->pending_requests > 0;
-	} 
+	}
 
 	/* finished local request */
 	if (ufetch->local_url != NULL) {
@@ -457,3 +488,15 @@
 
 	return ufetch->pending_requests > 0;
 }
+
+bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch)
+{
+	bool pending;
+
+	imap_urlauth_fetch_ref(ufetch);
+	pending = imap_urlauth_fetch_do_continue(ufetch);
+	imap_urlauth_fetch_unref(&ufetch);
+
+	return pending;
+}
+
diff -r 9dbcd10cac28 -r 5a36736445e9 src/lib-imap-urlauth/imap-urlauth-fetch.h
--- a/src/lib-imap-urlauth/imap-urlauth-fetch.h	Tue May 21 22:55:17 2013 +0300
+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.h	Tue May 21 22:55:23 2013 +0300
@@ -33,8 +33,7 @@
    for next reply, 0 if not all data was processed, and -1 for error. If a
    callback returns 0, imap_urlauth_fetch_continue() must be called once
    new replies may be processed. If this is the last request to yield a reply,
-   argument last is TRUE. The callback must not call
-   imap_urlauth_fetch_deinit(). */
+   argument last is TRUE. */
 typedef int
 imap_urlauth_fetch_callback_t(struct imap_urlauth_fetch_reply *reply,
 			      bool last, void *context);
@@ -42,7 +41,7 @@
 struct imap_urlauth_fetch *
 imap_urlauth_fetch_init(struct imap_urlauth_context *uctx,
 			imap_urlauth_fetch_callback_t *callback, void *context);
-void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch);
+void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **ufetch);
 
 int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url,
 			   enum imap_urlauth_fetch_flags url_flags);


More information about the dovecot-cvs mailing list