Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd02d4a6

Browse files
committed
Avoid premature free of pass-by-reference CALL arguments.
Prematurely freeing the EState used to evaluate CALL arguments led, in somecases, to passing dangling pointers to the procedure. This was masked intrivial cases because the argument pointers would point to Const nodes inthe original expression tree, and in some other cases because the resultvalue would end up in the standalone ExprContext rather than in memorybelonging to the EState --- but that wasn't exactly high qualityprogramming either, because the standalone ExprContext was neverexplicitly freed, breaking assorted API contracts.In addition, using a separate EState for each argument was just silly.So let's use just one EState, and one ExprContext, and make the latterbelong to the former rather than be standalone, and clean up the EState(and hence the ExprContext) post-call.While at it, improve the function's commentary a bit.Discussion:https://postgr.es/m/29173.1518282748@sss.pgh.pa.us
1 parent65b1d76 commitd02d4a6

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

‎src/backend/commands/functioncmds.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,6 +2204,12 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
22042204
* transaction commands based on that information, e.g., call
22052205
* SPI_connect_ext(SPI_OPT_NONATOMIC). The language should also pass on the
22062206
* atomic flag to any nested invocations to CALL.
2207+
*
2208+
* The expression data structures and execution context that we create
2209+
* within this function are children of the portalContext of the Portal
2210+
* that the CALL utility statement runs in. Therefore, any pass-by-ref
2211+
* values that we're passing to the procedure will survive transaction
2212+
* commits that might occur inside the procedure.
22072213
*/
22082214
void
22092215
ExecuteCallStmt(ParseState*pstate,CallStmt*stmt,boolatomic)
@@ -2218,8 +2224,11 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)
22182224
FmgrInfoflinfo;
22192225
FunctionCallInfoDatafcinfo;
22202226
CallContext*callcontext;
2227+
EState*estate;
2228+
ExprContext*econtext;
22212229
HeapTupletp;
22222230

2231+
/* We need to do parse analysis on the procedure call and its arguments */
22232232
targs=NIL;
22242233
foreach(lc,stmt->funccall->args)
22252234
{
@@ -2241,7 +2250,6 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)
22412250
aclresult=pg_proc_aclcheck(fexpr->funcid,GetUserId(),ACL_EXECUTE);
22422251
if (aclresult!=ACLCHECK_OK)
22432252
aclcheck_error(aclresult,OBJECT_PROCEDURE,get_func_name(fexpr->funcid));
2244-
InvokeFunctionExecuteHook(fexpr->funcid);
22452253

22462254
nargs=list_length(fexpr->args);
22472255

@@ -2254,6 +2262,7 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)
22542262
FUNC_MAX_ARGS,
22552263
FUNC_MAX_ARGS)));
22562264

2265+
/* Prep the context object we'll pass to the procedure */
22572266
callcontext=makeNode(CallContext);
22582267
callcontext->atomic=atomic;
22592268

@@ -2270,23 +2279,28 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)
22702279
callcontext->atomic= true;
22712280
ReleaseSysCache(tp);
22722281

2282+
/* Initialize function call structure */
2283+
InvokeFunctionExecuteHook(fexpr->funcid);
22732284
fmgr_info(fexpr->funcid,&flinfo);
22742285
InitFunctionCallInfoData(fcinfo,&flinfo,nargs,fexpr->inputcollid, (Node*)callcontext,NULL);
22752286

2287+
/*
2288+
* Evaluate procedure arguments inside a suitable execution context. Note
2289+
* we can't free this context till the procedure returns.
2290+
*/
2291+
estate=CreateExecutorState();
2292+
econtext=CreateExprContext(estate);
2293+
22762294
i=0;
22772295
foreach(lc,fexpr->args)
22782296
{
2279-
EState*estate;
22802297
ExprState*exprstate;
2281-
ExprContext*econtext;
22822298
Datumval;
22832299
boolisnull;
22842300

2285-
estate=CreateExecutorState();
22862301
exprstate=ExecPrepareExpr(lfirst(lc),estate);
2287-
econtext=CreateStandaloneExprContext();
2302+
22882303
val=ExecEvalExprSwitchContext(exprstate,econtext,&isnull);
2289-
FreeExecutorState(estate);
22902304

22912305
fcinfo.arg[i]=val;
22922306
fcinfo.argnull[i]=isnull;
@@ -2295,4 +2309,6 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)
22952309
}
22962310

22972311
FunctionCallInvoke(&fcinfo);
2312+
2313+
FreeExecutorState(estate);
22982314
}

‎src/test/regress/expected/create_procedure.out

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,22 @@ LINE 1: SELECT ptest1('x');
2121
^
2222
HINT: To call a procedure, use CALL.
2323
CALL ptest1('a'); -- ok
24+
CALL ptest1('xy' || 'zzy'); -- ok, constant-folded arg
25+
CALL ptest1(substring(random()::text, 1, 1)); -- ok, volatile arg
2426
\df ptest1
2527
List of functions
2628
Schema | Name | Result data type | Argument data types | Type
2729
--------+--------+------------------+---------------------+------
2830
public | ptest1 | | x text | proc
2931
(1 row)
3032

31-
SELECT * FROM cp_test ORDER BY a;
32-
a | b
33-
---+---
33+
SELECT * FROM cp_test ORDER BY b COLLATE "C";
34+
a | b
35+
---+-------
36+
1 | 0
3437
1 | a
35-
(1 row)
38+
1 | xyzzy
39+
(3 rows)
3640

3741
CREATE PROCEDURE ptest2()
3842
LANGUAGE SQL

‎src/test/regress/sql/create_procedure.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ $$;
1313

1414
SELECT ptest1('x');-- error
1515
CALL ptest1('a');-- ok
16+
CALL ptest1('xy'||'zzy');-- ok, constant-folded arg
17+
CALL ptest1(substring(random()::text,1,1));-- ok, volatile arg
1618

1719
\df ptest1
1820

19-
SELECT*FROM cp_testORDER BYa;
21+
SELECT*FROM cp_testORDER BYb COLLATE"C";
2022

2123

2224
CREATE PROCEDURE ptest2()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp