postgres.git / summary / log / commit / refs

commit    d358da81414abc57ef44dfd45dfedc3d443e5bd5
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Sun Nov 04 19:50:55 2018 +0000
First released in: 12.0, 11.1

    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 80ad3c770a3..1802cacbc9b 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; [parent: 4b0c3712c530]