Commit 9b6fb9fb authored by Tom Lane's avatar Tom Lane

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
parent 15c72934
...@@ -2225,6 +2225,7 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver ...@@ -2225,6 +2225,7 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
fexpr = stmt->funcexpr; fexpr = stmt->funcexpr;
Assert(fexpr); Assert(fexpr);
Assert(IsA(fexpr, FuncExpr));
aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE); aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
...@@ -2253,13 +2254,25 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver ...@@ -2253,13 +2254,25 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
* and AbortTransaction() resets the security context. This could be * and AbortTransaction() resets the security context. This could be
* reorganized, but right now it doesn't work. * 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; 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); nargs = list_length(fexpr->args);
ReleaseSysCache(tp); ReleaseSysCache(tp);
...@@ -2362,8 +2375,8 @@ TupleDesc ...@@ -2362,8 +2375,8 @@ TupleDesc
CallStmtResultDesc(CallStmt *stmt) CallStmtResultDesc(CallStmt *stmt)
{ {
FuncExpr *fexpr; FuncExpr *fexpr;
HeapTuple tuple; HeapTuple tuple;
TupleDesc tupdesc; TupleDesc tupdesc;
fexpr = stmt->funcexpr; fexpr = stmt->funcexpr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment