From f8d0a82bf9501e1c5efe40e0f55d0c063858f7b4 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 17 Aug 2005 22:14:34 +0000
Subject: [PATCH] Avoid an Assert failure if OuterUserId hasn't been set yet
 during AbortTransaction.  This can happen if a backend's InitPostgres
 transaction fails (eg, because the given username is invalid).  Per Alvaro.

---
 src/backend/access/transam/xact.c |  8 ++++----
 src/backend/utils/init/miscinit.c | 19 +++++++++++++++++--
 src/include/miscadmin.h           |  3 ++-
 3 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 5323cefe0e7..737d1f3252a 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.212 2005/08/08 19:17:22 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.213 2005/08/17 22:14:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1877,8 +1877,8 @@ AbortTransaction(void)
 
 	/*
 	 * Reset user id which might have been changed transiently.  We cannot
-	 * use s->currentUser, but must get the session outer-level userid from
-	 * miscinit.c.
+	 * use s->currentUser, since it may not be set yet; instead rely on
+	 * internal state of miscinit.c.
 	 *
 	 * (Note: it is not necessary to restore session authorization here
 	 * because that can only be changed via GUC, and GUC will take care of
@@ -1886,7 +1886,7 @@ AbortTransaction(void)
 	 * DEFINER function could send control here with the wrong current
 	 * userid.)
 	 */
-	SetUserId(GetOuterUserId());
+	AtAbort_UserId();
 
 	/*
 	 * do abort processing
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index f6c50438e03..148e2609734 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.148 2005/07/31 17:19:19 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.149 2005/08/17 22:14:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -286,7 +286,7 @@ make_absolute_path(const char *path)
  * OuterUserId is the current user ID in effect at the "outer level" (outside
  * any transaction or function).  This is initially the same as SessionUserId,
  * but can be changed by SET ROLE to any role that SessionUserId is a
- * member of.  We store this mainly so that AbortTransaction knows what to
+ * member of.  We store this mainly so that AtAbort_UserId knows what to
  * reset CurrentUserId to.
  *
  * CurrentUserId is the current effective user ID; this is the one to use
@@ -496,6 +496,21 @@ InitializeSessionUserIdStandalone(void)
 }
 
 
+/*
+ * Reset effective userid during AbortTransaction
+ *
+ * This is essentially SetUserId(GetOuterUserId()), but without the Asserts.
+ * The reason is that if a backend's InitPostgres transaction fails (eg,
+ * because an invalid user name was given), we have to be able to get through
+ * AbortTransaction without asserting.
+ */
+void
+AtAbort_UserId(void)
+{
+	CurrentUserId = OuterUserId;
+}
+
+
 /*
  * Change session auth ID while running
  *
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 5697a691e63..04cab28e39d 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.178 2005/07/25 22:12:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.179 2005/08/17 22:14:34 tgl Exp $
  *
  * NOTES
  *	  some of the information in this file should be moved to other files.
@@ -235,6 +235,7 @@ extern Oid GetOuterUserId(void);
 extern Oid GetSessionUserId(void);
 extern void InitializeSessionUserId(const char *rolename);
 extern void InitializeSessionUserIdStandalone(void);
+extern void AtAbort_UserId(void);
 extern void SetSessionAuthorization(Oid userid, bool is_superuser);
 extern Oid GetCurrentRoleId(void);
 extern void SetCurrentRoleId(Oid roleid, bool is_superuser);
-- 
GitLab