diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2018-11-04 14:50:55 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2018-11-04 14:50:55 -0500 |
commit | 9b6fb9fbb48dda828dcca47adc418632ddb36202 (patch) | |
tree | 2d9a3c02251e927681327102a5b0a38e6d45444d /src/backend/commands/functioncmds.c | |
parent | 15c7293477a6de03234f58898da7fb29f3ab5b94 (diff) | |
download | postgresql-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.c | 23 |
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; |