Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4ce6be4

Browse files
committed
Defend against crash while processing Describe Statement or Describe Portal
messages, when client attempts to execute these outside a transaction (startone) or in a failed transaction (reject message, except for COMMIT/ROLLBACKstatements which we can handle). Per report from Francisco Figueiredo Jr.
1 parent4262926 commit4ce6be4

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
lines changed

‎src/backend/commands/prepare.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.43 2005/11/29 01:25:49 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.44 2005/12/14 17:06:27 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -447,6 +447,30 @@ FetchPreparedStatementResultDesc(PreparedStatement *stmt)
447447
returnNULL;
448448
}
449449

450+
/*
451+
* Given a prepared statement, determine whether it will return tuples.
452+
*
453+
* Note: this is used rather than just testing the result of
454+
* FetchPreparedStatementResultDesc() because that routine can fail if
455+
* invoked in an aborted transaction. This one is safe to use in any
456+
* context. Be sure to keep the two routines in sync!
457+
*/
458+
bool
459+
PreparedStatementReturnsTuples(PreparedStatement*stmt)
460+
{
461+
switch (ChoosePortalStrategy(stmt->query_list))
462+
{
463+
casePORTAL_ONE_SELECT:
464+
casePORTAL_UTIL_SELECT:
465+
return true;
466+
467+
casePORTAL_MULTI_QUERY:
468+
/* will not return tuples */
469+
break;
470+
}
471+
return false;
472+
}
473+
450474
/*
451475
* Given a prepared statement that returns tuples, extract the query
452476
* targetlist.Returns NIL if the statement doesn't have a determinable

‎src/backend/tcop/postgres.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.470 2005/11/22 18:17:21 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.471 2005/12/1417:06:27 tgl Exp $
1212
*
1313
* NOTES
1414
* this is the "main" module of the postgres backend and
@@ -1849,6 +1849,15 @@ exec_describe_statement_message(const char *stmt_name)
18491849
ListCell*l;
18501850
StringInfoDatabuf;
18511851

1852+
/*
1853+
* Start up a transaction command. (Note that this will normally change
1854+
* current memory context.) Nothing happens if we are already in one.
1855+
*/
1856+
start_xact_command();
1857+
1858+
/* Switch back to message context */
1859+
MemoryContextSwitchTo(MessageContext);
1860+
18521861
/* Find prepared statement */
18531862
if (stmt_name[0]!='\0')
18541863
pstmt=FetchPreparedStatement(stmt_name, true);
@@ -1862,6 +1871,22 @@ exec_describe_statement_message(const char *stmt_name)
18621871
errmsg("unnamed prepared statement does not exist")));
18631872
}
18641873

1874+
/*
1875+
* If we are in aborted transaction state, we can't safely create a result
1876+
* tupledesc, because that needs catalog accesses. Hence, refuse to
1877+
* Describe statements that return data. (We shouldn't just refuse all
1878+
* Describes, since that might break the ability of some clients to issue
1879+
* COMMIT or ROLLBACK commands, if they use code that blindly Describes
1880+
* whatever it does.) We can Describe parameters without doing anything
1881+
* dangerous, so we don't restrict that.
1882+
*/
1883+
if (IsAbortedTransactionBlockState()&&
1884+
PreparedStatementReturnsTuples(pstmt))
1885+
ereport(ERROR,
1886+
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
1887+
errmsg("current transaction is aborted, "
1888+
"commands ignored until end of transaction block")));
1889+
18651890
if (whereToSendOutput!=DestRemote)
18661891
return;/* can't actually do anything... */
18671892

@@ -1902,12 +1927,36 @@ exec_describe_portal_message(const char *portal_name)
19021927
{
19031928
Portalportal;
19041929

1930+
/*
1931+
* Start up a transaction command. (Note that this will normally change
1932+
* current memory context.) Nothing happens if we are already in one.
1933+
*/
1934+
start_xact_command();
1935+
1936+
/* Switch back to message context */
1937+
MemoryContextSwitchTo(MessageContext);
1938+
19051939
portal=GetPortalByName(portal_name);
19061940
if (!PortalIsValid(portal))
19071941
ereport(ERROR,
19081942
(errcode(ERRCODE_UNDEFINED_CURSOR),
19091943
errmsg("portal \"%s\" does not exist",portal_name)));
19101944

1945+
/*
1946+
* If we are in aborted transaction state, we can't run
1947+
* SendRowDescriptionMessage(), because that needs catalog accesses.
1948+
* Hence, refuse to Describe portals that return data. (We shouldn't just
1949+
* refuse all Describes, since that might break the ability of some
1950+
* clients to issue COMMIT or ROLLBACK commands, if they use code that
1951+
* blindly Describes whatever it does.)
1952+
*/
1953+
if (IsAbortedTransactionBlockState()&&
1954+
portal->tupDesc)
1955+
ereport(ERROR,
1956+
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
1957+
errmsg("current transaction is aborted, "
1958+
"commands ignored until end of transaction block")));
1959+
19111960
if (whereToSendOutput!=DestRemote)
19121961
return;/* can't actually do anything... */
19131962

‎src/include/commands/prepare.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
88
*
9-
* $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.15 2005/11/29 01:25:50 tgl Exp $
9+
* $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.16 2005/12/14 17:06:28 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -60,6 +60,7 @@ extern PreparedStatement *FetchPreparedStatement(const char *stmt_name,
6060
externvoidDropPreparedStatement(constchar*stmt_name,boolshowError);
6161
externList*FetchPreparedStatementParams(constchar*stmt_name);
6262
externTupleDescFetchPreparedStatementResultDesc(PreparedStatement*stmt);
63+
externboolPreparedStatementReturnsTuples(PreparedStatement*stmt);
6364
externList*FetchPreparedStatementTargetList(PreparedStatement*stmt);
6465

6566
#endif/* PREPARE_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp