Skip to content

Commit 113082c

Browse files
committed
Fix inline_set_returning_function() to preserve the invalItems list properly.
This avoids a possible crash when inlining a SRF whose argument list contains a reference to an inline-able user function. The crash is quite reproducible with CLOBBER_FREED_MEMORY enabled, but would be less certain in a production build. Problem introduced in 9.0 by the named-arguments patch, which requires invoking eval_const_expressions() before we can try to inline a SRF. Per report from Brendan Jurd.
1 parent ae9ac79 commit 113082c

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2018,11 +2018,16 @@ rowtype_field_matches(Oid rowtypeid, int fieldnum,
20182018
* will not be pre-evaluated here, although we will reduce their
20192019
* arguments as far as possible.
20202020
*
2021+
* Whenever a function is eliminated from the expression by means of
2022+
* constant-expression evaluation or inlining, we add the function to
2023+
* root->glob->invalItems. This ensures the plan is known to depend on
2024+
* such functions, even though they aren't referenced anymore.
2025+
*
20212026
* We assume that the tree has already been type-checked and contains
20222027
* only operators and functions that are reasonable to try to execute.
20232028
*
20242029
* NOTE: "root" can be passed as NULL if the caller never wants to do any
2025-
* Param substitutions.
2030+
* Param substitutions nor receive info about inlined functions.
20262031
*
20272032
* NOTE: the planner assumes that this will always flatten nested AND and
20282033
* OR clauses into N-argument form. See comments in prepqual.c.
@@ -4107,6 +4112,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
41074112
bool modifyTargetList;
41084113
MemoryContext oldcxt;
41094114
MemoryContext mycxt;
4115+
List *saveInvalItems;
41104116
inline_error_callback_arg callback_arg;
41114117
ErrorContextCallback sqlerrcontext;
41124118
List *raw_parsetree_list;
@@ -4193,6 +4199,16 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
41934199
ALLOCSET_DEFAULT_MAXSIZE);
41944200
oldcxt = MemoryContextSwitchTo(mycxt);
41954201

4202+
/*
4203+
* When we call eval_const_expressions below, it might try to add items
4204+
* to root->glob->invalItems. Since it is running in the temp context,
4205+
* those items will be in that context, and will need to be copied out
4206+
* if we're successful. Temporarily reset the list so that we can keep
4207+
* those items separate from the pre-existing list contents.
4208+
*/
4209+
saveInvalItems = root->glob->invalItems;
4210+
root->glob->invalItems = NIL;
4211+
41964212
/* Fetch the function body */
41974213
tmp = SysCacheGetAttr(PROCOID,
41984214
func_tuple,
@@ -4319,6 +4335,10 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
43194335

43204336
querytree = copyObject(querytree);
43214337

4338+
/* copy up any new invalItems, too */
4339+
root->glob->invalItems = list_concat(saveInvalItems,
4340+
copyObject(root->glob->invalItems));
4341+
43224342
MemoryContextDelete(mycxt);
43234343
error_context_stack = sqlerrcontext.previous;
43244344
ReleaseSysCache(func_tuple);
@@ -4334,6 +4354,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
43344354
/* Here if func is not inlinable: release temp memory and return NULL */
43354355
fail:
43364356
MemoryContextSwitchTo(oldcxt);
4357+
root->glob->invalItems = saveInvalItems;
43374358
MemoryContextDelete(mycxt);
43384359
error_context_stack = sqlerrcontext.previous;
43394360
ReleaseSysCache(func_tuple);

0 commit comments

Comments
 (0)