aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-06-16 19:30:17 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-06-16 19:30:17 -0400
commitd03a41d1c860ffc97bda40a3673698d4044f5c88 (patch)
treee326bd4cf7a35f4354e007ef818fe8ed39df6da2
parente89a8e30e0a50e7882ab5a6896a11872bec969e3 (diff)
downloadpostgresql-d03a41d1c860ffc97bda40a3673698d4044f5c88.tar.gz
postgresql-d03a41d1c860ffc97bda40a3673698d4044f5c88.zip
Fix plancache refcount leak after error in ExecuteQuery.
When stuffing a plan from the plancache into a Portal, one is not supposed to risk throwing an error between GetCachedPlan and PortalDefineQuery; if that happens, the plan refcount incremented by GetCachedPlan will be leaked. I managed to break this rule while refactoring code in 9dbf2b7d7. There is no visible consequence other than some memory leakage, and since nobody is very likely to trigger the relevant error conditions many times in a row, it's not surprising we haven't noticed. Nonetheless, it's a bug, so rearrange the order of operations to remove the hazard. Noted on the way to looking for a better fix for bug #17053. This mistake is pretty old, so back-patch to all supported branches.
-rw-r--r--src/backend/commands/prepare.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 80d6df8ac1e..e54cfc8ad88 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -234,6 +234,17 @@ ExecuteQuery(ParseState *pstate,
plan_list = cplan->stmt_list;
/*
+ * DO NOT add any logic that could possibly throw an error between
+ * GetCachedPlan and PortalDefineQuery, or you'll leak the plan refcount.
+ */
+ PortalDefineQuery(portal,
+ NULL,
+ query_string,
+ entry->plansource->commandTag,
+ plan_list,
+ cplan);
+
+ /*
* For CREATE TABLE ... AS EXECUTE, we must verify that the prepared
* statement is one that produces tuples. Currently we insist that it be
* a plain old SELECT. In future we might consider supporting other
@@ -276,13 +287,6 @@ ExecuteQuery(ParseState *pstate,
count = FETCH_ALL;
}
- PortalDefineQuery(portal,
- NULL,
- query_string,
- entry->plansource->commandTag,
- plan_list,
- cplan);
-
/*
* Run the portal as appropriate.
*/