]> granicus.if.org Git - postgresql/commitdiff
Don't believe MinMaxExpr is leakproof without checking.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 Jan 2019 21:33:48 +0000 (16:33 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 Jan 2019 21:33:48 +0000 (16:33 -0500)
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

src/backend/optimizer/util/clauses.c

index 9f2ead73cb54ba43ac7b19fc70191a99d61ac35b..fa49b1c525be7a31c546f040ddec51b63d8f137d 100644 (file)
@@ -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:
 
                        /*