]> granicus.if.org Git - postgresql/commitdiff
Further patch rangetypes_selfuncs.c's statistics slot management.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 May 2017 19:02:58 +0000 (15:02 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 May 2017 19:02:58 +0000 (15:02 -0400)
Values in a STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM slot are float8,
not of the type of the column the statistics are for.

This bug is at least partly the fault of sloppy specification comments
for get_attstatsslot()/free_attstatsslot(): the type OID they want is that
of the stavalues entries, not of the underlying column.  (I double-checked
other callers and they seem to get this right.)  Adjust the comments to be
more correct.

Per buildfarm.

Security: CVE-2017-7484

src/backend/utils/adt/rangetypes_selfuncs.c
src/backend/utils/cache/lsyscache.c
src/include/catalog/pg_statistic.h

index 89d421e8432651df11f3f3e22ddd0408349abc9b..9be8502f2d1dd46ccb738f95a652b63099e8d8dd 100644 (file)
@@ -20,6 +20,7 @@
 #include "access/htup_details.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_statistic.h"
+#include "catalog/pg_type.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/rangetypes.h"
@@ -246,8 +247,9 @@ calc_rangesel(TypeCacheEntry *typcache, VariableStatData *vardata,
 
                /* Try to get fraction of empty ranges */
                if (get_attstatsslot(vardata->statsTuple,
-                                                        vardata->atttype, vardata->atttypmod,
-                                                  STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM, InvalidOid,
+                                                        FLOAT8OID, -1,
+                                                        STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM,
+                                                        InvalidOid,
                                                         NULL,
                                                         NULL, NULL,
                                                         &numbers, &nnumbers))
@@ -255,7 +257,7 @@ calc_rangesel(TypeCacheEntry *typcache, VariableStatData *vardata,
                        if (nnumbers != 1)
                                elog(ERROR, "invalid empty fraction statistic");                /* shouldn't happen */
                        empty_frac = numbers[0];
-                       free_attstatsslot(vardata->atttype, NULL, 0, numbers, nnumbers);
+                       free_attstatsslot(FLOAT8OID, NULL, 0, numbers, nnumbers);
                }
                else
                {
@@ -424,7 +426,7 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
        {
                if (!(HeapTupleIsValid(vardata->statsTuple) &&
                          get_attstatsslot(vardata->statsTuple,
-                                                          vardata->atttype, vardata->atttypmod,
+                                                          FLOAT8OID, -1,
                                                           STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM,
                                                           InvalidOid,
                                                           NULL,
@@ -438,7 +440,7 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
                /* check that it's a histogram, not just a dummy entry */
                if (length_nhist < 2)
                {
-                       free_attstatsslot(vardata->atttype,
+                       free_attstatsslot(FLOAT8OID,
                                                          length_hist_values, length_nhist, NULL, 0);
                        free_attstatsslot(vardata->atttype, hist_values, nhist, NULL, 0);
                        return -1.0;
@@ -578,7 +580,7 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
                        break;
        }
 
-       free_attstatsslot(vardata->atttype,
+       free_attstatsslot(FLOAT8OID,
                                          length_hist_values, length_nhist, NULL, 0);
        free_attstatsslot(vardata->atttype, hist_values, nhist, NULL, 0);
 
index 0b45fcb4943c3b25ec63d6ef3b35a14d5e3871e8..64fbb3947cc8e8412b270d640d70c924be410ba2 100644 (file)
@@ -2711,9 +2711,9 @@ get_attavgwidth(Oid relid, AttrNumber attnum)
  * that have been provided by a stats hook and didn't really come from
  * pg_statistic.
  *
- * statstuple: pg_statistics tuple to be examined.
- * atttype: type OID of attribute (can be InvalidOid if values == NULL).
- * atttypmod: typmod of attribute (can be 0 if values == NULL).
+ * statstuple: pg_statistic tuple to be examined.
+ * atttype: type OID of slot's stavalues (can be InvalidOid if values == NULL).
+ * atttypmod: typmod of slot's stavalues (can be 0 if values == NULL).
  * reqkind: STAKIND code for desired statistics slot kind.
  * reqop: STAOP value wanted, or InvalidOid if don't care.
  * actualop: if not NULL, *actualop receives the actual STAOP value.
@@ -2721,7 +2721,7 @@ get_attavgwidth(Oid relid, AttrNumber attnum)
  * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
  *
  * If assigned, values and numbers are set to point to palloc'd arrays.
- * If the attribute type is pass-by-reference, the values referenced by
+ * If the stavalues datatype is pass-by-reference, the values referenced by
  * the values array are themselves palloc'd.  The palloc'd stuff can be
  * freed by calling free_attstatsslot.
  *
@@ -2851,7 +2851,8 @@ get_attstatsslot(HeapTuple statstuple,
  * free_attstatsslot
  *             Free data allocated by get_attstatsslot
  *
- * atttype need be valid only if values != NULL.
+ * atttype is the type of the individual values in values[].
+ * It need be valid only if values != NULL.
  */
 void
 free_attstatsslot(Oid atttype,
index 85681ca194cacf76a1170321f4171035fe190dd8..8184b4b0b7c956c0702525d509c7e1c1437534e3 100644 (file)
@@ -275,7 +275,7 @@ typedef FormData_pg_statistic *Form_pg_statistic;
  * fraction of empty ranges. stavalues is a histogram of non-empty lengths, in
  * a format similar to STATISTIC_KIND_HISTOGRAM: it contains M (>=2) range
  * values that divide the column data values into M-1 bins of approximately
- * equal population. The lengths are stores as float8s, as measured by the
+ * equal population. The lengths are stored as float8s, as measured by the
  * range type's subdiff function. Only non-null rows are considered.
  */
 #define STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM  6