aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/functioncmds.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-11-04 14:50:55 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2018-11-04 14:50:55 -0500
commit9b6fb9fbb48dda828dcca47adc418632ddb36202 (patch)
tree2d9a3c02251e927681327102a5b0a38e6d45444d /src/backend/commands/functioncmds.c
parent15c7293477a6de03234f58898da7fb29f3ab5b94 (diff)
downloadpostgresql-9b6fb9fbb48dda828dcca47adc418632ddb36202.tar.gz
postgresql-9b6fb9fbb48dda828dcca47adc418632ddb36202.zip
Fix ExecuteCallStmt to not scribble on the passed-in parse tree.
Modifying the parse tree at execution time is, or at least ought to be, verboten. It seems quite difficult to actually cause a crash this way in v11 (although you can exhibit it pretty easily in HEAD by messing with plan_cache_mode). Nonetheless, it's risky, so fix and back-patch. Discussion: https://postgr.es/m/13789.1541359611@sss.pgh.pa.us
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r--src/backend/commands/functioncmds.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 3fd73a69f04..3925fb83a54 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -2225,6 +2225,7 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
fexpr = stmt->funcexpr;
Assert(fexpr);
+ Assert(IsA(fexpr, FuncExpr));
aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
@@ -2253,13 +2254,25 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
* and AbortTransaction() resets the security context. This could be
* reorganized, but right now it doesn't work.
*/
- if (((Form_pg_proc )GETSTRUCT(tp))->prosecdef)
+ if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
callcontext->atomic = true;
/*
- * Expand named arguments, defaults, etc.
+ * Expand named arguments, defaults, etc. We do not want to scribble on
+ * the passed-in CallStmt parse tree, so first flat-copy fexpr, allowing
+ * us to replace its args field. (Note that expand_function_arguments
+ * will not modify any of the passed-in data structure.)
*/
- fexpr->args = expand_function_arguments(fexpr->args, fexpr->funcresulttype, tp);
+ {
+ FuncExpr *nexpr = makeNode(FuncExpr);
+
+ memcpy(nexpr, fexpr, sizeof(FuncExpr));
+ fexpr = nexpr;
+ }
+
+ fexpr->args = expand_function_arguments(fexpr->args,
+ fexpr->funcresulttype,
+ tp);
nargs = list_length(fexpr->args);
ReleaseSysCache(tp);
@@ -2362,8 +2375,8 @@ TupleDesc
CallStmtResultDesc(CallStmt *stmt)
{
FuncExpr *fexpr;
- HeapTuple tuple;
- TupleDesc tupdesc;
+ HeapTuple tuple;
+ TupleDesc tupdesc;
fexpr = stmt->funcexpr;