diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-12-14 17:06:28 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-12-14 17:06:28 +0000 |
commit | 4ce6be4f5e1e4b0c89c5c8de179e3fa8216a7b54 (patch) | |
tree | aa97d6ee837e6fa5834da31defd3fd69f872b8fc /src/backend/tcop/postgres.c | |
parent | 426292663acb30bdd8381eae4058e8ffcbf12162 (diff) | |
download | postgresql-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.c | 51 |
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... */ |