aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-12-14 17:06:28 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-12-14 17:06:28 +0000
commit4ce6be4f5e1e4b0c89c5c8de179e3fa8216a7b54 (patch)
treeaa97d6ee837e6fa5834da31defd3fd69f872b8fc /src/backend/tcop/postgres.c
parent426292663acb30bdd8381eae4058e8ffcbf12162 (diff)
downloadpostgresql-4ce6be4f5e1e4b0c89c5c8de179e3fa8216a7b54.tar.gz
postgresql-4ce6be4f5e1e4b0c89c5c8de179e3fa8216a7b54.zip
Defend against crash while processing Describe Statement or Describe Portal
messages, when client attempts to execute these outside a transaction (start one) or in a failed transaction (reject message, except for COMMIT/ROLLBACK statements which we can handle). Per report from Francisco Figueiredo Jr.
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 3774c094b7b..5c0730050dd 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.470 2005/11/22 18:17:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.471 2005/12/14 17:06:27 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -1849,6 +1849,15 @@ exec_describe_statement_message(const char *stmt_name)
ListCell *l;
StringInfoData buf;
+ /*
+ * Start up a transaction command. (Note that this will normally change
+ * current memory context.) Nothing happens if we are already in one.
+ */
+ start_xact_command();
+
+ /* Switch back to message context */
+ MemoryContextSwitchTo(MessageContext);
+
/* Find prepared statement */
if (stmt_name[0] != '\0')
pstmt = FetchPreparedStatement(stmt_name, true);
@@ -1862,6 +1871,22 @@ exec_describe_statement_message(const char *stmt_name)
errmsg("unnamed prepared statement does not exist")));
}
+ /*
+ * If we are in aborted transaction state, we can't safely create a result
+ * tupledesc, because that needs catalog accesses. Hence, refuse to
+ * Describe statements that return data. (We shouldn't just refuse all
+ * Describes, since that might break the ability of some clients to issue
+ * COMMIT or ROLLBACK commands, if they use code that blindly Describes
+ * whatever it does.) We can Describe parameters without doing anything
+ * dangerous, so we don't restrict that.
+ */
+ if (IsAbortedTransactionBlockState() &&
+ PreparedStatementReturnsTuples(pstmt))
+ ereport(ERROR,
+ (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
+ errmsg("current transaction is aborted, "
+ "commands ignored until end of transaction block")));
+
if (whereToSendOutput != DestRemote)
return; /* can't actually do anything... */
@@ -1902,12 +1927,36 @@ exec_describe_portal_message(const char *portal_name)
{
Portal portal;
+ /*
+ * Start up a transaction command. (Note that this will normally change
+ * current memory context.) Nothing happens if we are already in one.
+ */
+ start_xact_command();
+
+ /* Switch back to message context */
+ MemoryContextSwitchTo(MessageContext);
+
portal = GetPortalByName(portal_name);
if (!PortalIsValid(portal))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_CURSOR),
errmsg("portal \"%s\" does not exist", portal_name)));
+ /*
+ * If we are in aborted transaction state, we can't run
+ * SendRowDescriptionMessage(), because that needs catalog accesses.
+ * Hence, refuse to Describe portals that return data. (We shouldn't just
+ * refuse all Describes, since that might break the ability of some
+ * clients to issue COMMIT or ROLLBACK commands, if they use code that
+ * blindly Describes whatever it does.)
+ */
+ if (IsAbortedTransactionBlockState() &&
+ portal->tupDesc)
+ ereport(ERROR,
+ (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
+ errmsg("current transaction is aborted, "
+ "commands ignored until end of transaction block")));
+
if (whereToSendOutput != DestRemote)
return; /* can't actually do anything... */