summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2022-11-03 16:01:57 +0000
committerTom Lane2022-11-03 16:01:57 +0000
commit5f3cec77b1b5d79100b127d0555a3e3d42e464da (patch)
treeed70005ece3c95b07a41ccab53dee42db4d8386b
parent19cefebe71ea2a2dca12c01f607375637fa7ea28 (diff)
Avoid crash after function syntax error in a replication worker.
If a syntax error occurred in a SQL-language or PL/pgSQL-language CREATE FUNCTION or DO command executed in a logical replication worker, we'd suffer a null pointer dereference or assertion failure. That seems like a rather contrived case, but nonetheless worth fixing. The cause is that function_parse_error_transpose assumes it must be executing within the context of a Portal, but logical/worker.c doesn't create a Portal since it's not running the standard executor. We can just back off the hard Assert check and make it fail gracefully if there's not an ActivePortal. (I have a feeling that the aggressive check here was my fault originally, probably because I wasn't sure if the case would always hold and wanted to find out. Well, now we know.) The hazard seems to exist in all branches that have logical replication, so back-patch to v10. Maxim Orlov, Anton Melnikov, Masahiko Sawada, Tom Lane Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/backend/catalog/pg_proc.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index afe48293287..056524d9993 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -977,7 +977,6 @@ function_parse_error_transpose(const char *prosrc)
{
int origerrposition;
int newerrposition;
- const char *queryText;
/*
* Nothing to do unless we are dealing with a syntax error that has a
@@ -995,11 +994,22 @@ function_parse_error_transpose(const char *prosrc)
}
/* We can get the original query text from the active portal (hack...) */
- Assert(ActivePortal && ActivePortal->status == PORTAL_ACTIVE);
- queryText = ActivePortal->sourceText;
+ if (ActivePortal && ActivePortal->status == PORTAL_ACTIVE)
+ {
+ const char *queryText = ActivePortal->sourceText;
- /* Try to locate the prosrc in the original text */
- newerrposition = match_prosrc_to_query(prosrc, queryText, origerrposition);
+ /* Try to locate the prosrc in the original text */
+ newerrposition = match_prosrc_to_query(prosrc, queryText,
+ origerrposition);
+ }
+ else
+ {
+ /*
+ * Quietly give up if no ActivePortal. This is an unusual situation
+ * but it can happen in, e.g., logical replication workers.
+ */
+ newerrposition = -1;
+ }
if (newerrposition > 0)
{