dovecot-1.2: pgsql: Don't write to freed memory if transaction i...

dovecot at dovecot.org dovecot at dovecot.org
Sun Jan 18 00:21:35 EET 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/81fd92599c7f
changeset: 8650:81fd92599c7f
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Jan 17 17:21:29 2009 -0500
description:
pgsql: Don't write to freed memory if transaction is aborted while SQL commands are being executed.

diffstat:

1 file changed, 21 insertions(+), 4 deletions(-)
src/lib-sql/driver-pgsql.c |   25 +++++++++++++++++++++----

diffs (97 lines):

diff -r 67c08c386702 -r 81fd92599c7f src/lib-sql/driver-pgsql.c
--- a/src/lib-sql/driver-pgsql.c	Sat Jan 17 13:56:24 2009 -0500
+++ b/src/lib-sql/driver-pgsql.c	Sat Jan 17 17:21:29 2009 -0500
@@ -70,6 +70,7 @@ struct pgsql_queue {
 
 struct pgsql_transaction_context {
 	struct sql_transaction_context ctx;
+	int refcount;
 
 	sql_commit_callback_t *callback;
 	void *context;
@@ -845,7 +846,19 @@ driver_pgsql_transaction_begin(struct sq
 
 	ctx = i_new(struct pgsql_transaction_context, 1);
 	ctx->ctx.db = db;
+	ctx->refcount = 1;
 	return &ctx->ctx;
+}
+
+static void
+driver_pgsql_transaction_unref(struct pgsql_transaction_context *ctx)
+{
+	i_assert(ctx->refcount > 0);
+	if (--ctx->refcount > 0)
+		return;
+
+	i_free(ctx->first_update);
+	i_free(ctx);
 }
 
 static void
@@ -871,13 +884,14 @@ driver_pgsql_transaction_commit(struct s
 		callback(ctx->error, context);
 		if (ctx->opened)
 			sql_exec(_ctx->db, "ROLLBACK");
-		i_free(ctx);
+		driver_pgsql_transaction_unref(ctx);
 		return;
 	}
 
 	if (!ctx->opened) {
 		/* nothing done */
 		ctx->callback(NULL, ctx->context);
+		driver_pgsql_transaction_unref(ctx);
 		return;
 	}
 
@@ -897,6 +911,7 @@ driver_pgsql_transaction_commit_s(struct
 	struct sql_result *result;
 
 	if (ctx->first_update != NULL) {
+		ctx->refcount++;
 		sql_query(_ctx->db, ctx->first_update,
 			  transaction_update_callback, ctx);
 		i_free_and_null(ctx->first_update);
@@ -919,7 +934,7 @@ driver_pgsql_transaction_commit_s(struct
 		sql_result_free(result);
 	}
 
-	i_free(ctx);
+	driver_pgsql_transaction_unref(ctx);
 	return *error_r == NULL ? 0 : -1;
 }
 
@@ -931,8 +946,7 @@ driver_pgsql_transaction_rollback(struct
 
 	if (ctx->opened)
 		sql_exec(_ctx->db, "ROLLBACK");
-	i_free(ctx->first_update);
-	i_free(ctx);
+	driver_pgsql_transaction_unref(ctx);
 }
 
 static void
@@ -944,6 +958,7 @@ transaction_update_callback(struct sql_r
 		ctx->failed = TRUE;
 		ctx->error = sql_result_get_error(result);
 	}
+	driver_pgsql_transaction_unref(ctx);
 }
 
 static void
@@ -963,12 +978,14 @@ driver_pgsql_update(struct sql_transacti
 			return;
 		}
 		ctx->opened = TRUE;
+		ctx->refcount += 2;
 		sql_query(_ctx->db, "BEGIN", transaction_update_callback, ctx);
 		sql_query(_ctx->db, ctx->first_update,
 			  transaction_update_callback, ctx);
 		i_free_and_null(ctx->first_update);
 	}
 
+	ctx->refcount++;
 	driver_pgsql_query_full(_ctx->db, query,
 				transaction_update_callback, ctx, FALSE);
 }


More information about the dovecot-cvs mailing list