From d358da81414abc57ef44dfd45dfedc3d443e5bd5 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 4 Nov 2018 14:50:55 -0500 Subject: [PATCH] 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 --- src/backend/commands/functioncmds.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 80ad3c770a..1802cacbc9 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; -- 2.40.0