From 543e6569a3f4730f3105379cc946cc6b54525179 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Fri, 24 Nov 2023 14:13:10 +0200
Subject: [PATCH 1/4] Turn tail recursion into iteration in
 CommitTransactionCommand()

Usually the compiler will optimize away the tail recursion anyway, but
if it doesn't, you can drive the function into stack overflow. For
example:

    (n=1000000; printf "BEGIN;"; for ((i=1;i<=$n;i++)); do printf "SAVEPOINT s$i;"; done; printf "ERROR; COMMIT;") | psql >/dev/null

Report by Egor Chindyaskin and Alexander Lakhin.

Discussion: https://www.postgresql.org/message-id/1672760457.940462079%40f306.i.mail.ru
---
 src/backend/access/transam/xact.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 536edb3792..e16b73a9f1 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -3033,12 +3033,15 @@ RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
 void
 CommitTransactionCommand(void)
 {
-	TransactionState s = CurrentTransactionState;
+	TransactionState s;
 	SavedTransactionCharacteristics savetc;
 
+recurse:
+	s = CurrentTransactionState;
 	/* Must save in case we need to restore below */
 	SaveTransactionCharacteristics(&savetc);
 
+	s = CurrentTransactionState;
 	switch (s->blockState)
 	{
 			/*
@@ -3226,8 +3229,7 @@ CommitTransactionCommand(void)
 			 */
 		case TBLOCK_SUBABORT_END:
 			CleanupSubTransaction();
-			CommitTransactionCommand();
-			break;
+			goto recurse;
 
 			/*
 			 * As above, but it's not dead yet, so abort first.
@@ -3235,8 +3237,7 @@ CommitTransactionCommand(void)
 		case TBLOCK_SUBABORT_PENDING:
 			AbortSubTransaction();
 			CleanupSubTransaction();
-			CommitTransactionCommand();
-			break;
+			goto recurse;
 
 			/*
 			 * The current subtransaction is the target of a ROLLBACK TO
-- 
2.39.2

