summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-01-02 16:33:48 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2019-01-02 16:33:48 -0500
commitc27c3993ef6dbdff1f196670877a47f374d884ad (patch)
tree4eadc52b3a4fb7a391244c80f5b4d527214cb101
parentb66a07430e9d17ad892c5e3241c19b1b33d73e46 (diff)
downloadpostgresql-c27c3993ef6dbdff1f196670877a47f374d884ad.tar.gz
Don't believe MinMaxExpr is leakproof without checking.
MinMaxExpr invokes the btree comparison function for its input datatype, so it's only leakproof if that function is. Many such functions are indeed leakproof, but others are not, and we should not just assume that they are. Hence, adjust contain_leaked_vars to verify the leakproofness of the referenced function explicitly. I didn't add a regression test because it would need to depend on some particular comparison function being leaky, and that's a moving target, per discussion. This has been wrong all along, so back-patch to supported branches. Discussion: https://postgr.es/m/31042.1546194242@sss.pgh.pa.us
-rw-r--r--src/backend/optimizer/util/clauses.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 9f2ead73cb..fa49b1c525 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -1481,7 +1481,6 @@ contain_leaked_vars_walker(Node *node, void *context)
case T_CaseExpr:
case T_CaseTestExpr:
case T_RowExpr:
- case T_MinMaxExpr:
case T_NullTest:
case T_BooleanTest:
case T_List:
@@ -1536,6 +1535,36 @@ contain_leaked_vars_walker(Node *node, void *context)
}
break;
+ case T_MinMaxExpr:
+ {
+ /*
+ * MinMaxExpr is leakproof if the comparison function it calls
+ * is leakproof.
+ */
+ MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
+ TypeCacheEntry *typentry;
+ bool leakproof;
+
+ /* Look up the btree comparison function for the datatype */
+ typentry = lookup_type_cache(minmaxexpr->minmaxtype,
+ TYPECACHE_CMP_PROC);
+ if (OidIsValid(typentry->cmp_proc))
+ leakproof = get_func_leakproof(typentry->cmp_proc);
+ else
+ {
+ /*
+ * The executor will throw an error, but here we just
+ * treat the missing function as leaky.
+ */
+ leakproof = false;
+ }
+
+ if (!leakproof &&
+ contain_var_clause((Node *) minmaxexpr->args))
+ return true;
+ }
+ break;
+
case T_CurrentOfExpr:
/*