Skip to content

Commit ef55e29

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 9350824 commit ef55e29

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.
@@ -4095,6 +4100,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
40954100
bool modifyTargetList;
40964101
MemoryContext oldcxt;
40974102
MemoryContext mycxt;
4103+
List *saveInvalItems;
40984104
inline_error_callback_arg callback_arg;
40994105
ErrorContextCallback sqlerrcontext;
41004106
List *raw_parsetree_list;
@@ -4181,6 +4187,16 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
41814187
ALLOCSET_DEFAULT_MAXSIZE);
41824188
oldcxt = MemoryContextSwitchTo(mycxt);
41834189

4190+
/*
4191+
* When we call eval_const_expressions below, it might try to add items
4192+
* to root->glob->invalItems. Since it is running in the temp context,
4193+
* those items will be in that context, and will need to be copied out
4194+
* if we're successful. Temporarily reset the list so that we can keep
4195+
* those items separate from the pre-existing list contents.
4196+
*/
4197+
saveInvalItems = root->glob->invalItems;
4198+
root->glob->invalItems = NIL;
4199+
41844200
/* Fetch the function body */
41854201
tmp = SysCacheGetAttr(PROCOID,
41864202
func_tuple,
@@ -4307,6 +4323,10 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
43074323

43084324
querytree = copyObject(querytree);
43094325

4326+
/* copy up any new invalItems, too */
4327+
root->glob->invalItems = list_concat(saveInvalItems,
4328+
copyObject(root->glob->invalItems));
4329+
43104330
MemoryContextDelete(mycxt);
43114331
error_context_stack = sqlerrcontext.previous;
43124332
ReleaseSysCache(func_tuple);
@@ -4322,6 +4342,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
43224342
/* Here if func is not inlinable: release temp memory and return NULL */
43234343
fail:
43244344
MemoryContextSwitchTo(oldcxt);
4345+
root->glob->invalItems = saveInvalItems;
43254346
MemoryContextDelete(mycxt);
43264347
error_context_stack = sqlerrcontext.previous;
43274348
ReleaseSysCache(func_tuple);

0 commit comments

Comments
 (0)