]> granicus.if.org Git - postgresql/commitdiff
Add an Assert that enum_cmp_internal() gets passed an FmgrInfo pointer.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 24 Feb 2017 03:08:10 +0000 (22:08 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 24 Feb 2017 03:08:10 +0000 (22:08 -0500)
If someone were to try to call one of the enum comparison functions
using DirectFunctionCallN, it would very likely seem to work, because
only in unusual cases does enum_cmp_internal() need to access the
typcache.  But once such a case occurred, code like that would crash
with a null pointer dereference.  To make an oversight of that sort
less likely to escape detection, add a non-bypassable Assert that
fcinfo->flinfo isn't NULL.

Discussion: https://postgr.es/m/25226.1487900067@sss.pgh.pa.us

src/backend/utils/adt/enum.c

index 8110ee222c15dced9b78a781a06326e474d1b906..b1d2a6f0c3b79715a03b8396192de88125936b37 100644 (file)
@@ -263,6 +263,15 @@ enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
 {
        TypeCacheEntry *tcache;
 
+       /*
+        * We don't need the typcache except in the hopefully-uncommon case that
+        * one or both Oids are odd.  This means that cursory testing of code that
+        * fails to pass flinfo to an enum comparison function might not disclose
+        * the oversight.  To make such errors more obvious, Assert that we have a
+        * place to cache even when we take a fast-path exit.
+        */
+       Assert(fcinfo->flinfo != NULL);
+
        /* Equal OIDs are equal no matter what */
        if (arg1 == arg2)
                return 0;
@@ -381,12 +390,7 @@ enum_cmp(PG_FUNCTION_ARGS)
        Oid                     a = PG_GETARG_OID(0);
        Oid                     b = PG_GETARG_OID(1);
 
-       if (a == b)
-               PG_RETURN_INT32(0);
-       else if (enum_cmp_internal(a, b, fcinfo) > 0)
-               PG_RETURN_INT32(1);
-       else
-               PG_RETURN_INT32(-1);
+       PG_RETURN_INT32(enum_cmp_internal(a, b, fcinfo));
 }
 
 /* Enum programming support functions */